C++發送郵件和附件


 

 頭文件

[cpp]  view plain copy
 
  1. /*********************************************************************** 
  2. *發送郵件模塊頭文件 
  3. *可以發送文本和附件(支持多個附件一起發送) 
  4. *************************************************************************/  
  5. #pragma once  
  6. struct sMailInfo //郵件信息  
  7. {  
  8.     char*   m_pcUserName;//用戶登錄郵箱的名稱  
  9.     char*   m_pcUserPassWord;//用戶登錄郵箱的密碼  
  10.     char*   m_pcSenderName;//用戶發送時顯示的名稱  
  11.     char*   m_pcSender;//發送者的郵箱地址  
  12.     char*   m_pcReceiver;//接收者的郵箱地址  
  13.     char*   m_pcTitle;//郵箱標題  
  14.     char*   m_pcBody;//郵件文本正文  
  15.     char*   m_pcIPAddr;//服務器的IP  
  16.     char*   m_pcIPName;//服務器的名稱(IP與名稱二選一,優先取名稱)  
  17.     sMailInfo(){memset(this,0,sizeof(sMailInfo));}  
  18. };  
  19. class CSendMail  
  20. {  
  21. public:  
  22.     CSendMail(void);  
  23.     ~CSendMail(void);  
  24.   
  25. public:  
  26.     bool SendMail(sMailInfo &smailInfo);//發送郵件,需要在發送的時候初始化郵件信息  
  27.     void AddFilePath(char * pcFilePath);//添加附件的決定路徑到附件列表中  
  28.     void DeleteFilePath(char* pcFilePath);//刪除附件路徑,如果有的話  
  29.     void DeleteAllPath(void);//刪除全部附件的路徑  
  30.   
  31. protected:  
  32.     void GetFileName(char* fileName,char* filePath);//從附件的路徑中獲取文件名稱  
  33.     void Char2Base64(char* pBuff64,char* pSrcBuff,int iLen);//把char類型轉換成Base64類型  
  34.     bool  CReateSocket(SOCKET &sock);//建立socket連接  
  35.     bool Logon(SOCKET &sock);//登錄郵箱,主要進行發郵件前的准備工作  
  36.     int GetFileData(char* FilePath);//由文件路徑獲取附件內容  
  37.   
  38.     bool SendHead(SOCKET &sock);//發送郵件頭  
  39.     bool SendTextBody(SOCKET &sock);//發送郵件文本正文  
  40.     bool SendFileBody(SOCKET &sock);//發送郵件附件  
  41.     bool SendEnd(SOCKET &sock);//發送郵件結尾  
  42. protected:  
  43.     CList<char*,char*> m_pcFilePathList;//記錄附件路徑  
  44.   
  45.     char  m_cSendBuff[4096];//發送緩沖區  
  46.     char  m_cReceiveBuff[1024];  
  47.     char* m_pcFileBuff;//指向附件內容  
  48.     sMailInfo m_sMailInfo;  
  49. };  


模塊實現文件

