先上源码

H

  1. /*  
  2.  * File:   CSendMail.h 
  3.  * Author: jaylong35 
  4.  * 
  5.  * Created on January 16, 2012, 6:14 PM 
  6.  */  
  7.   
  8. #ifndef CSENDMAIL_H  
  9. #define CSENDMAIL_H  
  10.   
  11. #include <string>  
  12. #include <list>  
  13. #include <vector>  
  14. #include <curl/curl.h>  
  15.   
  16. #define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000  
  17.   
  18.   
  19. class CSendMail {  
  20. public:  
  21.     CSendMail();  
  22.     CSendMail(  //create sendmail object with paremeter;  
  23.                 const std::string & strUser,  
  24.                 const std::string & strPsw,   
  25.                 const std::string & strSmtpServer,   
  26.                 int iPort,   
  27.                 const std::string & strMailFrom  
  28.             );  
  29.     CSendMail(const CSendMail& orig);  
  30.     virtual ~CSendMail();  
  31. private:  
  32.     std::string m_strUser;          //邮箱用户名  
  33.     std::string m_strPsw;           //邮箱密码  
  34.     std::string m_strSmtpServer;        //邮箱SMTP服务器  
  35.     int         m_iPort;            //邮箱SMTP服务器端口  
  36.     std::list<std::string> m_RecipientList;   //接收者邮件list  
  37.     std::string m_strMailFrom;          //发送者邮箱  
  38.     std::vector<std::string> m_MailContent;   //发送的内容队列,包括头和内容项  
  39.     int         m_iMailContentPos;      //用于发送数据时记录发送到第几个content  
  40.       
  41. private:  
  42.     //发送内容回调函数  
  43.     static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);  
  44.     //获取当前时间  
  45.     static struct timeval tvnow(void);  
  46.     //两个时间差  
  47.     static long tvdiff(struct timeval newer, struct timeval older);  
  48.     //创建邮件内容  
  49.     bool ConstructHead(const std::string & strSubject/*邮件主题*/, const std::string & strContent/*邮件内容*/);  
  50.       
  51. public:  
  52.       
  53.     bool SendMail(const std::string & strSubject, const char * pMailBody, int len);  
  54.     bool SendMail(const std::string & strSubject, const std::string & strMailBody);  
  55.     bool SendMail(  //create sendmail object with paremeter;  
  56.                     const std::string & strUser,  
  57.                     const std::string & strPsw,   
  58.                     const std::string & strSmtpServer,   
  59.                     int iPort,   
  60.                     std::list<std::string> & recipientList,  
  61.                     const std::string & strMailFrom,  
  62.                     const std::string & strSubject,   
  63.                     const char * pMailBody,   
  64.                     int len  
  65.                 );  
  66.     bool SendMail(  //create sendmail object with paremeter;  
  67.                     const std::string & strUser,  
  68.                     const std::string & strPsw,   
  69.                     const std::string & strSmtpServer,   
  70.                     int iPort,   
  71.                     const std::string & strMailTo,  
  72.                     const std::string & strMailFrom,  
  73.                     const std::string & strSubject,   
  74.                     const char * pMailBody,   
  75.                     int len  
  76.                 );  
  77.     bool SendMail(  //create sendmail object with paremeter;  
  78.                     const std::string & strUser,  
  79.                     const std::string & strPsw,   
  80.                     const std::string & strSmtpServer,   
  81.                     int iPort,   
  82.                     std::list<std::string> & recipientList,  
  83.                     const std::string & strMailFrom,  
  84.                     const std::string & strSubject,   
  85.                     const std::string & strMailBody  
  86.                 );  
  87.     bool SendMail(  //create sendmail object with paremeter;  
  88.                     const std::string & strUser,  
  89.                     const std::string & strPsw,   
  90.                     const std::string & strSmtpServer,   
  91.                     int iPort,   
  92.                     const std::string & strMailTo,  
  93.                     const std::string & strMailFrom,  
  94.                     const std::string & strSubject,   
  95.                     const std::string & strMailBody  
  96.                 );  
  97.       
  98.     void SetUser(const std::string & strUser) { m_strUser = strUser; }  
  99.     std::string & GetUser() { return m_strUser; }  
  100.       
  101.     void SetPsw(const std::string & strPsw) { m_strPsw = strPsw; }  
  102.     std::string & GetPsw() { return m_strPsw; }  
  103.       
  104.     void SetSmtpServer(const std::string & strSmtpServer) { m_strSmtpServer = strSmtpServer; }  
  105.     std::string & GetSmtpServer() { return m_strSmtpServer; }  
  106.       
  107.     void SetPort(int iPort) { m_iPort = iPort; }  
  108.     int GetPort() { return m_iPort; }  
  109.       
  110.     void SetMailFrom(const std::string & strMailFrom) { m_strMailFrom = strMailFrom; }  
  111.     std::string & GetMailFrom() { return m_strMailFrom; }  
  112.       
  113.     //添加接收者邮箱  
  114.     void AddRecipient(const std::string & strMailTo) { m_RecipientList.push_back(strMailTo); }  
  115.     void AddRecipient(std::list<std::string> recipientList)   
  116.     {   
  117.         std::copy(recipientList.begin(), recipientList.end(), m_RecipientList.begin());  
  118.     }  
  119.     void ClearRecipient() { m_RecipientList.clear(); }  
  120.       
  121. };  
  122.   
  123.   
  124. #endif  /* CSENDMAIL_H */  


