用C写一发送邮件的程序_第1页
用C写一发送邮件的程序_第2页
用C写一发送邮件的程序_第3页
免费预览已结束,剩余8页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、用 C+ 写一发送邮件的程序前言 电子邮件服务作为 Internet 上应用最多和最 广的服务项目得到了非常广泛的应用,在网络应用中也起到 非常重要的作用。如同其他的网络服务,电子邮件系统也有 其使用的传输协议,包括 SMTP ( Simple Mail Transfer Protocol ,简单邮件传输协议) 、POP( Post Office Protocol , 邮局协议)和 IMAP ( Internet Message Access Protocal , 消息访问协议) 等,这些协议应用于电子邮件的发送和接收。 一些邮件处理软件如 OutLook Express 和 FoxMail

2、等就是按 照 SMTP 和 POP3 协议结合 Windows Sockets 套接字进行 设计来收发邮件的。 本文以 SMTP 协议为研究对象, 在 Visual C+ 6.0 编程环境下按照 SMTP 协议通过套接字发送 SMTP 命令,接收并处理邮件服务器的反馈信息,从而实现对电子 邮件的发送。 SMTP 协议的通讯模型和会话流程 SMTP 协议通讯模型 SMTP 协议是 TCP/IP 协议族中的 一员,主要对如何将电子邮件从发送方地址传送到接收方地 址,也即是对传输的规则做了规定。 SMTP 协议的通信模型 并不复杂,主要工作集中在发送 SMTP 和接收 SMTP 上: 首先针对用户发

3、出的邮件请求, 由发送 SMTP 建立一条连接 到接收 SMTP 的双工通讯链路,这里的接收 SMTP 是相对 于发送 SMTP 而言的, 实际上它既可以是最终的接收者也可以是中间传送者。 发送 SMTP 负责向接收 SMTP 发送 SMTP 命令, 而接收 SMTP 则负责接收并反馈应答。 可大致用下面 的通讯模型示意图来表示: SMTP 协议的命令和应答 从前面的通讯模型可以看出 SMTP 协议在发送 SMTP 和接 收 SMTP 之间的会话是靠发送 SMTP 的 SMTP 命令和接收 SMTP 反馈的应答来完成的。 在通讯链路建立后, 发送 SMTP 发送 MAIL 命令指令邮件发送者,

4、 若接收 SMTP 此时可以接 收邮件则作出 OK 的应答, 然后发送 SMTP 继续发出 RCPT 命令以确认邮件是否收到,如果接收到就作出 OK 的应答, 否则就发出拒绝接收应答,但这并不会对整个邮件操作造成 影响。双方如此反复多次,直至邮件处理完毕。 SMTP 协议 共包含 10 个 SMTP 命令,列表如下: SMTP 命令 命令说 明HELLO v domain > v CRLF > 识别发送方到接收 SMTP 的一个 HELLO 命令MAIL FROM: v reverse-path >v CRLF > v reverse-path >为发送者地址。此

5、命令告诉接收方一个新邮件发送的开始, 并对所有的状态和缓冲区进行初始化。此命令开始一个邮件 传输处理,最终完成将邮件数据传送到一个或多个邮箱中。 RCPT TO: v forward-path >v CRLF > v forward-path > 标识各个邮件接收者的地址DATA v CRLF > 接收SMTP将把其后的行为看作邮件数据去处理,以vCRLF > . v CRLF >标识数据的结尾。REST v CRLF > 退出/复位当前的邮件传输NOOP v CRLF > 要求接收 SMTP仅做0K应答。(用于测 试)QUIT v CRLF &

6、gt; 要求接收SMTP返回一个OK应答并关闭 传输。VRFY v string > v CRLF > 验证指定的邮箱是否存在,由于安全因素,服务器多禁止此命令。EXPN v string > v CRLF > 验证给定的邮箱列表是否存 在,扩充邮箱列表,也常禁止使用。HELP vCRLF > 查询服务器支持什么命令注:v CRLF>为回车、换行,ASCII码分别为13、10 (十进制)。SMTP 协议的每一个命令都会返回一个应答码,应答码的每 一个数字都是有特定含义的,如第一位数字为 2 时表示命令 成功;为 5 表失败; 3 表没有完成。一些较复杂的邮件

