在上一篇博客里面,使用了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 "\x0d\x0a.\x0d\x0a"
#define CR "\x0d\x0a"
#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, ); 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 -;
} ssize_t readline(int fd, void *vptr, size_t maxlen)
{
ssize_t n, rc;
char c;
char *ptr; ptr = (char *)vptr;
for (n = ; n < maxlen; n++) {
if ( (rc = recv(fd, &c, , )) == ) {
*ptr++ = c;
if (c == '\n') break;
} else if (rc == ) {
if (n == ) return(); /* EOF, no data read */
else break; /* EOF, some data was read */
} else return(-); /* error */
} *ptr = ;
return(n);
} ssize_t Readline(int fd, void *ptr, size_t maxlen)
{
ssize_t n; if ( (n = readline(fd, ptr, maxlen)) == -) error("readline error");
return(n);
} int checkUser( char * User, char * Pass, int sockfd)
{
char recvline[MAXLINE], cmdUser [ ];
bzero(cmdUser,); strcat( cmdUser, "user " );
strcat( cmdUser, User );
strcat( cmdUser, "\n" ); char cmdPass [ ];
bzero(cmdPass,); strcat( cmdPass, "pass " );
strcat( cmdPass, Pass );
strcat( cmdPass, "\n" ); if (Readline(sockfd, recvline, MAXLINE) == )
error("checkUser: server terminated prematurely"); send(sockfd, cmdUser, strlen(cmdUser),); if (Readline(sockfd, recvline, MAXLINE) == )
error("checkUser: server terminated prematurely"); send(sockfd, cmdPass, strlen(cmdPass), ); if (Readline(sockfd, recvline, MAXLINE) == )
error("checkUser: server terminated prematurely"); if ( recvline[ ] == '-' ) {
fputs ( "\nUsuario o Contraseña incorrectos\n\n", stdout );
return ;
}
return ;
} static char encode(unsigned char u)
{ if(u < ) return 'A'+u;
if(u < ) return 'a'+(u-);
if(u < ) return ''+(u-);
if(u == ) return '+'; return '/'; } void reverse(char s[])
{
int i, j;
char c; for (i = , j = strlen(s)-; 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) < ) /* record sign */
n = -n; /* make n positive */
i = ;
do { /* generate digits in reverse order */
s[i++] = n % + ''; /* get next digit */
} while ((n /= ) > ); /* delete it */
if (sign < )
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
int getNumberOfRemoteMsgs( int sockfd )
{
char recvline[ MAXLINE ];
bzero( recvline, MAXLINE );
char cmd[ MAXLINE ];
bzero( cmd, MAXLINE ); strcat( cmd, "stat\x0d\x0a" ); send( sockfd, cmd, strlen( cmd ), ); if ( Readline( sockfd, recvline, MAXLINE ) == )
error("getNumberOfMsgs: terminated prematurely"); int i = , j = ; char number[ ];
bzero( number, );
//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( "\n\tNo new mail\n" );
return;
} char recvline[ MAXLINE ];
bzero( recvline, MAXLINE );
char cmd[ MAXLINE ];
bzero( cmd, MAXLINE ); char Subject[ MAXLINE ], Date[ MAXLINE ], From[ MAXLINE ];
int index = ;
char number[ ]; int b = ; while ( index != NofMessages + ) { bzero( number, );
itoa( index, number );
bzero( cmd, MAXLINE );
strcat( cmd, "top " );
strcat( cmd, number );
strcat( cmd, " 0\x0d\x0a" ); if ( b ) {
send( sockfd, cmd, strlen( cmd ), );
b = ;
} if ( Readline( sockfd, recvline, MAXLINE ) == )
error("getHeaders: server terminated prematurely"); if (NULL != strstr(recvline, "Subject:"))
if (strncmp(recvline, "Subject:", strlen("Subject:")) == ) {
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[] == '.') {
index++;
b = ;
} } } int delFromServer( int sockfd, int option )
{
int N = getNumberOfRemoteMsgs( sockfd ); if ( ! N ) {
printf( "Warning: inbox is empty !!!" );
return ;
} if ( N < option ) {
printf( "There are just %d, Messages", N );
return ;
} char cmd[ ], number[ ], recvline[ MAXLINE ];
bzero( number, );
bzero( cmd, );
bzero( recvline, MAXLINE );
itoa( option, number );
strcat( cmd, "dele " );
strcat( cmd, number );
strcat( cmd, CR ); send( sockfd, cmd, strlen( cmd ), ); if ( Readline( sockfd, recvline, MAXLINE ) == )
error("delFromServer: terminated prematurely"); if ( recvline[ ] == '+' )
printf ( "Message %d will be deleted when the session is ended\n", option );
else
printf( "There have been errors when trying to delete the message" ); return ;
} int pop3_main(void (*event_handler)(int))
{
printf( "Welcome to the pop3 client modified by tanhangbo\n\n" );
struct hostent *h;
int delete_index = ;
int remote_command = ;
char pop3_server[] = POP3_SERVER;
char smtp_server[] = SMTP_SERVER;
char user_name[] = USER_NAME;
char pass_word[] = PASS_WORD; char inServer[* + +];//111.111.111.111\0
char outServer[* + + ];
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\n", inServer);
printf("SMTP IP:%s\n", outServer); while() { delete_index = ;
remote_command = ; int sockfd = checkConn( inServer, POP3_PORT );
if( sockfd == - )
return ;
if(!checkUser(user_name, pass_word, sockfd)) {
printf("login fail!\n");
} parseRemoteHeaders(sockfd, &remote_command, &delete_index);
if ( != remote_command)
event_handler(remote_command);//handle here!!!!!!!
if ( != delete_index)
delFromServer(sockfd, delete_index); send( sockfd, "QUIT\x0d\x0a", strlen( "QUIT\x0d\x0a" ), );
close(sockfd);
sleep(); } return ;
}

