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; |