在上一篇博客里面,使用了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] = '