邮件客户端编程(pop和smtp)

环境:xp系统,vc6.0、c语言c++

这里是代码的草稿,本来设计的结构跟如今撸出来的结构相差比较大windows

实现的部分:服务器

  1. smtp协议,能够完成最简邮件格式的发送,收件人能够正常收到socket

  2. base64编码,能够完成对任意长度的字符串进行base64编码tcp

  3. base64解码,只是完成了对单个字节解码函数

  4. pop协议,只是完成了基本的服务器交互指令,对于data部分的接收没有实现oop

个人想法是摸索阶段的代码必定不会使用c++,进行整合优化的时候会考虑使用c++封装测试

还有看的时候,可能会感受代码比较乱,若是愿意的话,能够给我一些建议优化

 

#include <Winsock2.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#define PORTPOP 110
#define PORTSMTP 25
#define BUFF_BASE64 1024*1024*4  //开辟4M的base64编码的存储区,2M发送的数据,2M接收的数据
char *buff_begin;//缓冲区的起始指针
unsigned long num_now;//缓冲区当前字节数
char *point_now;//指向当前缓冲区的可用部分
struct base64{
 char result;//base64加密后的结果
 char residue;//原数据剩下的部分
 int  number;//位移的位数
};
char base64_char[64]={'A','B','C','D','E','F','G','H',
      'I','J','K','L','M','N','O','P',
      'Q','R','S','T','U','V','W','X',
      'Y','Z','a','b','c','d','e','f',
      'g','h','i','j','k','l','m','n',
      'o','p','q','r','s','t','u','v',
      'w','x','y','z','0','1','2','3',
      '4','5','6','7','8','9','+','/',};
int chartonumber(base64 *data);   //编码:数字转换为对应字母
int transformtobase64(base64 *data); //编码:对单字节编码
int transformstring(char *strings);  //编码:对字符串编码
//套接字是否已经链接
int condition_pop3=0; 
int tcp_pop(SOCKET pop,sockaddr_in saddr,char *r_buffer,char *s_buffer);
int tcp_smtp(char *r_buffer,char *s_buffer);
 char *name="servertss"; //用户名
 char *pasw="12345zxcvb";//密码
 char *capa="CAPA";
 char *user="USER";//用户名
 char *pass="PASS";//密码
 char *apop="APOP";//指定邮箱和MD5摘要串
 char *stat="STAT";//请求邮件总数和总字节数
 char *uidl="UIDL";//返回邮件的惟一标识符
 char *list="LIST";//返回邮件数量和每一个邮件的大小
 char *retr="RETR";//返回由参数标识的邮件的所有文本
 char *dele="DELE";//服务器将由参数标识的邮件标记为删除
 char *rset="RSET";//服务器将重置全部标记为删除的邮件,用于撤销DELE命令
 char *top="TOP";//服务器将返回由参数标识的邮件前n行内容,n必须是正整数
 char *noop="NOOP";//服务器返回一个确定的响应
 char *quit="QUIT";//结束会话
 char *ok="+OK";//服务器确认标识
 char crlf[2]={'\r','\n'};//结束标志
 char *ehlo="EHLO";//开始SMTP会话
 char *auth="AUTH";
 char *login="LOGIN";
 char *mail="MAIL";//邮件开始
 char *from="FROM";//发件方地址
 char *rcpt="RCPT";//收件方地址
 char *data="DATA";//邮件正文开始
 char *vrfy="VRFY";//用于验证指定的用户/邮箱是否存在
 char *expn="EXPN";//验证给定的邮箱列表是否存在,扩充邮箱列表,常被禁用
 char *help="HELP";//查询服务器支持什么命令
int senddata(char *begin);
int main()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 
 wVersionRequested=MAKEWORD(2,2);
 int err=WSAStartup(wVersionRequested,&wsaData);
 if(err!=0)
 {
  printf("WSAStartup函数加载失败\n");
  return 0;
 }
 buff_begin=(char *)malloc(BUFF_BASE64);
 if(!buff_begin)
  return 0;
 num_now=0;
 point_now=buff_begin;
 char request[512];//客户端请求缓冲
 char respond[512];//服务器回应缓冲
 //memset(request,'\0',512);
 //memset(respond,'\0',512);
 sockaddr_in saddr_pop;
 saddr_pop.sin_family=AF_INET;
 saddr_pop.sin_port=htons(PORTPOP);
 saddr_pop.sin_addr.s_addr= inet_addr("123.125.50.29");
 SOCKET client_pop;
 client_pop=socket(AF_INET,SOCK_STREAM,0);
 
/*
 char *s="这是一份测试邮件";
 transformstring(s);
 for(int i=0;i<num_now;i++)
 {
  printf("%c",*(buff_begin+i));
 }
 printf("\n");
*/
 int n=10;
 while(n)
 {
  tcp_smtp(request,respond);
  Sleep(30000);
  n--;
 }
