• 物联网-手机远程控制家里的摄像头(2)


    在上一篇博客里面,使用了Python来发送、接收mail,但是实际测试中出现了一些不稳定的

    情况,而且Python和即将使用的opencv会不兼容,使用进程间通讯或者其他方法会让整个系统

    显得复杂而且可能不稳定,于是尝试用c或者C++实现邮件的发送和接收。

    首先考虑的是上网找一个邮件库,找到了VMime库,于是开始安装。在简单看了一下它的文档之后

    开始搭建它的环境,可惜要装的东西太多,搭建许久后放弃,而且它里面用了各种C++的特性,使用起来显得眼花缭乱

    而且整个库太完整了,显得不够精简。

    于是继续上github搜索邮件库,最后找到了两个邮件库:

    https://github.com/leolanchas/Simple-POP3-Client

    和 https://github.com/kenchowcn/smtp

    其中,Simple-POP3-Client里面带有SMTP功能,可惜不支持附件,但是里面

    的POP3功能可以跑,所以后续定制了一下。

    smtp这份代码拿到后很惊喜,可以发送附件,于是测试之后就觉得可以直接用了(将它当做一个函数)

    其中我设定的整个系统需求POP3的功能带有邮件检测,SMTP只要负责发邮件就可以了,所以进行了POP3的定制:

    其中这两个库都是c库,改成C++的形式也是很容易的(解除一些错误即可),不行的话就用extern C来解决。

    这里已经改好了POP3库,支持C++,其中里面主要分为两个文件:

    pop3.cpp  这里是核心功能,负责定期检测邮件,根据邮件主题来传送一个

    命令码给回调函数。

    #include "pop3.h"
    
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <ctype.h>
    
    
    #define error printf
    #define CRLF "x0dx0a.x0dx0a"
    #define CR   "x0dx0a"
    #define    SA      struct sockaddr
    #define    MAXLINE    8192
    #define POP3_PORT    110
    
    
    #define XIMAGE 100
    #define XVIDEO 101
    #define IMAGE  102
    
    
    
    
    
    
    
    
    
    int checkConn( char * inServer, int port )
    {
        //
        // Check that the username and password are valid
        // Display error message or that they have accessed correctly
        //
        int    sockfd;
        struct sockaddr_in servaddr;
    
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons( port );
        inet_pton(AF_INET, inServer, &servaddr.sin_addr);
    
        if ( !connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) ) return sockfd;
        else return -1;
    }
    
    
    
    ssize_t readline(int fd, void *vptr, size_t maxlen)
    {
        ssize_t    n, rc;
        char    c;
        char *ptr;
    
        ptr = (char *)vptr;
        for (n = 1; n < maxlen; n++) {
            if ( (rc = recv(fd, &c, 1, 0)) == 1) {
                *ptr++ = c;
                if (c == '
    ') break;
            } else if (rc == 0) {
                if (n == 1) return(0);    /* EOF, no data read */
                else break;        /* EOF, some data was read */
            } else return(-1);    /* error */
        }
    
        *ptr = 0;
        return(n);
    }
    
    ssize_t Readline(int fd, void *ptr, size_t maxlen)
    {
        ssize_t    n;
    
        if ( (n = readline(fd, ptr, maxlen)) == -1) error("readline error");
        return(n);
    }
    
    
    int checkUser( char * User, char * Pass, int sockfd)
    {
        char recvline[MAXLINE], cmdUser [ 60 ];
        bzero(cmdUser,60);
    
        strcat( cmdUser, "user " );
        strcat( cmdUser, User );
        strcat( cmdUser, "
    " );
    
        char cmdPass [ 60 ];
        bzero(cmdPass,60);
    
        strcat( cmdPass, "pass " );
        strcat( cmdPass, Pass );
        strcat( cmdPass, "
    " );
    
        if (Readline(sockfd, recvline, MAXLINE) == 0)
            error("checkUser: server terminated prematurely");
    
        send(sockfd, cmdUser, strlen(cmdUser),0);
    
        if (Readline(sockfd, recvline, MAXLINE) == 0)
            error("checkUser: server terminated prematurely");
    
        send(sockfd, cmdPass, strlen(cmdPass), 0 );
    
        if (Readline(sockfd, recvline, MAXLINE) == 0)
            error("checkUser: server terminated prematurely");
    
        if ( recvline[ 0 ] == '-' ) {
            fputs ( "
    Usuario o Contraseña incorrectos
    
    ", stdout );
            return 0;
        }
        return 1;
    }
    
    
    static char encode(unsigned char u)
    {
    
        if(u < 26)  return 'A'+u;
        if(u < 52)  return 'a'+(u-26);
        if(u < 62)  return '0'+(u-52);
        if(u == 62) return '+';
    
        return '/';
    
    }
    
    
    
    
    void reverse(char s[])
    {
        int i, j;
        char c;
    
        for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
            c = s[i];
            s[i] = s[j];
            s[j] = c;
        }
    }
    
    
    void itoa(int n, char s[])
    {
        int i, sign;
    
        if ((sign = n) < 0)  /* record sign */
            n = -n;          /* make n positive */
        i = 0;
        do {       /* generate digits in reverse order */
            s[i++] = n % 10 + '0';   /* get next digit */
        } while ((n /= 10) > 0);     /* delete it */
        if (sign < 0)
            s[i++] = '-';
        s[i] = '';
        reverse(s);
    }
    int getNumberOfRemoteMsgs( int sockfd )
    {
        char recvline[ MAXLINE ];
        bzero( recvline, MAXLINE );
        char cmd[ MAXLINE ];
        bzero( cmd, MAXLINE );
    
        strcat( cmd, "statx0dx0a" );
    
        send( sockfd, cmd, strlen( cmd ), 0 );
    
        if ( Readline( sockfd, recvline, MAXLINE ) == 0 )
            error("getNumberOfMsgs: terminated prematurely");
    
        int i = 0, j = 0;
    
        char number[ 6 ];
        bzero( number, 6 );
        //recvline example:  "+OK 6 146378
    
        while ( recvline[ i++ ] != ' ' );
    
        while ( recvline[ i ] != ' ' )
            number[ j++ ] = recvline[ i++ ];
    
        return atoi( number );
    }
    
    void parseRemoteHeaders(int sockfd, int *remote_command, int *delete_index)
    {
        const int NofMessages = getNumberOfRemoteMsgs( sockfd );
        if( ! NofMessages ) {
            printf( "
    	No new mail
    " );
            return;
        }
    
        char recvline[ MAXLINE ];
        bzero( recvline, MAXLINE );
        char cmd[ MAXLINE ];
        bzero( cmd, MAXLINE );
    
        char Subject[ MAXLINE ], Date[ MAXLINE ], From[ MAXLINE ];
        int index = 1;
        char number[ 6 ];
    
        int b = 1;
    
    
        while ( index != NofMessages + 1 ) {
    
    
            bzero( number, 6 );
            itoa( index, number );
            bzero( cmd, MAXLINE );
            strcat( cmd, "top " );
            strcat( cmd, number );
            strcat( cmd, " 0x0dx0a" );
    
            if ( b ) {
                send( sockfd, cmd, strlen( cmd ), 0 );
                b = 0;
            }
    
            if ( Readline( sockfd, recvline, MAXLINE ) == 0 )
                error("getHeaders: server terminated prematurely");
    
    
            if (NULL != strstr(recvline, "Subject:"))
                if (strncmp(recvline, "Subject:", strlen("Subject:")) == 0) {
                    printf("%s", recvline);
                    if (NULL != strstr(recvline, "ximage")) {
                        printf("will del:%s", recvline);
                        *remote_command = XIMAGE;
                        *delete_index = index;
                    } else     if (NULL != strstr(recvline, "xvideo")) {
                        printf("will del:%s", recvline);
                        *remote_command = XVIDEO;
                        *delete_index = index;
                    } else     if (NULL != strstr(recvline, "image")) {
                        printf("will del:%s", recvline);
                        *remote_command = IMAGE;
                        *delete_index = index;
                    }
    
    
            }
    
            if (recvline[0] == '.') {
                index++;
                b = 1;
            }
    
        }
    
    }
    
    
    
    int delFromServer( int sockfd, int option )
    {
        int N = getNumberOfRemoteMsgs( sockfd );
    
        if ( ! N ) {
            printf( "Warning: inbox is empty !!!" );
            return 0;
        }
    
        if ( N < option ) {
            printf( "There are just %d, Messages", N );
            return 0;
        }
    
        char cmd[ 15 ], number[ 6 ], recvline[ MAXLINE ];
        bzero( number, 6 );
        bzero( cmd, 15 );
        bzero( recvline, MAXLINE );
        itoa( option, number );
        strcat( cmd, "dele " );
        strcat( cmd, number );
        strcat( cmd, CR );
    
        send( sockfd, cmd, strlen( cmd ), 0 );
    
        if ( Readline( sockfd, recvline, MAXLINE ) == 0 )
            error("delFromServer: terminated prematurely");
    
        if ( recvline[ 0 ] == '+' )
            printf ( "Message %d will be deleted when the session is ended
    ", option );
        else
            printf( "There have been errors when trying to delete the message" );
    
        return 1;
    }
    
    
    
    
    int pop3_main(void (*event_handler)(int))
    {
        printf( "Welcome to the pop3 client modified by tanhangbo
    
    " );
        struct hostent *h;
        int delete_index = 0;
        int remote_command = 0;
        char pop3_server[] = POP3_SERVER;
        char smtp_server[] = SMTP_SERVER;
        char user_name[] = USER_NAME;
        char pass_word[] = PASS_WORD;
    
    
        char  inServer[3*4 + 4 +1];//111.111.111.111
        char  outServer[3*4 + 4 + 1];
        h = gethostbyname(pop3_server);
        strcpy(inServer , inet_ntoa(*((struct in_addr *)h->h_addr)));
        h = gethostbyname(smtp_server);
        strcpy(outServer , inet_ntoa(*((struct in_addr *)h->h_addr)));
        printf("POP3 IP:%s
    ", inServer);
        printf("SMTP IP:%s
    ", outServer);
    
        while(1) {
    
            delete_index = 0;
            remote_command = 0;
    
    
            int sockfd = checkConn( inServer, POP3_PORT );
            if( sockfd == -1 )
                return 0;
            if(!checkUser(user_name, pass_word, sockfd)) {
                printf("login fail!
    ");
            }
    
    
            parseRemoteHeaders(sockfd, &remote_command, &delete_index);
            if (0 != remote_command)
                event_handler(remote_command);//handle here!!!!!!!
            if (0 != delete_index)
                delFromServer(sockfd, delete_index);
    
    
            send( sockfd, "QUITx0dx0a", strlen( "QUITx0dx0a" ), 0 );
            close(sockfd);
            sleep(1);
    
        }
    
    
        return 0;
    }

    main.cpp

    这是一个简单的sample:

    #include "stdio.h"
    #include "pop3.h"
    
    
    
    void handlee(int remote_command)
    {
        //process command here
        printf("I want to handle %d
    ", remote_command);
    }
    
    int main()
    {
        pop3_main(&handlee);
    }

    这样设计的目的是为了将其放到opencv相关的代码里面,同时这个回调函数

    会做一些相关的处理

    当然还有一个头文件:

    #ifndef POP3_TANHANGBO_H
    #define POP3_TANHANGBO_H
    
    
    
    #define POP3_SERVER "pop3.163.com"
    #define SMTP_SERVER "smtp.163.com"
    #define USER_NAME "user_"
    #define PASS_WORD "pass_"
    int pop3_main(void (*event_handler)(int));
    
    #endif

    测试的log:

    tan@tan-desktop:~/app/pop3$ g++ main.cpp pop3.cpp 
    tan@tan-desktop:~/app/pop3$ ./a.out 
    Welcome to the pop3 client modified by tanhangbo
    
    POP3 IP:123.125.50.29
    SMTP IP:123.58.178.203
    Subject: warning
    Subject: test
    Subject: warning
    Subject: test
    Subject: warning
    Subject: test
    Subject: warning
    Subject: test
    Subject: warning
    Subject: test
    Subject: warning
    Subject: test
    Subject: warning
    Subject: test
    Subject: warning
    Subject: test
    Subject: warning
    Subject: test
    Subject: image
    will del:Subject: image
    I want to handle 102
    Message 3 will be deleted when the session is ended
    Subject: warning
    Subject: test
    Subject: warning

    目前的进度是已经完成了Opencv的动作检测代码,接下来会将这个邮件

    功能和Opencv的代码连接起来,做一个稳定的基本功能,后续再进行功能的扩展。

    另外在找邮件库的时候找到了MailCore:  libmailcore.com

    后续如果做得比较完美,可以考虑做一个ios客户端,这样就更方便了。

  • 相关阅读:
    ArrayList 和 Vector 的区别
    Redis在springboot中使用,读取字符串
    初始化Mysql
    Redis 安装
    React-脚手架
    React virtual DOM explained in simple English/简单语言解释React的虚拟DOM
    数据结构
    书单(18-19)
    算法复杂度
    otrs离线部署
  • 原文地址:https://www.cnblogs.com/tanhangbo/p/4356126.html
Copyright © 2020-2023  润新知