7、程序 利用该特点,首先检查应答码的首数字,并根据其值来决定 下一步的动作。下面将 SMTP 的应答码列表如下: 应答码 说明501 参数格式错误502 命令不可实现503 错误的命令序列504 命令参数不可实现211 系统状态或系统帮助响应214 帮助信息220 v domain 服务就绪221 v domain 服务关闭421 vdomain 服务未就绪,关闭传输信道250 要求的邮件操作完成251用户非本地,将转发向v forward-path 450 要求的邮件操作未完成,邮箱不可用550 要求的邮件操作未完成,邮箱不可用451 放弃要求的操作;处理过程中出错551用户非本地,请尝试v

8、forward-path 452 系统存储不足,要求的操作未执行552 过量的存储分配,要求的操作未执行553 邮箱名不可用,要求的操作未执行354 开始邮件输入,以 "." 结束554 操作失败在应用程序中使用 SMTP 协议 SMTP 协议的会话流程 在进行程序设计之前有必要弄清 SMTP 协议的会话流程, 其 实前面介绍的内容已经可以大致勾勒出用 SMTP 发送邮件 的框架了,对于一次普通的邮件发送,其过程大致为:先建 立 TCP 连接,随后客户端发出 HELLO 命令以标识发件人自 己的身份,并继续由客户端发送 MAIL 命令,如服务器应答 为"OK&qu

9、ot;,可继续发送 RCPT命令来标识电子邮件的收件人, 在这里可以有多个 RCPT 行,而服务器端则表示是否愿意为 收件人接受该邮件。在双方协商结束后,用命令 DATA 将邮 件发送出去,其中对表示结束的 "."也一并发送出去。随后结 束本次发送过程,以 QUIT 命令退出。下面通过一个实例, 从 发送邮件到 来更 详细直观地描述此会话流程: R:220 Simple Mail Transfer Service Ready S:HELLO R:250 S:MAIL FROM: v >R:250 OKS:RCPT TO: v >R:250 OKS:DATAR:3

10、54 Start mail input;end with " vCRLF>.vCRLF >" S:……R:250 OK S:QUITR:221 Service closing transmission channel 邮件的格式化由于电子邮件结构上的特殊性,在传输 时是不能当作简单的文本来直接处理的,而必须按照一定的 格式对邮件头和邮件体进行格式化处理之后才可以被发送。 需要进行格式化的部分主要有:发件人地址、收件人地址、 主题和发送日期等。在 RFC 文档的 RFC 822 里对邮件的格 式化有详尽的说明,有关详情请参阅

11、该文档。下面通过 VC+6.0 按照 RFC 822 文档规定将格式化邮件的部分编写 如下(部分代码) : /邮件头准备 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();/ 发送时间

12、 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( "rn" );file:/ 邮件体准

13、备if( m_strBody.Right( 2 ) != _T( "rn" ) ) file:/ 确认最后以回车换行结束m_strBody += _T( "rn" ); 其中 add_header_line(LPCTSTR szHeaderLine) 函数用于把 szHeaderLine 指向的字串追加到 m_strHeader 后面。其中, 格式化后的邮件头保存在 m_strHeader 里,格式化后的邮件 体保存在 m_strBody 中。 由 Socket 套接字为 SMTP 提供网络通讯基础 许多网络程序都是采用 Socket 套接 字实现的,对

14、于一些标准的网络协议如 HTTP 、FTP 和 SMTP 等协议的编程也是基于套接字程序的,只是端口号不再是随 意设定而要由协议来指定,比如 HTTP 端口在 80 、FTP 是 21,而SMTP则是25。Socket只是提供在指定的端口上同 指定的服务器从事网络上的通讯能力,至于客户和服务器之 间是如何通讯的则由网络协议来规定,这对于套接字是完全 透明的。因此可以使用 Socket 套接字为程序提供网络通讯 的能力,而对于网络通讯连路建立好之后采取什么样的通讯 应答则要按 SMTP 协议的规定去执行了。 Socket 套接字网 络编程方面的文章资料非常丰富,限于本文篇幅,在此不再 赘述,有关