/*
 int ii=senddata(buff_begin);
 printf("%d",ii);
 for(int i=0;i<ii;i++)
 {
  printf("%c",*(buff_begin+i));
 }
*/
 /*
 tcp_pop(client_pop,saddr_pop,request,respond);
 bool brk=1;
 while(brk)//主循环会一直对是否有新邮件进行查询
 {
  Sleep(5000);
 }
*/
 WSACleanup();
 return 1;
}
//POP链接
int tcp_pop(SOCKET pop,sockaddr_in saddr,char *r_buffer,char *s_buffer)
{
 int con=connect(pop,(struct sockaddr *)&saddr,sizeof(saddr));
 if(con==0)
  printf("TCP已经链接\n");
 else
  return 0;
 
 //TCP链接完成以后会受到服务的第一次确认
 memset(r_buffer,'\0',512);
 int rec=recv(pop,r_buffer,512,0);
 printf("%s\n",r_buffer);
 //CAPA指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,capa,4);
 memcpy(s_buffer+4,crlf,2);
 printf("%s\n",s_buffer);
 send(pop,s_buffer,6,0);
 //CAPA指令以后接收服务器回应
 memset(r_buffer,'\0',512);
 rec=recv(pop,r_buffer,512,0);
 printf("%s",r_buffer);
 //USER指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,user,4);
 *(s_buffer+4)=' ';
 memcpy(s_buffer+5,name,9);
 memcpy(s_buffer+14,crlf,2);
 printf("%s\n",s_buffer);
 send(pop,s_buffer,16,0);
 //USER指令以后接收服务器回应
 memset(r_buffer,'\0',512);
 rec=recv(pop,r_buffer,512,0);
 printf("%s",r_buffer);
 //PASS指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,pass,4);
 *(s_buffer+4)=' ';
 memcpy(s_buffer+5,pasw,10);
 memcpy(s_buffer+15,crlf,2);
 printf("%s\n",s_buffer);
 send(pop,s_buffer,17,0);
 //PASS指令以后,服务器返回邮箱邮件总数
 memset(r_buffer,'\0',512);
 rec=recv(pop,r_buffer,512,0);
 printf("%s",r_buffer);
 //STAT指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,stat,4);
 memcpy(s_buffer+4,crlf,2);
 printf("%s\n",s_buffer);
 send(pop,s_buffer,6,0);
 //STAT指令以后接收服务器回应,请求邮件总数和总字节数
 memset(r_buffer,'\0',512);
 rec=recv(pop,r_buffer,512,0);
 printf("%s",r_buffer);
 //UIDL指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,uidl,4);
 memcpy(s_buffer+4,crlf,2);
 printf("%s\n",s_buffer);
 send(pop,s_buffer,6,0);
 //UIDL指令以后接收服务器回应,返回邮件的惟一标识符
 memset(r_buffer,'\0',512);
 rec=recv(pop,r_buffer,512,0);
 printf("%s",r_buffer);
 //LIST指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,list,4);
 memcpy(s_buffer+4,crlf,2);
 printf("%s\n",s_buffer);
 send(pop,s_buffer,6,0);
 //LIST指令以后接收服务器回应,返回邮件数量和每一个邮件的大小
 memset(r_buffer,'\0',512);
 rec=recv(pop,r_buffer,512,0);
 printf("%s",r_buffer);
 //QUIT指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,quit,4);
 memcpy(s_buffer+4,crlf,2);
 printf("%s\n",s_buffer);
 send(pop,s_buffer,6,0);
 //QUIT指令以后接收服务器回应,返回邮件数量和每一个邮件的大小
 memset(r_buffer,'\0',512);
 rec=recv(pop,r_buffer,512,0);
 printf("%s",r_buffer);
 
 return 1;
}
//SMTP链接
int tcp_smtp(char *r_buffer,char *s_buffer)
{
 sockaddr_in saddr_smtp;
 saddr_smtp.sin_family=AF_INET;
 saddr_smtp.sin_port=htons(PORTSMTP);
 saddr_smtp.sin_addr.s_addr= inet_addr("123.125.50.134");
 SOCKET smtp;
 smtp=socket(AF_INET,SOCK_STREAM,0);
 int con=connect(smtp,(struct sockaddr *)&saddr_smtp,sizeof(saddr_smtp));
 if(con==0)
  printf("TCP已经链接\n");
 else
 {
  return 0;
 }
 //TCP链接完成以后会受到服务的第一次确认
 memset(r_buffer,'\0',512);
 int rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 //EHLO指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,ehlo,4);
 memcpy(s_buffer+5,name,9);
 memcpy(s_buffer+14,crlf,2);
 printf("%s",s_buffer);
 send(smtp,s_buffer,16,0);
 //EHLO指令以后接收服务器回应
 memset(r_buffer,'\0',512);
 rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 //AUTH指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,auth,4);
 *(s_buffer+4)=' ';
 memcpy(s_buffer+5,login,5);
 memcpy(s_buffer+10,crlf,2);
 printf("%s",s_buffer);
 send(smtp,s_buffer,12,0);
 //AUTH指令以后接收服务器回应
 memset(r_buffer,'\0',512);
 rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 //USER
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,"c2VydmVydHNz",12);
 memcpy(s_buffer+12,crlf,2);
 printf("%s",s_buffer);
 send(smtp,s_buffer,14,0);
 //USER以后接收服务器回应
 memset(r_buffer,'\0',512);
 rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 //PASS
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,"MTIzNDV6eGN2Yg==",16);
 memcpy(s_buffer+16,crlf,2);
 printf("%s",s_buffer);
 send(smtp,s_buffer,18,0);
 //PASS以后
 memset(r_buffer,'\0',512);
 rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 //MAIL指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,mail,4);
 *(s_buffer+4)=' ';
 memcpy(s_buffer+5,"FROM: <);
 memcpy(s_buffer+30,crlf,2);
 printf("%s\n",s_buffer);
 send(smtp,s_buffer,32,0);
 //MAIL指令以后
 memset(r_buffer,'\0',512);
 rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 //RCPT指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,rcpt,4);
 *(s_buffer+4)=' ';
 memcpy(s_buffer+5,"TO: <);
 memcpy(s_buffer+28,crlf,2);
 printf("%s",s_buffer);
 send(smtp,s_buffer,30,0);
 //RCPT指令以后
 memset(r_buffer,'\0',512);
 rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 //DATA指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,data,4);
 memcpy(s_buffer+4,crlf,2);
 printf("%s",s_buffer);
 send(smtp,s_buffer,6,0);
 //DATA指令以后
 int ii=senddata(buff_begin);
 send(smtp,buff_begin,ii,0);
 memset(r_buffer,'\0',512);
 rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 //QUIT指令
 memset(s_buffer,'\0',512);
 memcpy(s_buffer,quit,4);
 memcpy(s_buffer+4,crlf,2);
 printf("%s\n",s_buffer);
 send(smtp,s_buffer,6,0);
 //QUIT指令以后接收服务器回应,返回邮件数量和每一个邮件的大小
 memset(r_buffer,'\0',512);
 rec=recv(smtp,r_buffer,512,0);
 printf("%s",r_buffer);
 closesocket(smtp);
 return 1;
}
//在2M缓冲区组建须要发送的数据
int senddata(char *begin)
{
 int num=0;
 memcpy(begin,"Date: Sat,8 Mar 2014 22:36:04 +0800 (CST)",41);
 memcpy(begin+41,crlf,2);
 num+=43;
 memcpy(begin+num,"From: \"" <);
 memcpy(begin+num+45,crlf,2);
 num+=45+2;
 memcpy(begin+num,"To: servertss <);
 memcpy(begin+num+33,crlf,2);
 num+=33+2;
 memcpy(begin+num,"Subject: =?GB2312?B?YysrtcTEx7G+yunE47fF1NrExMDvwcs=?=",54);
 memcpy(begin+num+54,crlf,2);
 num+=54+2;
 memcpy(begin+num,"Mime-Version: 1.0",17);
 memcpy(begin+num+17,crlf,2);
 num+=17+2;
 memcpy(begin+num,"Message-ID: <);
 memcpy(begin+num+43,crlf,2);
 num+=43+2;
 memcpy(begin+num,"Content-Type: multipart/alternative;",36);
 *(begin+num+36)='\n';
 *(begin+num+37)='\t';
 memcpy(begin+num+36+2,"boundary=\"----=_001_NextPart674370231387_=----\"",48);
 memcpy(begin+num+36+2+48,crlf,2);
 num+=36+2+48+2;
 memcpy(begin+num,crlf,2);
 num+=2;
 memcpy(begin+num,"------=_001_NextPart674370231387_=----",38);
 memcpy(begin+num+38,crlf,2);
 num+=38+2;
 memcpy(begin+num,"Content-Type: text/plain;",25);
 *(begin+num+25)='\n';
 *(begin+num+26)='\t';
 memcpy(begin+num+25+2,"charset=\"GB2312\"",16);
 memcpy(begin+num+25+2+16,crlf,2);
 num+=25+2+16+2;
 memcpy(begin+num,"Content-Transfer-Encoding: base64",33);
 memcpy(begin+num+33,crlf,2);
 *(begin+num+33+2)='\n';
 num+=33+2+1;
 memcpy(begin+num,"CgoKYysrtcTEx7G+yunE47fF1NrExMDvwcsKy9m2yLjmy9/O0goK",52);
 num+=52;
 memcpy(begin+num,crlf,2);
 num+=2;
 memcpy(begin+num,"------=_001_NextPart674370231387_=----",38);
 memcpy(begin+num+38,crlf,2);
 num+=38+2;
 memcpy(begin+num,crlf,2);
 *(begin+num+2)='.';
 memcpy(begin+num+2+1,crlf,2);
 num+=2+1+2;
 return num;
}
//接收到服务器的消息,须要进行检验是否为“+OK”和其余确认标识,以及后面的字符集
/*
int check_id(char *buff)
{
 char id[4];
 char characters[500];
 memset(id,'\0',4);
 memset(characters,'\0',500);
 int i=0;
 for(i=0;i<4;i++)
 {
  id[i]=*(buff+i);
  i++;
 }
 
 switch(id)
 {
 case "+OK":
  break;
 }
 return 1;
}
*/
//对字符串进行base64编码
int transformstring(char *strings)
{
 int num=0;  //记录字节数目
 int buf=0; //临时单字节存储
 base64 buf_transfer; //base64转换的中转
 memset(&buf_transfer,'\0',sizeof(buf_transfer));
 buf_transfer.result=*strings;
 buf_transfer.number=0;
 while(buf_transfer.result!='\0')//字符串结束,则程序结束
 {
  if((0<=buf)&&(buf<6))
  {
   buf=transformtobase64(&buf_transfer);
   memcpy(point_now,&(buf_transfer.result),1);
   num++;
   buf_transfer.result=*(strings+num);
  }
  else
  {
   if(buf==6)
   {
    *point_now=base64_char[(unsigned int)buf_transfer.residue];
    buf_transfer.number=0;
    buf_transfer.residue='\0';
    buf=0;
   }
   else
    return buf;
  }
  point_now=point_now+1;
  num_now++;
 }
 if(buf_transfer.residue)
 {
  *point_now=base64_char[(unsigned int)(buf_transfer.residue<<(6-buf_transfer.number))];
  point_now++;
  num_now++;
 }
 buf=num%3;
 switch(buf)
 {
 case 0:
  break;
 case 1:
  memset(point_now,'=',2);
  point_now=point_now+2;
  num_now=num_now+2;
  break;
 case 2:
  *point_now='=';
  point_now++;
  num_now++;
  break;
 }
 return num;
}
int transformtobase64(base64 *data)//对单字节数据进行base64编码
{
 if(data->number<0)
  return -1;
 if(data->number>6)
  return 8;
 char buf='\0',back='\0';
 buf=data->residue<<(6-data->number);
 back=data->result>>(2+data->number);
 buf=back^buf;
 buf&=63;
 back='\0';
 back=data->result<<(6-data->number);
 data->residue=back>>(6-data->number);
 data->result=base64_char[(unsigned int)buf];
 data->residue&=63;
 data->number=2+data->number;
 return data->number;
}
//对字符串进行base64解码
int transformbase64(char *strings)
{
 return 1;
}
int base64totransform(base64 *data)//对单字节数据进行base64解码
{
 if(data->number<0)
  return -1;
 if(data->number>6)
  return 8;
 if(!chartonumber(data))//转换为6位
  return 0;
 char buf='0',back='0';
 buf=data->residue<<(8-data->number);
 if(data->number<3)
 {
  back=data->result;
  data->number+=6;
 }
 else{
  if(data->number<9)
  {
   back=data->result>>(data->number-2);
   data->result=data->result<<(10-data->number);
   data->residue=data->result>>(10-data->number);
   data->number=data->number-2;
   data->result=buf^back;
  }
 }
 data->residue=back^buf;
 if(data->number>7)
 {
  data->result=data->residue;
  data->residue='0';
  data->number=0;
 }
 return data->number;
}
int chartonumber(base64 *data)
{
 //65-90:A-Z
 //97-122:a-z
 //48-57:0-9
 //43,47:+,/
 int cod=0;
 if(64<(int)(data->result)&&91>(int)(data->result))
 {
  cod=1;
  data->result=char((int)(data->result)-65);
 }
 if(96<(int)(data->result)&&123>(int)(data->result))
 {
  cod=1;
  data->result=char((int)(data->result)-97+26);
 }
 if(47<(int)(data->result)&&58>(int)(data->result))
 {
  cod=1;
  data->result=char((int)(data->result)-48+52);
 }
 if(43==(int)(data->result))
 {
  cod=1;
  data->result=0x2B;
 }
 if(47==(int)(data->result))
 {
  cod=1;
  data->result=0x2F;
 }
 if(cod)
  return 1;
 else
  return 0;
}
相关文章
相关标签/搜索