物联网-手机远程控制家里的摄像头(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 如果你要操作的计算机出入外网(大多数是家里网线进线直连电脑),就选择远程桌面选择框中的“允许运行任意版本远程桌面的计算 ...
随机推荐
- JDK自带工具一览表。妈妈再也不用担心你到处去下载小软件了~~
原来JDK早早就给我准备好了要用到的工具..反编译,JVM性能监视.诊断. JDK(Java Development Kit)是Java程序员最核心的开发工具,没有之一. JDK是一个功能强大的Jav ...
- jQuery Form 表单提交插件-----formSerialize,fieldSerialize,fieldValue,resetForm,clearForm,clearFields的 应用
一.jQuery Form的其他api 1. formSerialize 将表单序列化成查询串.这个方法将返回一个形如: name1=value1&name2=value2的字符串.是否可 ...
- 重载 && 重载递增递和减运算符
class Rule { private: double m_Length; public: explicit Rule(double lg = 1.0) :m_Length{ lg }{} Rule ...
- Swift 学习笔记 enum 枚举类型
异端,异端啊,我感觉这是map吧? enum ATMStatus { case Success(Int) case Error(String) } func withdraw(amount: Int) ...
- HTML5与触摸界面
习惯了开发典型的面向电脑端浏览器的网站在开发手机端网站或者移动App的时候面对很多新的问题,这些新的问题,在我看来或多或少会给浏览者在使用网站或App的时候带来不好的用户体验,对于一个产品级应用,用户 ...
- 搭建docker私有仓库,建立k8s集群
服务器IP角色分布 192.168.5.2 etcd server 192.168.5.2 kubernetes master 192.168.5.3 kubernetes node 192.168. ...
- 关于volatile和synchronized
这个可能是最好的对比volatile和synchronized作用的文章了.volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符.所以我们使用这两种关键字来指定三种简单的 ...
- Spring 一二事(2)
静态工厂方法及实例工厂的使用: applicationContext.xml: <!-- factory-method 是指调用静态工厂方法 --> <bean id="h ...
- 第20章 DLL高级技术(3)
20.4 函数转发器 (1)函数转发器原理(下图是利用Dependency Walker打开Kernel32.dll得到) ①图中CloseThreadpool*等4个函数转发到NTDLL中相应的函数 ...
- Unity-WIKI 之 DebugLine
脚本功能 在Unity中要使用画线功能,需要添加LineRenderer 组件,或打开Gizmos功能,下面这个组件为开发带来了方便 功能预览 搭建步骤 1.创建“Plugins” 文件夹 2.在“P ...