代码改变世界

邮箱基础协议:SMTP/POP3/IMAP

2019-12-03 19:42  陈心朔  阅读(...)  评论(... 编辑 收藏

电子邮件的组成:信封、首部和正文

电子邮件由三部分组成,下图是 Client 发送的整个数据:
 

  1. 信封(envelope)
     
    信封是 MTA 用来交付的,在上例中由两个 SMTP 命令指明;
     
    MAIL From: rstevens@sun.tuc.noao.edu
    RCPT To: estevens@noao.edu

  2. 首部(header)
     
    首部由用户代理使用,上例中可以看到 9 个首部字段:Recived、Message-Id、From、Date、Reply-To、X-Phone、X-Mailer、To 和 Subject
    (以 X- 开头的是用户定义的字段,其他是由 RFC 822 定义的,详见 4.1 节)

  3. 正文(body)
     
    正文是发送用户发给接收用户报文的内容,RFC 822 指定正文为 NVT ASCII 文字行,用 DATA 命令发送的各行都必须小于 1000 字节

 
用户接收我们指定为正文的部分,加上一些首部字段,并把结果传到 MTA;MTA 加上一些首部字段,加上信封,并把结果发送到另一个 MTA

 
(更多实现细节,详见 RFC 2821

 
 

用 TCP 进行的邮件交换是由报文传送代理 MTA(Message Transfer Agent)完成的。

 
TCP/IP 交换电子邮件示意图:

 

邮件基础协议

邮件基础的网络协议有以下三个,一般我们使用 SMTP 协议来发送邮件,POP3 和 IMAP 协议来接收邮件(从服务端接收邮件至客户端)

  • 下表中 IMAP 协议支持发送邮件并不是邮件投递,而是通过 append 指令将邮件从客户端上传到服务端
协议 工作端口(括号内为 SSL) 支持发送邮件 支持接收邮件
SMTP 25(465) True False
POP3 110(995) False True
IMAP 143(993) True True

 


SMTP

两个 MTA 之间通过 NVT ASCII 进行通信,客户向服务器发出命令,服务器用数字应答码和可选的人可读字符串进行响应
 
下图是 SMTP 的一个交互会话过程:
 

  1. 键入 mail -v 启动用户代理; 键入 subject(主题)和正文
  2. 主动打开 port:25 ;等待从 Server 返回的问候报文(应答码220)
  3. HELO:标识自己(参数必须是合格的主机名)
  4. MAIL:标识报文发起人
  5. RCPT:标识接收方(可发多次,标识多个接收方)
  6. DATA:邮件报文内容
  7. QUIT:结束邮件交换

下图是发送方 SMTP(Client)和接收方 SMTP(Server)之间的一个 SMTP 连接:
 

SMTP 指令

最小SMTP支持 8 个命令,除了上述 5 个命令还有:

  • RSET:异常中止当前的邮件事务并使两端复位。丢掉所有有关发送方、接收方或邮件的存储信息
  • VRFY:使客户询问发送方以验证接收方地址,而无需向发送方发送邮件(通常用与管理员查找邮件交付差错中使用)
  • NOOP:强迫服务器响应一个OK应答码(200)

(另外还有一些附加可选命令)

 
SMTP 用半双工的形式使用 TCP,客户发送一个命令后停止等待应答;实际上 Client 可以一次发多个命令,称为流水线技术(pipelining)

如果使用了这种技术,Client 则不能丢弃报文直到所有的应答都已检查过,确认报文被服务器接收了

使用 Telnet 模拟 SMTP 发送邮件


POP3

POP3 协议相对 SMTP/IMAP 要简单一些,协议的指令也不多

POP3 的生命周期

POP3 命令以 CRLF 对结束,特定命令多行响应,以 CRLF.CRLF 结束

在服务器打开邮件后,它为每个消息指定一个消息号,并以八进制表示每个消息的长度。第一个消息被指定为 1,第二个消息被指定为 2,以此类推,第 N 个消息被指定为 N
在POP3命令和响应中,所以的消息号和长度以十进制表示

AUTHORIZATION

  • USER :客户确认身份(参数:username)
  • PASS :身份确认完成
  • QUIT :终止 POP3 会话
  • APOP :用于替代 USER 和 PASS 命令,它以 MD5 数字摘要的形式向POP3邮件服务器提交帐户密码(参数:用户名/密钥)(该命令实现可选)

安全性:每个 POP3 会话都以 USER/PASS 互换开始,导致了用户名和口令在网络上的显式传送,当服务连接频率变大、时间间隔小,就会加大了泄密的可能
(使用APOP:随着密钥长度的增加,解读的难度也会上升)

TRANSACTION

操作状态下的命令:

  • STAT :查询邮箱中的统计信息(邮件数量和所有邮件大小)
  • LIST :列出邮箱中的所有邮件信息(消息号/大小)(参数:MSG 列出对应消息号的邮件信息)
  • RETR :获取某封邮件的内容(参数:MSG)
  • DELE :将某封邮件标记为删除(参数:MSG)(被标记的邮件直到当前会话进入 UPDATE 状态才被删除)
  • NOOP :检测连接状况
  • RSET :取消删除标记

UPDATE

当客户在 AUTHORIZATION 状态下发送 QUIT 命令后,会话进入 UPDATE 状态
如果会话因为 QUIT 命令以外的原因中断,会话并不进入 UPDATE 状态,也不从服务器中删除任何信件

 
(更多实现细节,详见 RFC 1939


IMAP

IMAP 协议通过 port:143 来提供电子邮件的收发服务,和 POP3 被用来提供电子邮件客户端服务(从服务器检索电子邮件)
相对于 POP3,IMAP 支持多个电子邮件客户端同时管理邮箱,并可以通过邮件的标签/状态,监测到其他用户对于邮件的操作
 
IMAP 还支持在线/离线两种操作模式,客户端可以获得邮件副本存储在本地

标志消息属性

与邮件关联的有一个或多个 token list,将 flag 添加至列表可以设置邮件的属性,每个 flag 可以设置为永久的或临时的(当前会话)

\Seen 邮件已阅读
\Answered 邮件已回复
\Flagged 邮件被标记为紧急/特别关注
\Delete 邮件被标记删除(to EXPUNGE)
\Draft 邮件被标记为草稿
\Recent 邮件最近到达该邮箱(本次会话是首次收到当前邮件通知)

具体的实现与服务器相关

状态和流程图

Client 和 Server 建立好连接后,IMAP 连接处于四种状态之一
最初的状态在服务器的 greeting 报文中标识,客户端在不当状态中尝试的命令服务器都将以 BAD/NO 响应(取决于实现)

  • Not Authenticated State :未经认证的状态,连接启动时进入该状态,除非已进行预验证
  • Authenticated State:认证状态,可选择邮箱进行访问
  • Selected State:选定状态,已选择一个邮箱访问
  • Logout State:退出状态,连接正在终止(LOGOUT 命令)

服务器必须发送 BYE 响应来关闭连接,同样的,客户端应该发送 LOGOUT 命令来关闭连接

如果服务器检测到客户端单方面关闭了连接,则可以省略 BYE 响应

IMAP 命令

下面罗列一些常见的 IMAP 命令

客户端命令 —— 任何状态

  • CAPABILITY:查询服务器实现的功能
  • NOOP:检测连接
  • LOGOUT:终止当前连接

客户端命令 —— 未经认证的状态

  • STARTTLS:与服务器使用 TLS 进行交互
  • AUTHENTICATE:与服务器的认证机制
  • LOGIN:鉴权登陆,输入用户名与密码

客户端命令 —— 认证状态

  • SELECT:选择邮箱
  • EXAMINE:以只读方式选择邮箱
  • CREATE:创建一个邮箱
  • DELETE:删除一个邮箱
  • RENAME:重命名邮箱
  • SUBSCRIBE:订阅指定邮箱
  • UNSUBSCRIBE:取消订阅邮箱
  • LSUB:返回订阅邮箱列表
  • APPEND:追加一个State,例如可以保存一封新的邮件

客户端命令 —— 选定状态

  • CHECK:检查当前服务器状态(例如:磁盘,内存等)
  • CLOSE:永久删除所有消息
  • EXPUNGE:永久删除所有消息,与 CLOSE 不同的是,将返回每个消息标识
  • SEARCH:类似 find 命令,功能很强大可以按照不同条件搜索邮件
  • FETCH:检索与消息相关数据,例如:获取正文
  • STORE:改变与消息相关数据,例如:设置邮箱已读、删除状态等
  • COPY:拷贝指定的消息
  • UID:返回 UID 列表用于 FETCH