服务热线:
您当前的位置:首页 > 世纪星月刊 > 第8期 (2011年8月)

【技术前沿】邮件程序揭秘

2011/9/19 11:57:33
 

研发部 杨盛海

 

无论是CS结构还是BS结构的程序,经常做客户端程序中发送邮件的功能,需求多种多样,有要求自动发送,有要求弹出邮件客户端,比如Outlook软件,然后在上面填写邮件发送,有单个邮件发送,也有批量发送,有只发送文本内容,还有发送带附件功能,应有尽有。

有关发送邮件的问题,都要涉及到SMTP协议。同样,收邮件要涉及POP3协议。但凡涉及到有关协议的工作必将无比繁琐,包括发邮件,但相对于其它协议来说,还是简单得多。为什么这么说,先看看名字,SMTP(Simple Mail Transfer Protocol)——简单邮件传输协议,这本来就是一个简单的协议。

这个协议规定了一些发送邮件相关的指令,如登录SMTP服务器,告诉服务器发邮件的地址,发送内容,发送附件以及退出等指令。实际上真正执行这些指令的还是SMTP服务器。最终,如何发送邮件的问题归结为如何组织SMTP指令,并发往SMTP服务器的问题。至于如何在自己的网站上做出一个邮件服务器来,那是另外一个比简单发送邮件功能要复杂得多的问题了。

目前互联网上有很多可以选择的邮件服务器,如新浪、163HotmailGmail等,当然大多数企业规定必须使用公司的邮箱以及服务器,所有这些服务器必然都包括一个SMTP服务器,举例,新浪在中国的发邮件服务器为smtp.sina.com.cn

有了smtp服务器,问题相对少了,下一步,组织SMTP指令。首先,必须要连接服务器,这时,服务器返回一个代码为220的信息,只要记住有220即可,其它乱七八糟的信息对我们没什么关系。发送一个HELO指令,后面带一个参数,可以是服务器名,也可以是其它一些别的东西,总之笔者在试验新浪的服务器时没有问题,表明它是一个无足轻重的指令,不过必须要有。然后服务器返回一个代码为250的信息,比较雷人。

再之后需要登录,先要发送一个AUTH LOGIN指令,服务器返回代码为334的信息,再发送一个经过编码的用户名,需要经过base64编码,这样网络偷窥者就看不出什么东西了。这时,服务器又返回334,然后再发送经过编码的密码。如果服务器验证正确,这次返回一个代码为335的信息,准备工作完成,接下去就可以干正事。

下面要做的事是告诉服务器,是谁发送邮件、向谁发送、发送的内容以及发送的附件。谁发送,表示为“MAIL FORM:<[发送方邮件地址]>”,把这个字符串发送到服务器,如果正常,将收到服务器回应,代码为250。然后发送“向谁发送”,表示为“RCPT TO:<[接收方邮件地址]>”,把这个字符串发送到服务器,如果正常,将收到服务器回应,代码同样是250

最后发送邮件正文,先发送一个字符串“DATA”,收到服务器的正确的回复354后,则可以发送邮件内容了,内容可以一次性都发送完,也可以一块块地发送,为让收邮件的服务器更好地处理邮件内容,每发送一块内容时,都要发送一大堆和内容不相干的东西,包括附件也是,为表明它自己这部分内容是附件,也要附加一些说明,下面是个典型的例子:

From:<xiaoye3003.student@sina.com>

To:<xiaoye3004@hotmail.com>

Subject:asdf

MIME_Version:1.0

X-Mailer:Smtp Client By xxx

MIME_Version:1.0

Content-type:multipart/mixed;Boundary=aaa

 

--aaa--

Content-type:text/plain;Charset=gb2312

Content-Transfer-Encoding:8bi

 

csdf

 

其中像MIME_VersionContent-type等东西都是让我们人类费解的,然而有时候对于服务器来说,又是必不可少的标识。这些都不用刻意去记它,甚至也不用花费脑子去理解,因为我们的应用几乎用不到这些知识。发送内容可以直接发送,或者使用Base64编码一下都行,附件一般地需要编码一下。

在发送完data之后,服务器返回354,然后我们可以尽情发送自己想要发送的东西,等发送结束时,需要发一个<cr><lf>.<cr><lf>(回车换行.回车换行)告诉服务器,我发完了,此时,服务器回给你一个代码为250的信息,告诉你ok了。

等你兴冲冲地打开接收的邮箱去看时,也许发现里面空空如也,没有任何未读邮件,这可能是你发送的非常简单的邮件,大部分邮箱都把它认为是垃圾邮件,将其过滤掉了。

当所有事情做完后,当然不要忘了断开连接,发送一个quit,这时服务器回给你一个代码221的信息,表示服务结束。

以上就是一个发送邮件的全过程,当然没有说到邮件服务器里怎么处理,单就这样,这样的过程还是有点复杂,于是有很多有关电子邮件的封装库就出现了,微软公司比较有名的有两个,一个是MSAPI32,另一个是无所不包的.net Framework平台,尤其是后面一种,提供了几乎傻瓜都会用的函数,照着MSDN中的文档写一遍就会用了。

然而客户的需求总会超出类库所覆盖的范围,有的客户不喜欢默默无闻的邮件发送工作,他们喜欢弹出一个界面来,由他们自己填写内容并发送,于是Outlook软件就承担这个工作,只要在需要的时候调用一下就行,包括发件人、收件人、主题、内容都可以在参数中指定,唯一困难的是无法在参数中指定附件,后来从网上找到一个MSAPI32中应用附件的方法,才解决这个问题。

还有些客户使用SSL协议来加密邮件,这对早期一些邮件处理库提出新的问题,如果使用自己写的邮件程序,还要将SSL处理过程加到其中,无疑在一项本来比较复杂的工作上又增加新的难度,还好,.net Framework平台考虑到这一点,在这个平台的基础上发送带有SSL加密的邮件,仅仅是改变一个参数的属性而已,极其简单。不过,这种便利的背后是程序员不为人知的辛苦工作。

每做一项非常简单工作的时候,我们往往忽视它内在包含的复杂技术,然而也许有一天我们需要改变这其中的某些细节,并由此修正这些技术的一部分缺陷,正如SSL所做的一样。所以,并不是别人替我们做好的工作就不需要去管它,了解并掌握它并不会花费太多精力,然而带给我们的,也许是意想不到的收获。

 


企业邮箱  |  法律公告  |  隐私保护  |  联系我们  |