物联网-手机远程控制家里的摄像头(2) - POP3和SMTP的C语言精简实现
在上一篇博客里面,使用了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语言精简实现的更多相关文章
- Remote Desktop安卓软件实现手机远程控制电脑
这篇文章写的是利用Remote Desktop安卓软件实现手机远程控制电脑. 电脑上的操作: 鼠标右击计算机>属性>远程设置>计算机名 如下图:
- POP3、SMTP、IMAP和Exchange都是个什么玩意?
很多时候一直对POP3.SMTP.IMAP和Exchange等迷迷糊糊的.下面就整理说明一下: 当前常用的电子邮件协议有SMTP.POP3.IMAP4,它们都隶属于TCP/IP协议簇,默认状态下,分别 ...
- 阿里云邮箱POP3、SMTP设置教程
3G免费网www.3gmfw.cn免费为你分享阿里云邮箱POP3.SMTP设置教程,阿里云邮箱 阿里云邮箱POP3设置 阿里云邮箱SMTP设置的相关资源如下: 什么是POP3.SMTP? 阿里云邮箱已 ...
- POP3、SMTP和IMAP介绍和设置
什么是POP3.SMTP和IMAP? 参照:http://help.163.com/09/1223/14/5R7P6CJ600753VB8.html 用于 Outlook 的 POP 和 IMAP 电 ...
- [Email] 收发邮件的协议 : IMAP and SMTP , POP3 and SMTP
支持 IMAP 和 SMTP 的应用 与仅同步收件箱的 POP 不同,IMAP 同步所有电子邮件文件夹. 在电子邮件应用中使用以下设置. 接收 (IMAP) 服务器 服务器地址:imap-mail.o ...
- 发送邮件程序报错454 Authentication failed以及POP3和SMTP简介
一.发现问题 在测试邮件发送程序的时候,发送给自己的QQ邮箱,程序报错454 Authentication failed, please open smtp flag first. 二.解决问题 进入 ...
- 常用电子邮件协议服务POP3/IMAP/SMTP/Exchange
标题: 常用电子邮件协议服务POP3/IMAP/SMTP/Exchange 作者: 梦幻之心星 347369787@QQ.com 标签: [电子邮件, 服务, 协议] 目录: [客户端] 日期: 20 ...
- 手机变为电脑的摄像头,使像素高清起来-使用DroidCam
你是不是已经在嫌弃电脑自带的摄像头的渣渣像素呢? 今天给大家安利一个方法:将手机摄像头设置为电脑的摄像头,让像素高清起来,对于搞图像的同志们真是福音啊,尤其是做人脸识别的时候. 方法有很多种,我推荐我 ...
- 使用微软Remote Desktop 手机远程控制 windows
在我的电脑上右击选择“属性”,打开属性面板.然后点击左边的“远程设置”. 2/2 如果你要操作的计算机出入外网(大多数是家里网线进线直连电脑),就选择远程桌面选择框中的“允许运行任意版本远程桌面的计算 ...
随机推荐
- Visual Studio发布Web项目报错:Unable to add 'xxx' to the Web site. Unable to add file 'xxx'. The specified file could not be encrypted.
背景 Visual Studio下的Web项目 现象 发布时遇到Unable to add 'xxx' to the Web site. Unable to add file 'xxx'. The ...
- Effective Java 71 Use lazy initialization judiciously
Lazy initialization - It decreases the cost of initializing a class or creating an instance, at the ...
- emacs24下使用jedi对python编程进行补全
在开始前先装好pip和virtualenv(见pip的安装一文),另需安装好make 1.emacs下安装: epc deferred.el auto-complete 使用M-x package-i ...
- Python Tomcat Script(多实例)
之前书写过 Tomcat 单实例的 Python 脚本,本次增加 Tomcat 多实例的操作脚本. 1:准备 安装所需 Python 插件 A方法: pip install argparse B方法: ...
- python lambda表达式简单用法
习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即: 1 2 3 4 5 6 7 8 # 普通条件语句 if 1 == 1: name = 'wupeiqi' else ...
- Loj 1003–Drunk(拓扑排序)
1003 - Drunk PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB One of my fr ...
- 手机号码js正则验证
手机号码js正则验证 var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/; if (!myreg.test($(" ...
- shell exit 0 exit 1
其实都一样,都是退出,只不过返回这个0和1是返回给操作系统的错误或者正确代码. exit 1 指的是脚本运行的返回值,用来指示成功或失败,以及失败的原因. exit 0 表示成功,exit 1表示失败 ...
- hadoop中NameNode、DataNode和Client三者之间协作关系及通信方式介绍
<ignore_js_op> 1)NameNode.DataNode和Client NameNode可以看作是分布式文件系统中的管理者,主要负责管理文件系统的命名空间.集群 ...
- Linux 系统常用命令汇总(二) vi 文本编辑
文本编辑 vi 命令 作用 +文件名 编辑文本文件,若文件不存在同时创建该文件 Ctrl+f 向后翻一页 Ctrl+b 向前翻一页 Ctrl+d 向后翻半页 Ctrl+u 向前翻半页 + 光标移动到下 ...