基於jwSMTP的C++傳送Email的Demo

工程師WWW發表於2014-08-13

由於業務上存在傳送報警郵件的需求,一直想找一個簡單易用的傳送Email的C++庫。


終於找到了,它就是jwSTMP(http://sourceforge.net/projects/jwsmtp/)。


最新的jwSTMP版本(1.32.15)能夠跨平臺(BSD、Linux和Windows等)的支援以C++程式碼或者C++庫的形式編碼傳送Email。它可以傳送附件、支援多個收件人(最多100個),支援CC(抄送)和BCC(隱藏性抄送);同樣的,它也支援以HTML的方式傳送郵件。


我們知道傳送Email有POP3和SMTP兩種方式。目前jwSTMP不支援POP3的方式。但是它提供了MX lookup方式,即直接得到目的地址的郵件交換伺服器地址(MX)將郵件傳送出去。


現在說說如何使用吧。


下載和編譯。請到sourceforge上將它下載下來。如果使用Windows平臺,直接點選工程檔案即可(預設是VC6的工程檔案,我使用VS2008將工程檔案轉化也是可以的)然後編譯即可;如果使用Linux,請執行通行的三部曲:

./configure
make
make install


程式碼修改。適合中國人的習慣,我將使用163的郵箱服務展示jwSMTP的用法。

最簡單的demo1.cpp檔案如下:

  1. #include <iostream>  
  2. // 由於標頭檔案所處的位置是jwsmtp-1.32.15\jwsmtp\jwsmtp,所以,需要注意include的路徑  
  3. #include "jwsmtp/jwsmtp.h"  
  4.   
  5. int main(int argc, char* argv[])  
  6. {  
  7.    jwsmtp::mailer m("testjwstmp@163.com"/*接收者*/"testjwstmp@163.com"/*傳送者*/"這裡填寫郵件標題",  
  8.                     "這裡填寫郵件內容""smtp.163.com",  
  9.                     jwsmtp::mailer::SMTP_PORT, false);  
  10.   
  11.    //經過測試,163支援的auth認證是PLAIN模式  
  12.    m.authtype(jwsmtp::mailer::PLAIN);  
  13.   
  14.    //這裡輸入認證使用者名稱,注意哦,需要是***@163.com的使用者名稱  
  15.    m.username("testjwstmp@163.com");  
  16.    //這裡輸入密碼  
  17.    m.password("******");  
  18.    m.send(); // 這裡傳送郵件,需要注意的是,這裡是同步模式哦!  
  19.    std ::cout << m.response() << std::endl;//這裡返回是否成功,250代表傳送郵件成功;  
  20.    system("pause");  
  21.    return 0;  
  22. }  


需要注意的是,雖然我在測試時傳送在cpp檔案中寫入中文使用163.com傳送是沒有出現亂碼的,但是,在公司中傳送報警郵件則會出現亂碼。為了解決亂碼問題,需要使用網路上有人提供的string s2utfs(const  string&  strSrc)函式進行轉碼為utf8。


  1. #ifndef __CHARSET_CVT__  
  2. #define __CHARSET_CVT__  
  3. #include  <string>  
  4. #include  <clocale>  
  5.   
  6. std::string ws2s(const std::wstring& ws)  
  7. {  
  8.     std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";   
  9.     setlocale(LC_ALL, "chs");  
  10.     const wchar_t* _Source = ws.c_str();  
  11.     size_t _Dsize = 2 * ws.size() + 1;  
  12.     char *_Dest = new char[_Dsize];  
  13.     memset(_Dest, 0, _Dsize);  
  14.     wcstombs(_Dest, _Source, _Dsize);  
  15.     std::string result = _Dest;  
  16.     delete [] _Dest;  
  17.     setlocale(LC_ALL, curLocale.c_str());  
  18.     return result;  
  19. }  
  20.   
  21. std::wstring s2ws(const std::string& s)   
  22. {  
  23.     setlocale(LC_ALL, "chs");  
  24.     const char* _Source = s.c_str();  
  25.     size_t _Dsize = s.size() + 1;  
  26.     wchar_t* _Dest = new wchar_t[_Dsize];  
  27.     wmemset(_Dest, 0, _Dsize);  
  28.     int nret = mbstowcs(_Dest, _Source, _Dsize);  
  29.     std::wstring result = _Dest;  
  30.     delete [] _Dest;  
  31.     setlocale(LC_ALL, "C");  
  32.   
  33.     return result;  
  34. }  
  35.   
  36. std::wstring UTF2Uni(const char* src, std::wstring &t)   
  37. {  
  38.     if (src == NULL)  
  39.     {  
  40.         return L"";  
  41.     }  
  42.   
  43.     int size_s = strlen(src);  
  44.     int size_d = size_s + 10;  
  45.   
  46.     wchar_t *des = new wchar_t[size_d];  
  47.     memset(des, 0, size_d * sizeof(wchar_t));  
  48.   
  49.     int s = 0, d = 0;  
  50.     bool toomuchbyte = true//set true to skip error prefix.  
  51.   
  52.     while (s  < size_s && d  < size_d)  
  53.     {  
  54.         unsigned char c = src[s];  
  55.         if ((c & 0x80) == 0)  
  56.         {  
  57.             des[d++] += src[s++];  
  58.         }  
  59.         else if((c & 0xE0) == 0xC0)  /// < 110x-xxxx 10xx-xxxx  
  60.         {  
  61.             WCHAR &wideChar = des[d++];  
  62.             wideChar  = (src[s + 0] & 0x3F)<<6;  
  63.             wideChar |= (src[s + 1] & 0x3F);  
  64.   
  65.             s += 2;  
  66.         }  
  67.         else if((c & 0xF0) == 0xE0)  /// < 1110-xxxx 10xx-xxxx 10xx-xxxx  
  68.         {  
  69.             WCHAR &wideChar = des[d++];  
  70.   
  71.             wideChar  = (src[s + 0] & 0x1F)<<12;  
  72.             wideChar |= (src[s + 1] & 0x3F)<<6;  
  73.             wideChar |= (src[s + 2] & 0x3F);  
  74.   
  75.             s += 3;  
  76.         }  
  77.         else if((c & 0xF8) == 0xF0)  /// < 1111-0xxx 10xx-xxxx 10xx-xxxx 10xx-xxxx  
  78.         {  
  79.             WCHAR &wideChar = des[d++];  
  80.   
  81.             wideChar  = (src[s + 0] & 0x0F)<<18;  
  82.             wideChar  = (src[s + 1] & 0x3F)<<12;  
  83.             wideChar |= (src[s + 2] & 0x3F)<<6;  
  84.             wideChar |= (src[s + 3] & 0x3F);  
  85.   
  86.             s += 4;  
  87.         }  
  88.         else  
  89.         {  
  90.             WCHAR &wideChar = des[d++]; /// < 1111-10xx 10xx-xxxx 10xx-xxxx 10xx-xxxx 10xx-xxxx  
  91.   
  92.             wideChar  = (src[s + 0] & 0x07)<<24;  
  93.             wideChar  = (src[s + 1] & 0x3F)<<18;  
  94.             wideChar  = (src[s + 2] & 0x3F)<<12;  
  95.             wideChar |= (src[s + 3] & 0x3F)<<6;  
  96.             wideChar |= (src[s + 4] & 0x3F);  
  97.   
  98.             s += 5;  
  99.         }  
  100.     }  
  101.   
  102.     t = des;  
  103.     delete[] des;  
  104.     des = NULL;  
  105.   
  106.     return t;  
  107. }  
  108.   
  109. int Uni2UTF(const std::wstring& strRes, char *utf8, int nMaxSize)  
  110. {  
  111.     if (utf8 == NULL)  
  112.     {  
  113.         return -1;  
  114.     }  
  115.     int len = 0;  
  116.     int size_d = nMaxSize;  
  117.   
  118.     for (std::wstring::const_iterator it = strRes.begin(); it != strRes.end(); ++it)  
  119.     {   
  120.         wchar_t wchar = *it;   
  121.         if (wchar  < 0x80)   
  122.         {  
  123.             //length = 1;  
  124.             utf8[len++] = (char)wchar;  
  125.         }  
  126.         else if(wchar  < 0x800)  
  127.         {  
  128.             //length = 2;  
  129.             if (len + 1 >= size_d)  
  130.             {  
  131.                 return -1;  
  132.             }  
  133.   
  134.             utf8[len++] = 0xc0 | ( wchar >> 6 );  
  135.             utf8[len++] = 0x80 | ( wchar & 0x3f );  
  136.         }  
  137.         else if(wchar  < 0x10000)  
  138.         {  
  139.             //length = 3;  
  140.             if (len + 2 >= size_d)  
  141.             {  
  142.                 return -1;  
  143.             }  
  144.   
  145.             utf8[len++] = 0xe0 | ( wchar >> 12 );  
  146.             utf8[len++] = 0x80 | ( (wchar >> 6) & 0x3f );  
  147.             utf8[len++] = 0x80 | ( wchar & 0x3f );  
  148.         }  
  149.         else if( wchar  < 0x200000)  
  150.         {  
  151.             //length = 4;   
  152.             if (len + 3 >= size_d)  
  153.             {  
  154.                 return -1;  
  155.             }  
  156.   
  157.             utf8[len++] = 0xf0 | ( (int)wchar >> 18 );  
  158.             utf8[len++] = 0x80 | ( (wchar >> 12) & 0x3f );  
  159.             utf8[len++] = 0x80 | ( (wchar >> 6) & 0x3f );  
  160.             utf8[len++] = 0x80 | ( wchar & 0x3f );  
  161.         }  
  162.     }  
  163.     return len;  
  164. }  
  165.   
  166. std::string s2utfs(const std::string& strSrc)   
  167. {  
  168.     std::string strRes;  
  169.     std::wstring wstrUni = s2ws(strSrc);  
  170.   
  171.     char* chUTF8 = new char[wstrUni.length() * 3];  
  172.     memset(chUTF8, 0x00, wstrUni.length() * 3);  
  173.     Uni2UTF(wstrUni, chUTF8, wstrUni.length() * 3);  
  174.     strRes = chUTF8;   
  175.     delete [] chUTF8;  
  176.     return strRes;  
  177. }  
  178.   
  179. std::string utfs2s(const std::string& strutf)   
  180. {  
  181.     std::wstring wStrTmp;  
  182.     UTF2Uni(strutf.c_str(), wStrTmp);  
  183.     return ws2s(wStrTmp);  
  184. }  
  185.   
  186. #endif  



給多人傳送HTML的demo2.cpp檔案如下

  1. #include <iostream>  
  2. // 由於標頭檔案所處的位置是jwsmtp-1.32.15\jwsmtp\jwsmtp,所以,需要注意include的路徑  
  3. #include "jwsmtp/jwsmtp.h"  
  4.   
  5. std::string html("<html>"  
  6. "<body>"  
  7. "This is the html part of the message<br><br>"  
  8. "<b>bold</b><br>"  
  9. "<i>italic</i><br>"  
  10. "<font size=\"7\">Large Text</font><br><br>"  
  11. "Or a link: <a href=\"http://johnwiggins.net\">johnwiggins.net</a><br><br>"  
  12. "And an image: <br><img alt=\"an image in email\" src=\"http://johnwiggins.net/jwsmtp/example.png\"><br>"  
  13. "</body>"  
  14. "</html>");  
  15.   
  16. int main(int argc, char* argv[])  
  17. {  
  18.    jwsmtp::mailer m(""/*接收者不填寫*/"testjwstmp@163.com"/*傳送者*/"這裡填寫郵件標題",  
  19.                     "這裡填寫郵件內容""smtp.163.com",  
  20.                     jwsmtp::mailer::SMTP_PORT, false);  
  21.   
  22.    //新增多個接收者  
  23.    m.addrecipient("testjwstmp@163.com");  
  24.    m.addrecipient("testjwstmp@gmail.com");  
  25.    m.addrecipient("testjwstmp@qq.com");  
  26.   
  27.    //新增HTML的傳送內容,它會替換建構函式中的“這裡填寫郵件內容”  
  28.    m.setmessageHTML(html);  
  29.   
  30.    //經過測試,163支援的auth認證是PLAIN模式  
  31.    m.authtype(jwsmtp::mailer::PLAIN);  
  32.   
  33.    //這裡輸入認證使用者名稱,注意哦,需要是***@163.com的使用者名稱  
  34.    m.username("testjwstmp@163.com");  
  35.    //這裡輸入密碼  
  36.    m.password("******");  
  37.    m.send(); // 這裡傳送郵件,需要注意的是,這裡是同步模式哦!  
  38.    std ::cout << m.response() << std::endl;//這裡如果展示的是250,代表傳送郵件成功  
  39.    system("pause");  
  40.    return 0;  
  41. }  


附上傳送Email的返回碼

郵件服務返回程式碼含義  
500   格式錯誤,命令不可識別(此錯誤也包括命令列過長)  
501   引數格式錯誤  
502   命令不可實現  
503   錯誤的命令序列  
504   命令引數不可實現  
211   系統狀態或系統幫助響應  
214   幫助資訊  
220     服務就緒  
221     服務關閉傳輸通道  
421     服務未就緒,關閉傳輸通道(當必須關閉時,此應答可以作為對任何命令的響應)  
250   要求的郵件操作完成  
251   使用者非本地,將轉發向  
450   要求的郵件操作未完成,郵箱不可用(例如,郵箱忙)  
550   要求的郵件操作未完成,郵箱不可用(例如,郵箱未找到,或不可訪問)  
451   放棄要求的操作;處理過程中出錯  
551   使用者非本地,請嘗試  
452   系統儲存不足,要求的操作未執行  
552   過量的儲存分配,要求的操作未執行  
553   郵箱名不可用,要求的操作未執行(例如郵箱格式錯誤)  
354   開始郵件輸入,以.結束  
554   操作失敗  
535   使用者驗證失敗  
235   使用者驗證成功  
334   等待使用者輸入驗證信

相關文章