以前以为协议非常高神,但做了这个之后发现还好,没想象的那么艰难。
先要了解邮件的原理
再者就是上面2协议
可以先用telnet测试一下,以初步了解那2协议:http://hi.baidu.com/343243581/item/113c7212ced7e0e05e53b1d8
实现大致思想,SMTP,POP3相关介绍:http://www.doc88.com/p-929298657611.html
主要人家都讲得很好很详细了,天冷,我也懒得打字了。
/*这里面放一些公共的头文件*/ #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> //字节序转换函数 #include <netdb.h> //地址查询 extern int BUFFMAX; extern void recvCntInfo(int cnt,char thisBuff[]);
#include <stdio.h> /*下面定义常量*/ const int BUFFMAX=2000; //接受消息缓冲区大小 /*处理的函数*/ void recvCntInfo(int cnt,char thisBuff[]) { if(cnt==-1) { printf("recv出错,退出程序!\n"); exit(0); } else if(cnt==0) { printf("无可用消息或对方已经按序结束!\n"); } else { thisBuff[cnt]=‘\0‘; printf("发回:%s\n",thisBuff); } }
#include "myHead.h" static const char* SEND_DES="smtp.163.com"; //访问163邮箱 static const int SEND_PORT=25; //smtp的端口号 /*下面定义邮箱命令的标号*/ static const int HELO=0; static const int AUTHLOGIN=1; static const int USERNAME=2; static const int PASSWORD=3; static const int MAILFROM=4; static const int RCPTTO=5; static const int DATA=6; static const int CONTENT=7; static const int QUIT=8; int main(void) { /*主机信息*/ struct hostent* host; //这里面的地址采用网络字节序 if((host=gethostbyname(SEND_DES))==NULL) //获得域名对应的主机信息 { printf("gethostbyname 错误!程序退出!\n"); exit(1); } printf("\n域名对应主机名:%s\n",host->h_name); /*创建socket*/ int sockfd=socket(AF_INET,SOCK_STREAM,0); //ipv4 tcp if(sockfd==-1) { printf("socket 创建错误!\n"); exit(1); } printf("socket 创建成功!\n"); /*目的地地址信息*/ struct sockaddr_in serAddr; serAddr.sin_family=AF_INET; //ipv4 serAddr.sin_port=htons(SEND_PORT); //端口号变换成网络字节须 serAddr.sin_addr=*((struct in_addr *)host->h_addr);//server ip 注意这里的细节东西 bzero(&(serAddr.sin_zero),8); //加0以成功转化为struct sockaddr类型 /*下面进行操作,共分为三大步:建立连接,对话及发送邮件信息,关闭连接*/ char buff[BUFFMAX]; int cnt; /*第一步:建立连接*/ printf("\n请求:连接IP地址 %s 端口 %d 的服务.... ",SEND_DES,SEND_PORT); if((connect(sockfd,(struct sockaddr*)&serAddr,sizeof(struct sockaddr)))==-1) //结构体强制转换 { printf("connect 错误!\n"); exit(1); } printf("connect 成功!\n"); cnt=recv(sockfd,buff,BUFFMAX,0); //接受请求这个端口后的回答 recvCntInfo(cnt,buff); /*第二步:对话及发送邮件信息*/ /*初始化每次对话要发送的信息*/ char* msg[9]={""}; //分别对应每次的发送消息 msg[HELO]="helo 163\n"; //打招呼 msg[AUTHLOGIN]="auth login\n"; //登录命令 msg[USERNAME]="MTU2MDg0MTk0NTA=\n"; //已经转化为base64编码方式 msg[PASSWORD]="MjY2MTQ3\n"; //base64编码方式 msg[MAILFROM]="MAIL FROM:<15608419450@163.com>\n"; //发邮件人 msg[RCPTTO]="RCPT TO:<1150614705@qq.com>\n"; //预期接受人 msg[DATA]="data\n"; //准备发送邮件数据的命令 msg[CONTENT]="FROM:15608419450@163.com\nTO:1150614705@qq.com\nSubject:163 to qq\n\nfffdfdfddddfdd HELLO! 163 TO QQ EMAIL!\nNow it is 20:44\n.\n"; msg[QUIT]="quit\n"; /*下面开始发送各个消息*/ int step; for(step=HELO;step<=CONTENT;step++) //每个step对应一次发送消息及接受消息的对话 { printf("< %d > 发送信息如下:\n%s",step,msg[step]); if((send(sockfd,msg[step],strlen(msg[step]),0))==-1) //注意这里一定要用strlen()而不是sizeof.... { printf("send 出错!\n"); } printf("send 成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,0); recvCntInfo(cnt,buff); } /*第三步,退出程序*/ printf("邮件已成功从此客户端发送到邮件服务器!现在发送退出连接邮件服务器消息:\n"); if((send(sockfd,msg[QUIT],strlen(msg[QUIT]),0))==-1) //注意这里一定要用strlen()而不是sizeof.... { printf("quit 发送出错!\n"); } printf("quit 发送成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,0); recvCntInfo(cnt,buff); }
#include "myHead.h" const char* GET_DES="pop3.163.com"; const int GET_PORT=110; /*下面定义常量,其实标号不重要,只是当作下标,好记*/ static const int USR=0; static const int PSW=1; static const int QUIT=2; static const int LIST=3; static const int RETR=4; static const int DELE=5; static const int RSET=6; static char* msg[7]={""}; //装指向字符串的指针数组,仅此文件可见 int showOprate(void); //显示选择,返回输入项 int main(void) { /*初始化命令*/ msg[USR]="user 15608419450@163.com\n"; msg[PSW]="pass 266147\n"; msg[QUIT]="quit\n"; msg[LIST]="LIST\n"; msg[RSET]="RSET\n"; /*主机信息*/ struct hostent* host; //这里面的地址采用网络字节序 if((host=gethostbyname(GET_DES))==NULL) //获得域名对应的主机信息 { printf("gethostbyname 错误!程序退出!\n"); exit(1); } printf("\n域名对应主机名:%s\n",host->h_name); /*创建socket*/ int sockfd=socket(AF_INET,SOCK_STREAM,0); //ipv4 tcp if(sockfd==-1) { printf("socket 创建错误!\n"); exit(1); } printf("socket 创建成功!\n"); /*目的地地址信息*/ struct sockaddr_in serAddr; serAddr.sin_family=AF_INET; //ipv4 serAddr.sin_port=htons(GET_PORT); //端口号变换成网络字节须 serAddr.sin_addr=*((struct in_addr *)host->h_addr);//server ip 注意这里的细节东西 bzero(&(serAddr.sin_zero),8); //加0以成功转化为struct sockaddr类型 /*下面进行操作,共分为三个状态*/ char buff[BUFFMAX]; int cnt; /*一:认证状态*/ /*先连接主机*/ printf("\n请求:连接IP地址 %s 端口 %d 的服务.... ",GET_DES,GET_PORT); if((connect(sockfd,(struct sockaddr*)&serAddr,sizeof(struct sockaddr)))==-1) //结构体强制转换 { printf("connect 错误!\n"); exit(1); } printf("connect 成功!\n"); cnt=recv(sockfd,buff,BUFFMAX,0); //接受请求这个端口后的回答 recvCntInfo(cnt,buff); /*再输入用户名和密码*/ printf("下面登录邮箱:\n"); int step=USR; for(;step<=PSW;step++) //其实就2步发送 { printf("< %d > 发送信息如下:\n%s",step,msg[step]); if((send(sockfd,msg[step],strlen(msg[step]),0))==-1) //注意这里一定要用strlen()而不是sizeof.... { printf("send 出错!\n"); } printf("send 成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,0); recvCntInfo(cnt,buff); } /*二,处理状态*/ int choise=showOprate(); while(choise!=0) //循环显示 { /*下面处理输入的情况*/ if(choise>4|choise<0) { printf("选择 %d 为非法输入!请重新输入!\n",choise); } else { int sendChoise; //发送的消息对应的下标 int val; //命令的参数 char sendStr[100]={‘\0‘}; //待发送的字符串 switch(choise) { case 1:sendChoise=LIST;break; //仅仅列表 case 2:{ printf("请输入要返回的邮件编号:"); scanf("%d",&val); //需要编号 getchar(); sprintf(sendStr,"%s%d%c","retr ",val,‘\n‘); //注意也要把换行符加进去 sendChoise=RETR; msg[RETR]=sendStr; break; } case 3:{ printf("请输入要删除的邮件编号"); scanf("%d",&val); //需要编号 getchar(); sprintf(sendStr,"%s%d%c","dele ",val,‘\n‘); sendChoise=DELE; msg[DELE]=sendStr; break; } case 4:sendChoise=RSET;break; } printf("发送请求:\n%s",msg[sendChoise]); if((send(sockfd,msg[sendChoise],strlen(msg[sendChoise]),0))==-1) //注意这里一定要用strlen()而不是sizeof.... { printf("send 出错!\n"); } printf("send 成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,0); recvCntInfo(cnt,buff); } choise=showOprate(); } /*三,更新状态*/ printf("操作结束,现在发送退出连接邮件服务器消息以完成更新操作\n"); if((send(sockfd,msg[QUIT],strlen(msg[QUIT]),0))==-1) //注意这里一定要用strlen()而不是sizeof.... { printf("quit 发送出错!\n"); } printf("quit 发送成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,0); recvCntInfo(cnt,buff); } int showOprate(void) { printf("\n邮件操作选项如下:\n"); printf("1:LIST 2:RETR\n"); printf("3:DELE 4:RSET\n"); printf("请输入操作序号(0结束):"); int choise; scanf("%d",&choise); getchar(); return choise; }
exec:send get send:send.o myFunc.o gcc send.o myFunc.o -o send get:get.o myFunc.o gcc get.c myFunc.o -o get send.o:send.c myHead.h gcc send.c -c get.o:get.c myHead.h gcc get.c -c myFunc.0:myFunc.c gcc myFunc.c -c
那个。。。貌似有我的邮箱用户名和密码,我也不用。。。哈哈