cpp

  1. /*  
  2.  * File:   CSendMail.cpp 
  3.  * Author: root 
  4.  *  
  5.  * Created on January 16, 2012, 6:14 PM 
  6.  */  
  7.   
  8. #include "CSendMail.h"  
  9.   
  10. CSendMail::CSendMail()   
  11. {  
  12.     m_strUser = "";  
  13.     m_strPsw = "";  
  14.     m_strSmtpServer = "";  
  15.     m_iPort = -1;  
  16.     m_RecipientList.clear();  
  17.     m_strMailFrom = "";  
  18.     m_MailContent.clear();  
  19.     m_iMailContentPos = 0;  
  20. }  
  21.   
  22. CSendMail::CSendMail(  //create sendmail object with paremeter;  
  23.                 const std::string & strUser,  
  24.                 const std::string & strPsw,   
  25.                 const std::string & strSmtpServer,   
  26.                 int iPort,   
  27.                 const std::string & strMailFrom  
  28.             )  
  29. {  
  30.     m_strUser = strUser;  
  31.     m_strPsw = strPsw;  
  32.     m_strSmtpServer = strSmtpServer;  
  33.     m_iPort = iPort;  
  34.     m_RecipientList.clear();  
  35.     m_strMailFrom = strMailFrom;  
  36.     m_MailContent.clear();  
  37.     m_iMailContentPos = 0;  
  38. }  
  39.   
  40. CSendMail::CSendMail(const CSendMail& orig) {  
  41. }  
  42.   
  43. CSendMail::~CSendMail() {  
  44. }  
  45.   
  46. size_t CSendMail::read_callback(void* ptr, size_t size, size_t nmemb, void* userp)  
  47. {  
  48.     CSendMail * pSm = (CSendMail *)userp;  
  49.   
  50.     if(size*nmemb < 1)  
  51.         return 0;  
  52.     if(pSm->m_iMailContentPos < pSm->m_MailContent.size())  
  53.     {  
  54.         size_t len;  
  55.         len = pSm->m_MailContent[pSm->m_iMailContentPos].length();  
  56.   
  57.         memcpy(ptr, pSm->m_MailContent[pSm->m_iMailContentPos].c_str(), pSm->m_MailContent[pSm->m_iMailContentPos].length());  
  58.         pSm->m_iMailContentPos++; /* advance pointer */  
  59.         return len;  
  60.     }  
  61.     return 0;  
  62. }  
  63.   
  64. struct timeval CSendMail::tvnow()  
  65. {  
  66.   /* 
  67.   ** time() returns the value of time in seconds since the Epoch. 
  68.   */   
  69.     struct timeval now;  
  70.     now.tv_sec = (long)time(NULL);  
  71.     now.tv_usec = 0;  
  72.     return now;  
  73. }  
  74.   
  75. long CSendMail::tvdiff(timeval newer, timeval older)  
  76. {  
  77.     return (newer.tv_sec-older.tv_sec)*1000+  
  78.         (newer.tv_usec-older.tv_usec)/1000;  
  79. }  
  80.   
  81. bool CSendMail::ConstructHead(const std::string & strSubject, const std::string & strContent)  
  82. {  
  83.     m_MailContent.push_back("MIME-Versioin: 1.0\n");  
  84.     std::string strTemp = "To: ";  
  85.     for(std::list<std::string >::iterator it = m_RecipientList.begin(); it != m_RecipientList.end();)  
  86.     {  
  87.         strTemp += *it;  
  88.         it++;  
  89.         if(it != m_RecipientList.end())  
  90.                 strTemp += ",";  
  91.     }  
  92.     strTemp += "\n";  
  93.     m_MailContent.push_back(strTemp);  
  94.     if(strSubject != "")  
  95.     {  
  96.         strTemp = "Subject: ";  
  97.         strTemp += strSubject;  
  98.         strTemp += "\n";  
  99.         m_MailContent.push_back(strTemp);  
  100.     }  
  101.     m_MailContent.push_back("Content-Transfer-Encoding: 8bit\n");  
  102.     m_MailContent.push_back("Content-Type: text/html; \n Charset=\"UTF-8\"\n\n");  
  103.     if(strContent != "")  
  104.     {  
  105.         m_MailContent.push_back(strContent);  
  106.     }  
  107.       
  108.     return true;  
  109. }  
  110.   
  111. bool CSendMail::SendMail(const std::string& strSubject, const std::string& strMailBody)   
  112. {  
  113.     m_MailContent.clear();  
  114.     m_iMailContentPos = 0;  
  115.     ConstructHead(strSubject, strMailBody);  
  116.     bool bRet = true;  
  117.     CURL *curl;  
  118.     CURLM *mcurl;  
  119.     int still_running = 1;  
  120.     struct timeval mp_start;  
  121.     char mp_timedout = 0;  
  122.     struct curl_slist* rcpt_list = NULL;  
  123.   
  124.     curl_global_init(CURL_GLOBAL_DEFAULT);  
  125.   
  126.     curl = curl_easy_init();  
  127.     if (!curl)  
  128.     {  
  129.         printf("Init curl failed!\n");  
  130.         return false;  
  131.     }  
  132.   
  133.     mcurl = curl_multi_init();  
  134.     if (!mcurl)  
  135.     {  
  136.         printf("Init mcurl failed!\n");  
  137.         return false;  
  138.     }  
  139.     for(std::list<std::string >::iterator it = m_RecipientList.begin(); it != m_RecipientList.end();it++)  
  140.     {  
  141.         rcpt_list = curl_slist_append(rcpt_list, it->c_str());  
  142.     }  
  143.       
  144.     if(m_strSmtpServer == "" || m_iPort <= 0)  
  145.     {  
  146.         printf("smtp server couldn't be empty, or port must be large than 0!\n");  
  147.           
  148.         curl_slist_free_all(rcpt_list);  
  149.         curl_multi_cleanup(mcurl);  
  150.         curl_easy_cleanup(curl);  
  151.         curl_global_cleanup();  
  152.         return false;  
  153.     }  
  154.     std::string strUrl = "smtp://" + m_strSmtpServer;  
  155.     strUrl += ":";  
  156.     char cPort[10];  
  157.     memset(cPort, 0, 10);  
  158.     sprintf(cPort, "%d", m_iPort);  
  159.     strUrl += cPort;  
  160.     curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());  
  161.       
  162.     if(m_strUser != "")  
  163.     {  
  164.         curl_easy_setopt(curl, CURLOPT_USERNAME, m_strUser.c_str());  
  165.     }  
  166.     if(m_strPsw != "")  
  167.     {  
  168.         curl_easy_setopt(curl, CURLOPT_PASSWORD, m_strPsw.c_str());  
  169.     }  
  170.       
  171.     curl_easy_setopt(curl, CURLOPT_READFUNCTION, &CSendMail::read_callback);  
  172.       
  173.     if(m_strMailFrom == "")  
  174.     {  
  175.         printf("Mail from address couldn't be empty!\n");  
  176.           
  177.         curl_slist_free_all(rcpt_list);  
  178.         curl_multi_cleanup(mcurl);  
  179.         curl_easy_cleanup(curl);  
  180.         curl_global_cleanup();  
  181.         return false;  
  182.     }  
  183.     curl_easy_setopt(curl, CURLOPT_MAIL_FROM, m_strMailFrom.c_str());  
  184.     curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpt_list);  
  185.     curl_easy_setopt(curl, CURLOPT_USE_SSL, (long) CURLUSESSL_ALL);  
  186.     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);  
  187.     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);  
  188.     curl_easy_setopt(curl, CURLOPT_READDATA, this);  
  189.     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);  
  190.     curl_easy_setopt(curl, CURLOPT_SSLVERSION, 0L);  
  191.     curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);  
  192.     curl_multi_add_handle(mcurl, curl);  
  193.   
  194.     mp_timedout = 0;  
  195.     mp_start = tvnow();  
  196.   
  197.     /* we start some action by calling perform right away */  
  198.     curl_multi_perform(mcurl, &still_running);  
  199.   
  200.     while (still_running) {  
  201.         struct timeval timeout;  
  202.         int rc; /* select() return code */  
  203.   
  204.         fd_set fdread;  
  205.         fd_set fdwrite;  
  206.         fd_set fdexcep;  
  207.         int maxfd = -1;  
  208.   
  209.         long curl_timeo = -1;  
  210.   
  211.         FD_ZERO(&fdread);  
  212.         FD_ZERO(&fdwrite);  
  213.         FD_ZERO(&fdexcep);  
  214.   
  215.         /* set a suitable timeout to play around with */  
  216.         timeout.tv_sec = 1;  
  217.         timeout.tv_usec = 0;  
  218.   
  219.         curl_multi_timeout(mcurl, &curl_timeo);  
  220.         if (curl_timeo >= 0) {  
  221.             timeout.tv_sec = curl_timeo / 1000;  
  222.             if (timeout.tv_sec > 1)  
  223.                 timeout.tv_sec = 1;  
  224.             else  
  225.                 timeout.tv_usec = (curl_timeo % 1000) * 1000;  
  226.         }  
  227.   
  228.         /* get file descriptors from the transfers */  
  229.         curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);  
  230.   
  231.         /* In a real-world program you OF COURSE check the return code of the 
  232.            function calls.  On success, the value of maxfd is guaranteed to be 
  233.            greater or equal than -1.  We call select(maxfd + 1, ...), specially in 
  234.            case of (maxfd == -1), we call select(0, ...), which is basically equal 
  235.            to sleep. */  
  236.   
  237.         rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);  
  238.   
  239.         if (tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {  
  240.             fprintf(stderr, "ABORTING TEST, since it seems "  
  241.                     "that it would have run forever.\n");  
  242.             bRet = false;  
  243.             break;  
  244.         }  
  245.   
  246.         switch (rc) {  
  247.             case -1:  
  248.                 /* select error */  
  249.                 printf("select error\n");  
  250.                 bRet = false;  
  251.                 break;  
  252.             case 0: /* timeout */  
  253.                 printf("time out, retry again!\n");  
  254.                 curl_multi_perform(mcurl, &still_running);  
  255.                 break;  
  256.             default: /* action */  
  257.                 curl_multi_perform(mcurl, &still_running);  
  258.                 break;  
  259.         }  
  260.     }  
  261.   
  262.     curl_multi_remove_handle(mcurl, curl);  
  263.     curl_slist_free_all(rcpt_list);  
  264.     curl_multi_cleanup(mcurl);  
  265.     curl_easy_cleanup(curl);  
  266.     curl_global_cleanup();  
  267.     return bRet;  
  268. }  
  269.   
  270. bool CSendMail::SendMail(const std::string & strSubject, const char* pMailBody, int len)  
  271. {  
  272.     std::string strMailContent;  
  273.     strMailContent.append(pMailBody, len);  
  274.       
  275.     return SendMail(strSubject, strMailContent);  
  276. }  
  277.   
  278. bool CSendMail::SendMail(const std::string& strUser, const std::string& strPsw, const std::string& strSmtpServer, int iPort, std::list<std::string>& recipientList, const std::string& strMailFrom, const std::string& strSubject, const std::string& strMailBody)  
  279. {  
  280.     m_strUser = strUser;  
  281.     m_strPsw = strPsw;  
  282.     m_strSmtpServer = strSmtpServer;  
  283.     m_iPort = iPort;  
  284.     std::copy(recipientList.begin(), recipientList.end(), m_RecipientList.begin());  
  285.     m_strMailFrom = strMailFrom;  
  286.       
  287.     return SendMail(strSubject, strMailBody);  
  288.       
  289. }  
  290.   
  291. bool CSendMail::SendMail(const std::string& strUser, const std::string& strPsw, const std::string& strSmtpServer, int iPort, std::list<std::string>& recipientList, const std::string& strMailFrom, const std::string& strSubject, const char* pMailBody, int len)  
  292. {  
  293.     std::string strMailContent;  
  294.     strMailContent.append(pMailBody, len);  
  295.     return SendMail(strUser, strPsw, strSmtpServer, iPort, recipientList, strMailFrom, strSubject, strMailContent);  
  296. }  
  297.   
  298. bool CSendMail::SendMail(const std::string& strUser, const std::string& strPsw, const std::string& strSmtpServer, int iPort, const std::string& strMailTo, const std::string& strMailFrom, const std::string& strSubject, const std::string& strMailBody)  
  299. {  
  300.     std::list<std::string> recipientList;  
  301.     recipientList.push_back(strMailTo);  
  302.       
  303.     return SendMail(strUser, strPsw, strSmtpServer, iPort, recipientList, strMailFrom, strSubject, strMailBody);  
  304. }  
  305.   
  306. bool CSendMail::SendMail(const std::string& strUser, const std::string& strPsw, const std::string& strSmtpServer, int iPort, const std::string& strMailTo, const std::string& strMailFrom, const std::string& strSubject, const char* pMailBody, int len)  
  307. {  
  308.     std::string strMailContent;  
  309.     strMailContent.append(pMailBody, len);  
  310.     return SendMail(strUser, strPsw, strSmtpServer, iPort, strMailTo, strMailFrom, strSubject, strMailContent);  
  311.   
  312. }  

这个是通过libcurl multi接口来做的,所以使用的时候记得要libcurl库的支持。