用C++發郵件

來源:互聯網
上載者:User

      近段時間,實驗室電腦的IP頻繁地改變,搞得想用遠程偷下懶都不行。這時想到的解決方案有:靜態IP,動態網域名稱,自己解決。靜態IP雖然可以自己指定,但一關機後,與對方衝突就完了,作罷。免費的動態網域名稱又要手機認證,也作罷。最後只能自己解決。解決方案是寫一個程式不斷地檢測本機IP,如果改變了,就發郵件通知。檢測本機IP很簡單,就略過。這裡介紹下怎樣發郵件吧。

      發郵件前,需要理解SMTP(Simple Mail Transfer Protocol)。SMTP是電子郵件從客戶機傳輸到伺服器或從某一個伺服器傳輸到另一個伺服器使用的傳輸協議。SMTP 是請求/響應協議,命令和響應都是基於 ASCII 文本,並以 CR 和 LF 符結束。響應包括一個表示返回狀態的三位元字代碼。在 TCP 協議 25 連接埠監聽串連請求。其命令如下:

SMTP命令 命令說明
HELO <domain><CRLF> 識別發送方到接收SMTP的一個HELO命令
AUTH LOGIN<CRLF> 登陸伺服器的命令。在這條命令之後,要發送用Base64編碼後的使用者名稱與密碼進行登陸
MAIL FROM:<reverse-path><CRLF> <reverse-path>為寄件者地址。此命令告訴接收方一個新郵件發送的開始,並對所有的狀態和緩衝區進行初始化。此命令開始一個郵件傳輸處理,最終完成將郵件資料傳送到一個或多個郵箱中。
RCPT TO:<forward-path><CRLF> <forward-path>標識各個郵件接收者的地址
DATA <CRLF> 接收SMTP將把其後的行為看作郵件資料去處理,以<CRLF>.<CRLF>標識資料的結尾。
REST <CRLF> 退出/複位當前的郵件傳輸
NOOP <CRLF> 要求接收SMTP僅做OK應答。(用於測試)
QUIT <CRLF> 要求接收SMTP返回一個OK應答並關閉傳輸。
VRFY <string> <CRLF> 驗證指定的郵箱是否存在,由於安全因素,伺服器多禁止此命令。
EXPN <string> <CRLF> 驗證給定的郵箱列表是否存在,擴充郵箱列表,也常禁止使用。
HELP <CRLF> 查詢服務器支援什麼命令

 

     瞭解了這些命令後,  就可以發郵件了。發一封簡單郵件的互動圖如下,其中郵箱使用163郵箱:

 

       C++發郵件的實現表示如下:

//author: Zero//facade of function send()void Send(SOCKET& s, string& data) {    if( send(s, data.c_str(), data.length(), 0) == SOCKET_ERROR ) {        cerr<<"send data \""<<data<<"\" error"<<endl;    }}//facade of function recv()void Recv(SOCKET& s, char* buf, int len) {    memset(buf, 0, len);    if( recv(s, buf, len, 0) == SOCKET_ERROR ) {        cerr<<"error, while receiving data"<<endl;    }}string Base64Encode(const string& src) {    int i, j, srcLen = src.length();    string dst(srcLen / 3 * 4 + 4, 0);    for(i = 0, j= 0; i <=srcLen - 3; i+=3, j+=4) {        dst[j] = (src[i] & 0xFC) >> 2;        dst[j+1] = ((src[i] & 0x03) << 4) + ((src[i+1] & 0xF0) >> 4);        dst[j+2] = ((src[i+1] & 0x0F) << 2) + ((src[i+2] & 0xC0) >> 6);        dst[j+3] = src[i+2] & 0x3F;    }    if( srcLen % 3 == 1 ) {        dst[j] = (src[i] & 0xFC) >> 2;        dst[j+1] = ((src[i] & 0x03) << 4);        dst[j+2] = 64;        dst[j+3] = 64;        j += 4;    }    else if( srcLen % 3 == 2 ) {        dst[j] = (src[i] & 0xFC) >> 2;        dst[j+1] = ((src[i] & 0x03) << 4) + ((src[i+1] & 0xF0) >> 4);        dst[j+2] = ((src[i+1] & 0x0F) << 2);        dst[j+3] = 64;        j+=4;    }    static unsigned char *base64 = (unsigned char*)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");    for(i = 0; i < j; ++i) {    //map 6 bit value to base64 ASCII character        dst[i] = base64[(int)dst[i]];    }        return dst;}bool SendEmail(const string& smtpServer, const string& username, const string& pw, const string& to, const string& data) {    hostent *ph = gethostbyname(smtpServer.c_str());    if( ph == NULL ) {        cerr<<"no host: "<<smtpServer<<endl;        return false;    }        sockaddr_in sin;    memset(&sin, 0, sizeof(sin));    sin.sin_family = AF_INET;    sin.sin_port = htons(25);    //port of SMTP     memcpy(&sin.sin_addr.S_un.S_addr, ph->h_addr_list[0], ph->h_length);    //connect to the mail server    SOCKET s = socket(PF_INET, SOCK_STREAM, 0);    if( connect(s, (sockaddr*)&sin, sizeof(sin)) ) {        cerr<<"failed to connect the mail server"<<endl;        return false;    }    //    char recvBuffer[1024];    Recv(s, recvBuffer, sizeof(recvBuffer));    //wait for greeting message    Send(s, "HELO " + smtpServer + "\r\n");         Recv(s, recvBuffer, sizeof(recvBuffer));    //should recv "250 OK"    //start to log in        Send(s, (string)"auth login\r\n");    Recv(s, recvBuffer, sizeof(recvBuffer));    //should recv "334 username:"(This is the decode message)        Send(s, Base64Encode(username) + "\r\n");    Recv(s, recvBuffer, sizeof(recvBuffer));    if( string(recvBuffer).substr(0, 3) != "334" ) {        cout<<"username is error!"<<endl;        return false;    }    Send(s, Base64Encode(pw) + "\r\n");    Recv(s, recvBuffer, sizeof(recvBuffer));    if( string(recvBuffer).substr(0, 3) != "235") {        cout<<"password error"<<endl;        return false;    }    //Set sender    Send(s, "mail from:<" + username + ">\r\n");    Recv(s, recvBuffer, sizeof(recvBuffer));    //should recv "250 Mail OK"    //set receiver    Send(s, "rcpt to:<" + to + ">\r\n");    Recv(s, recvBuffer, sizeof(recvBuffer));    //should recv "250 Mail OK"    //send data    Send(s, (string)"data\r\n");    Recv(s, recvBuffer, sizeof(recvBuffer));    //should recv "354 End data with <CR><LF>.<CR><LF>"    Send(s, "to:" + to + "\r\n" + "subject:the newest IP\r\n\r\n" + data + "\r\n.\r\n");    Recv(s, recvBuffer, sizeof(recvBuffer));    Send(s, (string)"quit\r\n");    Recv(s, recvBuffer, sizeof(recvBuffer));    closesocket(s);    return true;}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.