0x01 简单介绍一下SMTP
SMTP(Simple Mail Transfer Protocol
, 简单邮件传输协议)属于TCP/IP
协议簇(那么显而易见的是, 它基于TCP而非UDP, 这样做是为了邮件不在传输途中丢失, 唯一的缺点是增大了链路开销, 但是现在这些开销基本可以忽略不计), 一句话概括就是发送电子邮件的协议. 它使用TCP的25
号端口.
SMTP服务器则是遵循SMTP协议的发送邮件服务器, 用来发送或中转发出的电子邮件.
0x02 SMTP指令与应答
上面已经说过SMTP基于TCP, 那么在客户端与服务端建立TCP连接之后, 在这个连接上进行控制、应答和数据发送/接收. 客户端以文本形式发出请求, 服务端返回一个三位数字的状态码.
SMTP指令:
-
HELO <domain> | 开始通信
-
EHLO <domain> | 开始通信(E代表扩展, 需要身份验证)
-
MAIL FROM: <reverse-path> | 发送人
-
RCPT TO: <forward-path> | 收件人
-
DATA | 正文部分
-
RSET | 初始化
-
VRFY <string> | 确认用户名
-
EXPN <string> | 将邮件组扩展为地址列表
-
NOOP | 请求应答
-
QUIT | 关闭
SMTP状态码:
-
211 | 系统状态或求助回答
-
214 | 求助信息
-
220 | 服务就绪
-
221 | 服务结束
-
250 | 完成请求命令
-
251 | 非本地用户, 报文将被转发
-
354 | 开始邮件输入
-
421 | 服务不可用
-
450 | 邮箱不可用
-
451 | 命令异常终止: 本地差错
-
452 | 命令异常终止: 储存容量不足
-
500 | 不能识别命令
-
501 | 不能识别参数或变量
-
502 | 命令未实现
-
503 | 命令序列不正确
-
504 | 命令参数未实现
-
550 | 邮箱不可用
-
551 | 非本地用户
-
552 | 储存容量不足
-
553 | 邮箱不可用, 请求中止
-
554 | 其他错误
0x03 SMTP报文结构
SMTP协议将邮件内容和其他信息封装在SMTP报文中, 报文由三个部分组成——信封、首部和主体. 可以看到信封实际上是由SMTP命令组成的.
0x04 RFC中的SMTP
-
所有报文都是由ASCII码组成
-
报文由报文行组成,各行之间用回车(CR)、换行(LF)符分隔
-
报文的长度不能超过998个字符
-
报文行的长度≤78个字符之内(不包括回车换行符)
-
报文中可包括多个首部字段和首部内容
-
报文可包括一个主体,主体必须用一个空行与其首部分隔
-
除非需要使用回车与换行符,否则报文中不使用回车与换行符
原始文献地址:
实践: 通过telnet从SMTP服务器发送邮件
试了几个邮箱, 都不能用…于是我在本地搭建了SMTP服务, 所使用的域名是kainhao-smtp.local
和kainhao.local
.
我省略了交互中需要的[CR]
和[LF]
首先登录SMTP服务器:
telnet kainhao-smtp.local 25
收到回复220 kainhao-smtp.local | CONN Success!
接着执行问好:
EHLO kainhao.local
回复250 OK
然后指明发件人(我并没有打开SMTP认证或Pop before SMTP, 所以跳过了登录):
MAIL FROM: <kainhao@kainhao-smtp.local>
收到回复250 OK
指明收件人:
RCPT TO: <cheese@kainhao-smtp.local>
收到回复250 OK
开始写文件正文:
DATA
收到回复354 START INPUT
接着正文:
ACROSS THE GREAT WALL WE CAN REACH EVERY CORNER IN THE WORLD [CRLF]. [CRLF]
SMTP以.
作为邮件正文的结束符, 但即使正文本身包含这个字符, 也能做出识别, 具体方法请自行查阅RFC 821
接着关闭连接:
QUIT
收到221
.
不愧是简单邮件传输协议…内容还真不多…
暂无评论内容