我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
查看源代码

笔记:互联网电子邮件架构

果然写笔记是最好的读书方式,这里的笔记绝不是对知识点的堆砌,而是要让没读过这书的人有一个大概的了解,或者让读过书的人有新的发现。

最高效的阅读便是从书中为自己寻找论据。

在我的日志中,“笔记”前缀表示我这是现学现卖,对内容没太多把握。

电子邮件的出现要比Web早得多,一直以来都可以算是互联网的核心服务之一。

应该说由于历史遗留问题,目前电子邮件的架构并不完美,但一直都没有合格的替代品出现。

电子邮件使用SMTP协议被发送,SMTP是一个“简单”的,基于纯文本的交互式协议,位于TCP之上。当A向B发送邮件时,A向B在25端口上发起TCP连接,使用SMTP协议向B传输一份邮件,同时指明发信人地址和收信人地址。

这时,A和B就可以称为邮件服务器,通常一个邮件服务器是既可以收信也可以发信的,即同时是SMTP服务器和SMTP客户端。作为一台服务器,需要保持时刻在线,以便随时接收新邮件。显然,用户是不会直接使用服务器的。

在经典的电子邮件架构中,在每个用户的个人计算机上,都有一个本地SMTP代理,它负责在本地收集邮件,并定时发往服务器。引入本地SMTP代理后,A向B发送邮件时,用户A将写好的邮件交给本地SMTP代理(通常是个人计算机上的一个用户程序),本地SMTP代理通过SMTP协议将邮件发送到A的邮件服务器,A的邮件服务器再将邮件通过SMTP发送到B的邮件服务器。

本地SMTP代理和邮件服务器都会维护一个邮件队列,逐个发送邮件,当邮件无法送达时会进行几次重试,仍无法发送时会退回发信人。

邮件已经到达了B的邮件服务器,再来考虑B如何收信。B的个人计算机并不能保证时刻在线,也可能没有固定的IP地址,所以邮件服务器很难将新邮件发送到他的个人计算机上。

可以想象,SMTP是一个“推送”协议,当有新信息时,由发信人向收信人推送信息。而在从邮件服务器检查新邮件时,我们需要的可能是一种“拉取”协议,由收信人定时拉取新信息。

于是有了POP3, 它同样是在TCP之上的,基于纯文本的“简单”交互式协议。个人计算机上的POP3代理,定时使用POP3协议从邮件服务器检查新邮件,同时将新邮件下载到个人计算机。

除POP3以外还有功能更加复杂的IMAP协议,IMAP协议在POP3的基础上还支持同步阅读状态,搜索,建立文件夹对邮件进行分类等等功能。

SMTP代理和POP3(IMAP)代理分别代表了收信和发信,它们通常是一体的,称为邮件客户端,如Outlook, Thunderbird.

一封邮件除了正文之外,还可能有很多元信息,如收信人,发信人,日期,标题,收信来源等。这些键/值对信息以邮件报头的形式存在于一封邮件中,非常类似于HTTP中的报头。在早期的SMTP协议中,仅在邮件中支持ASCII字符,无法使用非ASCII字符(如中文),也无法使用格式文本和嵌入附件。于是出现了MIME标准,通过将邮件正文(base64)编码,并添加特殊的报头信息,即可实现使用非ASCII字符,使用HTML, 嵌入图片和附件等功能。

形如 m@jybox.net 的电子邮件地址指明了该邮箱位于 jybox.net 这台服务器上,对应的用户名是 m, 显然我们可以通过DNS查询到jybox.net所对应的IP, 但电子邮件服务器并非由通常的A记录指定,而是有专门的MX记录。发信人通过向DNS查询邮件地址中域名的MX记录来找到收信人的邮件服务器。

我们再来考虑安全性问题,SMTP是可选验证的。在本地SMTP代理向邮件服务器提交邮件时,通常是需要验证用户名和密码的,因为邮件服务器只希望向它的用户而不是所有人提供邮件转发服务。而在邮件服务器间发送的邮件则无需验证,因为你需要接收来自所有人的邮件。

至于邮件拉取协议(POP3, IMAP)显然也需要验证,因为一个人只应当能够查看自己邮箱里的邮件。

至此,还没有任何方式来鉴定一封邮件的真伪,任何人都可以在向收信人邮件服务器发送邮件时伪造发信人地址。为此,你可以通过DNS在一个域名的TXT记录中查询到一份被称为SPF的记录,该记录指明了经过认证的,用于该域名的发信服务器的地址,若发信人不是这个地址,则可以认为邮件是伪造的。除此之外,还有一些手段可以对SMTP进行加密,签名,工作量证明,但它们不是业界标准的一部分或应用较少,这里不再介绍。

Hotmail是当年最为成功的,基于Web的免费邮件服务,现在几乎所有邮件服务提供商均支持通过Web发送和接收邮件,甚至不再提供SMTP和POP3/IMAP访问服务。

不过随着智能手机的普及,SMTP和POP3/IMAP又回来了。

撰写评论

如希望撰写评论,请发邮件至 jysperm@gmail.com 并注明文章标题,我会挑选对读者有价值的评论附加到文章末尾。

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2024-04-08.