main.cpp

这是一个简单的sample:

#include "stdio.h"
#include "pop3.h" void handlee(int remote_command)
{
//process command here
printf("I want to handle %d\n", 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
Message will be deleted when the session is ended
Subject: warning
Subject: test
Subject: warning

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

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

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

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

物联网-手机远程控制家里的摄像头(2) - POP3和SMTP的C语言精简实现的更多相关文章

  1. Remote Desktop安卓软件实现手机远程控制电脑

    这篇文章写的是利用Remote Desktop安卓软件实现手机远程控制电脑. 电脑上的操作: 鼠标右击计算机>属性>远程设置>计算机名 如下图:

  2. POP3、SMTP、IMAP和Exchange都是个什么玩意?

    很多时候一直对POP3.SMTP.IMAP和Exchange等迷迷糊糊的.下面就整理说明一下: 当前常用的电子邮件协议有SMTP.POP3.IMAP4,它们都隶属于TCP/IP协议簇,默认状态下,分别 ...

  3. 阿里云邮箱POP3、SMTP设置教程

    3G免费网www.3gmfw.cn免费为你分享阿里云邮箱POP3.SMTP设置教程,阿里云邮箱 阿里云邮箱POP3设置 阿里云邮箱SMTP设置的相关资源如下: 什么是POP3.SMTP? 阿里云邮箱已 ...

  4. POP3、SMTP和IMAP介绍和设置

    什么是POP3.SMTP和IMAP? 参照:http://help.163.com/09/1223/14/5R7P6CJ600753VB8.html 用于 Outlook 的 POP 和 IMAP 电 ...

  5. [Email] 收发邮件的协议 : IMAP and SMTP , POP3 and SMTP

    支持 IMAP 和 SMTP 的应用 与仅同步收件箱的 POP 不同,IMAP 同步所有电子邮件文件夹. 在电子邮件应用中使用以下设置. 接收 (IMAP) 服务器 服务器地址:imap-mail.o ...

  6. 发送邮件程序报错454 Authentication failed以及POP3和SMTP简介

    一.发现问题 在测试邮件发送程序的时候,发送给自己的QQ邮箱,程序报错454 Authentication failed, please open smtp flag first. 二.解决问题 进入 ...

  7. 常用电子邮件协议服务POP3/IMAP/SMTP/Exchange

    标题: 常用电子邮件协议服务POP3/IMAP/SMTP/Exchange 作者: 梦幻之心星 347369787@QQ.com 标签: [电子邮件, 服务, 协议] 目录: [客户端] 日期: 20 ...

  8. 手机变为电脑的摄像头,使像素高清起来-使用DroidCam

    你是不是已经在嫌弃电脑自带的摄像头的渣渣像素呢? 今天给大家安利一个方法:将手机摄像头设置为电脑的摄像头,让像素高清起来,对于搞图像的同志们真是福音啊,尤其是做人脸识别的时候. 方法有很多种,我推荐我 ...

  9. 使用微软Remote Desktop 手机远程控制 windows

    在我的电脑上右击选择“属性”,打开属性面板.然后点击左边的“远程设置”. 2/2 如果你要操作的计算机出入外网(大多数是家里网线进线直连电脑),就选择远程桌面选择框中的“允许运行任意版本远程桌面的计算 ...

随机推荐

  1. 关于JAVA中的static方法、并发问题以及JAVA运行时内存模型

    一.前言 最近在工作上用到了一个静态方法,跟同事交流的时候,被一个问题给问倒了,只怪基础不扎实... 问题大致是这样的,“在多线程环境下,静态方法中的局部变量会不会被其它线程给污染掉?”: 我当时的想 ...

  2. 内部类--毕向东Java基础教程学习笔记

    内部类的访问规则 1. 内部类可以直接访问外部类的成员,包括私有. 之所以可以直接访问外部类的成员,是因为内部类中持有外部类的引用,格式:外部类名.this 2.外部类要访问内部类,必须建立内部类对象 ...

  3. hibernate集合类型映射

    Set无序 元素不可重复 List有序 元素可重复 Bag无序 元素可重复 Map键值对 Student: package model; import java.util.Set; public cl ...

  4. 详解xml文件描述,读取方法以及将对象存放到xml文档中,并按照指定的特征寻找的方案

    主要的几个功能: 1.完成多条Emp信息的XML描述2.读取XML文档解析Emp信息3.将Emp(存放在List中)对象转换为XML文档4.在XML文档中查找指定特征的Emp信息 dom4j,jaxe ...

  5. Android ANR分析

    1.发生anr时手机会生产traces文件 拉取trace文件:adb pull data/anr/traces.txt ./mytraces.txt 保存路径 参考

  6. (转)c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考

    昨天去面试一家公司,面试题中有一个题,自己没弄清楚,先记录如下: class D { public: void printA() { cout<<"printA"< ...

  7. SSH 无密码访问其它机器 和 Windows 上 putty 无密码访问 Linux 机器

    1. 从一台 Linux 机器(ubuntu1)上无密码访问其它机器(ubuntu2) (1)登录 ubuntu1 并切换到用户比如 s1 (2)运行 ssh-keygen -t rsa (3)运行c ...

  8. [转]WCDMA系统结构及关键技术

    本文转自:http://blog.csdn.net/lele52141/article/details/8498951 WCDMA系统结构: CN指核心网,UTRAN接入网,UE用户设备. UTRAN ...

  9. java使用HttpURLConnection和HttpClient分别模拟get和post请求以及操作cookies

    1.使用HttpURLConnection public static String getJsonByURL(String base_url) { String url = base_url; St ...

  10. SQL Server 2005 安装图解教程(Windows)

    因工作需要,好久未安装SQL Server2005,今天安装了一下,特此写下安装步骤留下笔记. 安装前准备: 先安装IIS,再安装SQL Server2005 一.安装 点击安装,如下图: 选择操作系 ...