15、详情请参阅相关文档。为简便起见,没有采用编 写较复杂的 Windows Sockets API 进行编程, 而是使用经过 较好封装的 MFC 的 CSocket 类。在正式使用套接字之前, 也要先用 AfxSocketInit() 函数对套接字进行初始化,然后用 Create() 创建套接字对象,并由该套接字通过 Connect () 建立同邮件服务器的连接。如果一切正常,再后续的工作中 就是遵循 SMTP 协议的约定来使用 Send ()、 Receive() 函 数来发送 SMTP 命令和接收邮件服务器发来的应答码以完 成对邮件的传送。 SMTP 会话应答的实现 在同邮 件服务器建立好链路

16、连接后就可以按前面介绍过的会话流 程进行程序设计了, 对于 SMTP 命令的发送, 可按命令格式 将其组帧完毕后用 CSocket 类的 Send() 函数将其发送到服 务器,并通过 CSocket 类的 Receive() 函数接收从邮件服务 器发来的应答码, 并根据 SMTP 协议的应答码表对其做出响 应的处理。下面是用于接收应答码的函数 get_response() 的 部分实现代码: BOOL CSMTP:get_response( UINT response_expected )/ 输入参数为希望的应答码 ……/ m_wsSMTPServer

17、为 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(

18、response != pResp- > “Response )……/ 不相等的话进行错误处理return FALSE;return TRUE; 会话的各个部分比较类似,都是命令-应答方式,而且均成对出现,下面是本文的重点也是实现的关键部分 -在 程序控制下完成对 SMTP 命令的格式化以及对命令的发送 和对邮件服务器应答码的检验处理:/ 格式化并发送HELLO 命令,并接收、验证服务器应答码 gethostname( local_host, 80 );sHello.Format( _T( "HELO %srn" ), loca

19、l_host ); m_wsSMTPServer.Send( (LPCTSTR)sHello, sHello.GetLength() );if( !get_response( GENERIC_SUCCESS ) ) file:/ 检验应答 码是否为 250……return FALSE;file:/ 格式化并发送 MAIL 命令,并接收、验证服务器应答码sFrom.Format( _T( "MAIL From:v %s >rn"),(LPCTSTR)msg- > m_strFrom ); m_wsSMTPServer.Sen

20、d( (LPCTSTR)sFrom, sFrom.GetLength() );if( !get_response( GENERIC_SUCCESS ) ) file:/ 检验应答 码是否为 250return FALSE;file:/ 格式化并发送 RCPT 命令, 并接收、 验证服务器应答码 sEmail=(LPCTSTR)msg- > m_strTo;sTo.Format( _T( "RCPT TO:v%s>rn" ),(LPCTSTR)sEmail );m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() )

21、;if(!get_response( GENERIC_SUCCESS ) file:/ 检验应答码 是否为 250return FALSE;file:/ 格式化并发送 DATA 命令, 并接收、 验证服务器应答码 sTemp = _T( "DATArn" );m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );if( !get_response( DATA_SUCCESS ) ) file:/ 检验应答码是 否为 354 return FALSE;file:/发送根据RFC 822文档规定格式化过的邮件头m_ws

22、SMTPServer.Send( (LPCTSTR)msg- > m_strHeader, msg- > m_strHeader.GetLength();……file:/发送根据RFC 822文档规定格式化过的邮件体 sTemp = msg- > m_strBody;if( sTemp.Left( 3 ) = _T( ".rn" ) ) sTemp = _T( "." ) + sTemp;while( (nPos = sTemp.Find( szBad )> -1 )sCooked = sTemp.Mid( nStart, nPos );sCooked += szGood;sTemp = sCo

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论