[cpp]  view plain copy
 
  1. /************************************************************************ 
  2. * 發送郵件模塊 
  3. *可以發送文本和附件(支持多個附件一起發送) 
  4. *Date:2011-12-01 
  5. ************************************************************************/  
  6. #include "StdAfx.h"  
  7. #include "SendMail.h"  
  8. #include "winsock2.h"  
  9. #pragma comment(lib,"WSOCK32")  
  10.   
  11. CSendMail::CSendMail(void)  
  12. {  
  13.     m_pcFileBuff=NULL;  
  14.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  15.     memset(m_cReceiveBuff,0,sizeof(m_cReceiveBuff));  
  16. }  
  17.   
  18.   
  19. CSendMail::~CSendMail(void)  
  20. {  
  21.     DeleteAllPath();  
  22. }  
  23.   
  24.   
  25. void CSendMail::Char2Base64(char* pBuff64,char* pSrcBuff,int iLen)  
  26. {  
  27.     //1   1   1   1   1   1   1   1  
  28.     // 分配給pBuff64  ↑ 分配給pBuff64+1  
  29.     //         point所在的位置  
  30.     static char Base64Encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";//base64所映射的字符表  
  31.     int point;//每一個源字符拆分的位置,可取2,4,6;初始為2  
  32.     point=2;  
  33.     int i;  
  34.     int iIndex;//base64字符的索引  
  35.     char n=0;//上一個源字符的殘留值  
  36.     for(i=0;i<iLen;i++)  
  37.     {  
  38.         if(point==2)  
  39.         {  
  40.             iIndex=((*pSrcBuff)>>point)&0x3f;//取得pSrcBuff的高point位  
  41.         }  
  42.         else if (point==4)  
  43.         {  
  44.             iIndex=((*pSrcBuff)>>point)&0xf;//取得pSrcBuff的高point位  
  45.         }  
  46.         else if(point==6)  
  47.         {  
  48.             iIndex=((*pSrcBuff)>>point)&0x3;//取得pSrcBuff的高point位  
  49.         }  
  50.         iIndex+=n;//與pSrcBuff-1的低point結合組成Base64的索引  
  51.         *pBuff64++=Base64Encode[iIndex];//由索引表得到pBuff64  
  52.         n=((*pSrcBuff)<<(6-point));//計算源字符中的殘留值  
  53.         n=n&0x3f;//確保n的最高兩位為0  
  54.         point+=2;//源字符的拆分位置上升2  
  55.         if(point==8)//如果拆分位置為8說明pSrcBuff有6位殘留,可以組成一個完整的Base64字符,所以直接再組合一次  
  56.         {  
  57.             iIndex=(*pSrcBuff)&0x3f;//提取低6位,這就是索引了  
  58.             *pBuff64++=Base64Encode[iIndex];//  
  59.             n=0;//殘留值為0  
  60.             point=2;//拆分位置設為2  
  61.         }  
  62.         pSrcBuff++;  
  63.   
  64.     }  
  65.     if(n!=0)  
  66.     {  
  67.         *pBuff64++=Base64Encode[n];  
  68.     }  
  69.     if(iLen%3==2)//如果源字符串長度不是3的倍數要用'='補全  
  70.     {  
  71.         *pBuff64='=';  
  72.     }  
  73.     else if(iLen%3==1)  
  74.     {  
  75.         *pBuff64++='=';  
  76.         *pBuff64='=';  
  77.     }  
  78. }  
  79.   
  80. void CSendMail::AddFilePath(char * pcFilePath)//添加附件路徑  
  81. {  
  82.     if(pcFilePath==NULL)  
  83.     {  
  84.         return;  
  85.     }  
  86.     int i;  
  87.     char* temp;  
  88.     for(i=0;i<m_pcFilePathList.GetCount();i++)  
  89.     {  
  90.         temp=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i));  
  91.         if(strcmp(pcFilePath,temp)==0)//如果已經存在就不用再添加了  
  92.         {  
  93.             return;  
  94.         }  
  95.     }  
  96.     m_pcFilePathList.AddTail(pcFilePath);  
  97. }  
  98.   
  99. void CSendMail::DeleteFilePath(char* pcFilePath)//刪除附件路徑  
  100. {  
  101.     int i;  
  102.     char* temp;  
  103.     for(i=0;i<m_pcFilePathList.GetCount();i++)  
  104.     {  
  105.         temp=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i));  
  106.         if(strcmp(temp,pcFilePath)==0)//找到並刪除它,如果沒找到就算了  
  107.         {  
  108.             m_pcFilePathList.RemoveAt(m_pcFilePathList.FindIndex(i));  
  109.             delete[] temp;  
  110.             return;  
  111.         }  
  112.     }  
  113. }  
  114.   
  115.   
  116. void CSendMail::DeleteAllPath(void)  
  117. {  
  118.     m_pcFilePathList.RemoveAll();  
  119. }  
  120.   
  121. int CSendMail::GetFileData(char* FilePath)  
  122. {  
  123.     m_pcFileBuff=NULL;  
  124.     if(FilePath==NULL)  
  125.     {  
  126.         return 0;  
  127.     }  
  128.     CFile f;  
  129.     int len;  
  130.       
  131.       
  132.     USES_CONVERSION;  
  133.     if(!f.Open(A2W(FilePath),CFile::modeRead|CFile::modeNoTruncate|CFile::typeBinary))  
  134.     {  
  135.         return 0;  
  136.     }  
  137.     len=(int)f.GetLength();  
  138.     m_pcFileBuff=new char[len+1];  
  139.     memset(m_pcFileBuff,0,len+1);  
  140.     f.Read(m_pcFileBuff,len);  
  141.   
  142.     f.Close();  
  143.     return len;  
  144. }  
  145.   
  146. void CSendMail::GetFileName(char* fileName,char* filePath)  
  147. {  
  148.     if(filePath==NULL || fileName==NULL)  
  149.     {  
  150.         return;  
  151.     }  
  152.     int i;  
  153.     for(i=0;i<(int)strlen(filePath);i++)  
  154.     {  
  155.         if(filePath[strlen(filePath)-1-i]=='\\')  
  156.         {  
  157.             memcpy(fileName,&filePath[strlen(filePath)-i],i);  
  158.             return;  
  159.         }  
  160.     }  
  161. }  
  162.   
  163. bool CSendMail::CReateSocket(SOCKET &sock)  
  164. {  
  165.     WORD wVersionRequested;  
  166.     WSADATA wsaData;  
  167.     int err;  
  168.     wVersionRequested = MAKEWORD( 2, 2 );  
  169.     err = WSAStartup( wVersionRequested, &wsaData );  
  170.     if ( err != 0 )   
  171.     {  
  172.         return false;  
  173.     }  
  174.     if ( LOBYTE( wsaData.wVersion ) != 2 ||  
  175.         HIBYTE( wsaData.wVersion ) != 2 )  
  176.     {  
  177.         WSACleanup( );  
  178.         return false;   
  179.     }  
  180.     sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);  
  181.     if (sock == INVALID_SOCKET)  
  182.     {  
  183.         return false;  
  184.     }  
  185.   
  186.     sockaddr_in servaddr;  
  187.     memset(&servaddr,0,sizeof(sockaddr_in));  
  188.     servaddr.sin_family = AF_INET;  
  189.     servaddr.sin_port = htons(25);//發郵件一般都是25端口  
  190.     if(m_sMailInfo.m_pcIPName=="")  
  191.     {  
  192.         servaddr.sin_addr.s_addr = inet_addr(m_sMailInfo.m_pcIPAddr);//直接使用IP地址  
  193.     }  
  194.     else  
  195.     {  
  196.         struct hostent *hp=gethostbyname(m_sMailInfo.m_pcIPName);//使用名稱  
  197.         servaddr.sin_addr.s_addr=*(int*)(*hp->h_addr_list);  
  198.     }  
  199.   
  200.   
  201.     int ret = connect(sock,(sockaddr*)&servaddr,sizeof(servaddr));//建立連接  
  202.     if (ret == SOCKET_ERROR)  
  203.     {  
  204.         return false;  
  205.     }  
  206.   
  207.     return true;  
  208. }  
  209.   
  210.   
  211. bool CSendMail::Logon(SOCKET &sock)  
  212. {  
  213.     recv(sock,m_cReceiveBuff,1024,0);  
  214.   
  215.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  216.     sprintf_s(m_cSendBuff,"HELO []\r\n");  
  217.     send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//開始會話  
  218.     recv(sock,m_cReceiveBuff,1024,0);  
  219.     if(m_cReceiveBuff[0]!='2' || m_cReceiveBuff[1]!='5' || m_cReceiveBuff[2]!='0')  
  220.     {  
  221.         return false;  
  222.     }  
  223.   
  224.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  225.     sprintf_s(m_cSendBuff,"AUTH LOGIN\r\n");  
  226.     send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//請求登錄  
  227.     recv(sock,m_cReceiveBuff,1024,0);  
  228.     if(m_cReceiveBuff[0]!='3' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='4')  
  229.     {  
  230.         return false;  
  231.     }  
  232.   
  233.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  234.     Char2Base64(m_cSendBuff,m_sMailInfo.m_pcUserName,strlen(m_sMailInfo.m_pcUserName));  
  235.     m_cSendBuff[strlen(m_cSendBuff)]='\r';  
  236.     m_cSendBuff[strlen(m_cSendBuff)]='\n';  
  237.     send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//發送用戶名  
  238.     recv(sock,m_cReceiveBuff,1024,0);  
  239.     if(m_cReceiveBuff[0]!='3' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='4')  
  240.     {  
  241.         return false;  
  242.     }  
  243.   
  244.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  245.     Char2Base64(m_cSendBuff,m_sMailInfo.m_pcUserPassWord,strlen(m_sMailInfo.m_pcUserPassWord));  
  246.     m_cSendBuff[strlen(m_cSendBuff)]='\r';  
  247.     m_cSendBuff[strlen(m_cSendBuff)]='\n';  
  248.     send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//發送用戶密碼  
  249.     recv(sock,m_cReceiveBuff,1024,0);  
  250.     if(m_cReceiveBuff[0]!='2' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='5')  
  251.     {  
  252.         return false;  
  253.     }  
  254.     return true;//登錄成功  
  255. }  
  256.   
  257.   
  258. bool CSendMail::SendHead(SOCKET &sock)  
  259. {  
  260.     int rt;  
  261.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  262.     sprintf_s(m_cSendBuff,"MAIL FROM:<%s>\r\n",m_sMailInfo.m_pcSender);  
  263.     rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  264.       
  265.     if(rt!=strlen(m_cSendBuff))  
  266.     {  
  267.         return false;  
  268.     }  
  269.     recv(sock,m_cReceiveBuff,1024,0);  
  270.   
  271.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  272.     sprintf_s(m_cSendBuff,"RCPT TO:<%s>\r\n",m_sMailInfo.m_pcReceiver);  
  273.     rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  274.     if(rt!=strlen(m_cSendBuff))  
  275.     {  
  276.         return false;  
  277.     }  
  278.     recv(sock,m_cReceiveBuff,1024,0);  
  279.   
  280.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  281.     memcpy(m_cSendBuff,"DATA\r\n",strlen("DATA\r\n"));  
  282.     rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  283.     if(rt!=strlen(m_cSendBuff))  
  284.     {  
  285.         return false;  
  286.     }  
  287.     recv(sock,m_cReceiveBuff,1024,0);  
  288.   
  289.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  290.     sprintf_s(m_cSendBuff,"From:\"%s\"<%s>\r\n",m_sMailInfo.m_pcSenderName,m_sMailInfo.m_pcSender);  
  291.     sprintf_s(&m_cSendBuff[strlen(m_cSendBuff)],150,"To:\"INVT.COM.CN\"<%s>\r\n",m_sMailInfo.m_pcReceiver);  
  292.     sprintf_s(&m_cSendBuff[strlen(m_cSendBuff)],150,"Subject:%s\r\nMime-Version: 1.0\r\nContent-Type: multipart/mixed;   boundary=\"INVT\"\r\n\r\n",m_sMailInfo.m_pcTitle);  
  293.     rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  294.     if(rt!=strlen(m_cSendBuff))  
  295.     {  
  296.         return false;  
  297.     }  
  298.   
  299.     return true;  
  300. }  
  301.   
  302. bool CSendMail::SendTextBody(SOCKET &sock)  
  303. {  
  304.     int rt;  
  305.     memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  306.     sprintf_s(m_cSendBuff,"--INVT\r\nContent-Type: text/plain;\r\n  charset=\"gb2312\"\r\n\r\n%s\r\n\r\n",m_sMailInfo.m_pcBody);  
  307.     rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  308.     if(rt!=strlen(m_cSendBuff))  
  309.     {  
  310.         return false;  
  311.     }  
  312.     else  
  313.     {  
  314.         return true;  
  315.     }  
  316. }  
  317.   
  318. bool CSendMail::SendFileBody(SOCKET &sock)  
  319. {  
  320.     int i;  
  321.     char* filePath;  
  322.     int rt;  
  323.     int len;  
  324.     int pt=0;  
  325.     char fileName[128];  
  326.     for(i=0;i<m_pcFilePathList.GetCount();i++)  
  327.     {  
  328.         pt=0;  
  329.         memset(fileName,0,128);  
  330.         filePath=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i));  
  331.         len=GetFileData(filePath);  
  332.         GetFileName(fileName,filePath);  
  333.   
  334.         sprintf_s(m_cSendBuff,"--INVT\r\nContent-Type: application/octet-stream;\r\n  name=\"%s\"\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment;\r\n  filename=\"%s\"\r\n\r\n",fileName,fileName);  
  335.         send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  336.         while (pt<len)  
  337.         {  
  338.             memset(m_cSendBuff,0,sizeof(m_cSendBuff));  
  339.             Char2Base64(m_cSendBuff,&m_pcFileBuff[pt],min(len-pt,3000));  
  340.             m_cSendBuff[strlen(m_cSendBuff)]='\r';  
  341.             m_cSendBuff[strlen(m_cSendBuff)]='\n';  
  342.             rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  343.             pt+=min(len-pt,3000);  
  344.             if(rt!=strlen(m_cSendBuff))  
  345.             {  
  346.                 return false;  
  347.             }  
  348.         }  
  349.         if(len!=0)  
  350.         {  
  351.             delete [] m_pcFileBuff;  
  352.         }  
  353.     }  
  354.   
  355.     return true;  
  356. }  
  357.   
  358. bool CSendMail::SendEnd(SOCKET &sock)  
  359. {  
  360.     sprintf_s(m_cSendBuff,"--INVT--\r\n.\r\n");  
  361.     send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  362.   
  363.     sprintf_s(m_cSendBuff,"QUIT\r\n");  
  364.     send(sock,m_cSendBuff,strlen(m_cSendBuff),0);  
  365.     closesocket(sock);  
  366.     WSACleanup();  
  367.     return true;  
  368. }  
  369.   
  370.   
  371. bool CSendMail::SendMail(sMailInfo &smailInfo)  
  372. {  
  373.     memcpy(&m_sMailInfo,&smailInfo,sizeof(smailInfo));  
  374.     if(m_sMailInfo.m_pcBody==NULL  
  375.         || m_sMailInfo.m_pcIPAddr==NULL  
  376.         || m_sMailInfo.m_pcIPName==NULL  
  377.         || m_sMailInfo.m_pcReceiver==NULL  
  378.         || m_sMailInfo.m_pcSender==NULL  
  379.         || m_sMailInfo.m_pcSenderName==NULL  
  380.         || m_sMailInfo.m_pcTitle==NULL  
  381.         || m_sMailInfo.m_pcUserName==NULL  
  382.         || m_sMailInfo.m_pcUserPassWord==NULL)  
  383.     {  
  384.         return false;  
  385.     }  
  386.     SOCKET sock;  
  387.     if(!CReateSocket(sock))//建立連接  
  388.     {  
  389.         return false;  
  390.     }  
  391.   
  392.     if(!Logon(sock))//登錄郵箱  
  393.     {  
  394.         return false;  
  395.     }  
  396.   
  397.     if(!SendHead(sock))//發送郵件頭  
  398.     {  
  399.         return false;  
  400.     }  
  401.   
  402.     if(!SendTextBody(sock))//發送郵件文本部分  
  403.     {  
  404.         return false;  
  405.     }  
  406.   
  407.     if(!SendFileBody(sock))//發送附件  
  408.     {  
  409.         return false;  
  410.     }  
  411.   
  412.     if(!SendEnd(sock))//結束郵件,並關閉sock  
  413.     {  
  414.         return false;  
  415.     }  
  416.   
  417.     return true;  
  418. }  

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com