在网络协议上,高层协议确实比底层协议更容易理解,也更加的人性化。 传输层的 TCP, UDP 都还停留在各种字节内容的整合和校验上,而更上层的应用层协议就已经能够直观到通过直接解读就能理解其每条消息的含义了。

SMTP 协议

SMTP,简单邮件传输协议。单从协议内容上来说确实没有太多的学习难度。但是,扭转“常识”恰恰是巨大的绊脚石。 直接就进入了网页邮件系统 or 客户端邮件系统的时代。图形化的界面配合上一些关键字的内容 (比如收件人,主题等)。 点击发送就觉得一封邮件已经发出去了。

但是,究竟这中间做了什么呢? 163,GMAIL, QQ 等邮箱究竟又在其中扮演着怎样的一个角色?

首先,SMTP 是为了高效、可靠地传递邮件而存在的。

下面先给一段演示。通过 telnet 连接到 183.57.48.34 (这个是腾讯企业邮其中一台机器的 IP) 25 (SMTP 服务端口) ,以本机作为 SMTP 的客户端,而将 183.XXX 作为 SMTP 的服务端,来完成邮件信息的一次交互。 (当然,最后失败了。被企业邮识别为垃圾邮件了…)

下列每行 # 开始及之后的内容是个人添加的注释,其它内容是 telnet 交互的内容。 同时,-- 标志该行内容由

$ telnet 183.57.48.34 25
Trying 183.57.48.34...
Connected to 183.57.48.34.
Escape character is '^]'.
220 bizmx17.qq.com MX QQ Mail Server
HELO test                               -- # MEANS HELLO <domain> 在每次建立连接通道后,发送的第一条消息
250 bizmx17.qq.com                         # 服务器的回复值 Code 250 
MAIL FROM: <[email protected]>              -- # MAIL 表示邮件的发起方,用于退信等其他邮件反向事件
250 Ok                                   
RCPT TO: <[email protected]>                   -- # RCPT 表示邮件的接收方,用于投递邮件等正向事件
250 Ok
DATA                                    -- # DATA 表示之后的内容将作为邮件正文 (正文这个描述可能不太恰当,更应该是等同于信封内的所有内容)
354 End data with <CR><LF>.<CR><LF>
                                        --
It's a fake mail.                       -- # 邮件正文,其实还可以写上诸如 'Subject: XXX' 'Cc: XXX' 的内容
.                                       -- # 正文内容结束的标志,<CR><LF>.<CR><LF>
550 Mail content denied. https://service.exmail.qq.com/cgi-bin/help?subtype=1&&id=20022&&no=1000726 # 这里很无奈,没腾讯给拦了,没发出去。不过反正是假的,邮件信息不全。

几个主要的 SMTP 交互指令

  • HELO: (HELLO) 主要用于让 SMTP 服务器对当前连接的 SMTP 客户端(上例是 telnet 模拟的) 建立一个身份标志 (一般是当前的主机名)
  • MAIL: 用法 MAIL FROM: [email protected] (不区分大小写) 可以将其与普通信件的信封等同。毕竟都是要写上发信人,如果没人收信,也就可以根据这个声明将信件退回。
  • RCPT: (RECIPIENT) 用法 RCPT TO: [email protected] (可多次重复声明,即将一封信件复制多次投送给每次声明的对象) 相当于普通信件的收信人。不过也有点区别,毕竟普通信件没法一件多发嘛。
  • DATA: DATA 之后到 <CR><LF>.<CR><LF> 之前的所有内容都作为邮件的正文内容。等同于普通信件信封内的信纸(当然了,信纸上在写上 To XXX: Yours XXX 也是很正常的嘛),类似的也就是 DATA 数据中也可以包括 Subject: (主题), From: (写信人), Date: (日期), To:(收件人)等内容。

几个次要的 SMTP 交互指令

  • RSET: (Reset) 重置,丢弃之前针对邮件所描述的所有内容,重新开始。

  • VRFY: (VERIFY) 用于确认收件人是否存在,以及收件人的完整地址

  • NOOP: 强制服务器做出一个回应,没有实际意义。

  • QUIT: 要求收信服务器返回一个邮件接收成功的信号,之后释放连接通道。

SMTP 扩展

前面描述了这么多,应该来说找一些支持 TCP (或者其他稳定的传输层连接也是可以的) 连接的命令就完全可以支持一次邮件发送的需求。

但是,如果想要发送一些中文字符之类的,马上就出现了问题。

这里有几种方式,但本人还没有理解透彻。仅列出知道的可行方案。

  • 通过 IMF (Internet Message Format) 进行发件
  • 通过 ESMTP

SMTP 安全

出于 SMTP 本身协议的设计,没有一个有效的身份认证机制。

纵使通过 MAIL FROM: <[email protected]> 在信封上写明了是由 A 发出的信件。 但是,装在信封内的信纸却可以属上另一个人的名字。

利用这种规则,也就出现了伪装发信人这样的操作。当然,现在的大量邮箱服务提供商都会对这种情况进行标记。

“代发”标记

参考

  1. SIMPLE MAIL TRANSFER PROTOCOL
  2. MIME
  __                    __                  
 / _| __ _ _ __   __ _ / _| ___ _ __   __ _ 
| |_ / _` | '_ \ / _` | |_ / _ \ '_ \ / _` |
|  _| (_| | | | | (_| |  _|  __/ | | | (_| |
|_|  \__,_|_| |_|\__, |_|  \___|_| |_|\__, |
                 |___/                |___/