郵件客戶端編程(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;
}
相關文章
相關標籤/搜索