![]() |
SMTP命令 | 命令說明 |
HELLO <domain> <CRLF> | 識別發送方到接收SMTP的一個HELLO命令 |
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> | 查詢服務器支持什么命令 |
應答碼 | 說明 |
501 | 參數格式錯誤 |
502 | 命令不可實現 |
503 | 錯誤的命令序列 |
504 | 命令參數不可實現 |
211 | 系統狀態或系統幫助響應 |
214 | 幫助信息 |
220 | <domain>服務就緒 |
221 | <domain>服務關閉 |
421 | <domain>服務未就緒,關閉傳輸信道 |
250 | 要求的郵件操作完成 |
251 | 用戶非本地,將轉發向<forward-path> |
450 | 要求的郵件操作未完成,郵箱不可用 |
550 | 要求的郵件操作未完成,郵箱不可用 |
451 | 放棄要求的操作;處理過程中出錯 |
551 | 用戶非本地,請嘗試<forward-path> |
452 | 系統存儲不足,要求的操作未執行 |
552 | 過量的存儲分配,要求的操作未執行 |
553 | 郵箱名不可用,要求的操作未執行 |
354 | 開始郵件輸入,以"."結束 |
554 | 操作失敗 |
R:220 sina.com Simple Mail Transfer Service Ready S:HELLO sohu.com R:250 sina.com S:MAIL FROM:<langrui@sohu.com> R:250 OK S:RCPT TO:<renping@sina.com> R:250 OK S:DATA R:354 Start mail input;end with "<CRLF>.<CRLF>" S:…… R:250 OK S:QUIT R:221 sina.com Service closing transmission channel |
//郵件頭準備 strTemp = _T( "From: " ) + m_strFrom; file://發件人地址 add_header_line( (LPCTSTR)strTemp ); strTemp = _T( "To: " ) + m_strTo; file://收件人地址 add_header_line( (LPCTSTR)strTemp ); m_tDateTime = m_tDateTime.GetCurrentTime();//發送時間 strTemp = _T( "Data: " ); strTemp += m_tDateTime.Format( "%a, %d %b %y %H:%M:%S %Z" ); add_header_line( (LPCTSTR)strTemp ); strTemp = _T( "Subject: " ) + m_strSubject; file://主題 add_header_line( (LPCTSTR)strTemp ); file://郵件頭結束 m_strHeader += _T( "\r\n" ); file://郵件體準備 if( m_strBody.Right( 2 ) != _T( "\r\n" ) ) file://確認最后以回車換行結束 m_strBody += _T( "\r\n" ); |
BOOL CSMTP::get_response( UINT response_expected )//輸入參數為希望的應答碼 { …… // m_wsSMTPServer為CSocket的類對象,調用Receive()將應答碼接收到緩存 // response_buf中 m_wsSMTPServer.Receive( response_buf, RESPONSE_BUFFER_SIZE ) sResponse = response_buf; sscanf( (LPCTSTR)sResponse.Left( 3 ), _T( "%d" ), &response ); pResp = &response_table[ response_expected ]; file://檢驗收到的應答碼是否是所希望得到的 if( response != pResp->nResponse ) { ……//不相等的話進行錯誤處理 return FALSE; } return TRUE; } |
//格式化并發送HELLO命令,并接收、驗證服務器應答碼 gethostname( local_host, 80 ); sHello.Format( _T( "HELO %s\r\n" ), local_host ); m_wsSMTPServer.Send( (LPCTSTR)sHello, sHello.GetLength() ); if( !get_response( GENERIC_SUCCESS ) ) file://檢驗應答碼是否為250 { …… return FALSE; } file://格式化并發送MAIL命令,并接收、驗證服務器應答碼 sFrom.Format( _T( "MAIL From: <%s>\r\n" ), (LPCTSTR)msg->m_strFrom ); m_wsSMTPServer.Send( (LPCTSTR)sFrom, sFrom.GetLength() ); if( !get_response( GENERIC_SUCCESS ) ) file://檢驗應答碼是否為250 return FALSE; file://格式化并發送RCPT命令,并接收、驗證服務器應答碼 sEmail=(LPCTSTR)msg->m_strTo; sTo.Format( _T( "RCPT TO: <%s>\r\n" ), (LPCTSTR)sEmail ); m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() ); if(!get_response( GENERIC_SUCCESS )) file://檢驗應答碼是否為250 return FALSE; file://格式化并發送DATA命令,并接收、驗證服務器應答碼 sTemp = _T( "DATA\r\n" ); m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() ); if( !get_response( DATA_SUCCESS ) ) file://檢驗應答碼是否為354 return FALSE; file://發送根據RFC 822文檔規定格式化過的郵件頭 m_wsSMTPServer.Send( (LPCTSTR)msg->m_strHeader, msg->m_strHeader.GetLength() ); …… file://發送根據RFC 822文檔規定格式化過的郵件體 sTemp = msg->m_strBody; if( sTemp.Left( 3 ) == _T( ".\r\n" ) ) sTemp = _T( "." ) + sTemp; while( (nPos = sTemp.Find( szBad )) > -1 ) { sCooked = sTemp.Mid( nStart, nPos ); sCooked += szGood; sTemp = sCooked + sTemp.Right( sTemp.GetLength() - (nPos + nBadLength) ); } m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() ); file://發送內容數據結束標志"<CRLF>.<CRLF>",并檢驗返回應答碼 sTemp = _T( "\r\n.\r\n" ); m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() ); if( !get_response( GENERIC_SUCCESS ) )// 檢驗應答碼是否為250 return FALSE; |
原文轉自:http://www.anti-gravitydesign.com