SMTP简介
SMTP称为简单邮件传输协议(Simple Mail Transfer Protocal),目标是向用户提供高效、可靠的邮件传输。它的一个重要特点是它能够在传送中接力传送邮件,即邮件可以通过不同网络上的主机接力式传送。通常它工作在两种情况下:一是邮件从客户机传输到服务器;二是从某一个服务器传输到另一个服务器。SMTP是一个请求/响应协议,它一般监听25号端口,加密协议一般使用465端口,用于接收用户的Mail请求,并与远端Mail服务器建立SMTP连接。
在实际应用中,一般使用SMTP协议发送邮件,一般使用POP3,IMAP协议接收邮件
SMTP协议工作机制
SMTP通常有两种工作模式。发送SMTP和接收SMTP。具体工作方式为:发送SMTP在接收到用户的邮件请求后,判断此邮件是否为本地邮件,若是本地邮件,直接投送到用户的邮箱,否则向DNS查询远端邮件服务器的MX记录,并建立与远端接收SMTP之间的一个双向传送通道,此后SMTP命令由发送SMTP发出,由接收SMTP接收,而应答则反方向传送。一旦传送通道建立,SMTP发送者发送MAIL命令指明邮件发送者。如果SMTP接收者可以接收邮件则返回OK应答。SMTP发送者再发出RCPT命令确认邮件是否接收到。如果SMTP接收者接收,则返回OK应答;如果不能接收到,则发出拒绝接收应答(但不中止整个邮件操作),双方将如此反复多次。当接收者收到全部邮件后会接收到特别的序列,如果接收者成功处理了邮件,则返回OK应答。
邮箱的发送流程
先来了解一下邮件的概念
电子邮件和我们生活中发送的邮件很像,也可以映射为信封、称谓、时间、正文等。
其中信封的部分就是通过SMTP命令指定的,首部和主体就是写在邮件正文中的。
具体怎么来指定这些信息,就要通过SMTP命令了,具体操作流程如下:
telnet smtp.126.com 25 #与邮箱服务器简历链接
#220 126.com Anti-spam GT for Coremail System (126com[20140526])
EHLO localhost #新协议中用来替代HELO命令
#250-mail
#250-PIPELINING
#250-AUTH LOGIN PLAIN
#250-AUTH=LOGIN PLAIN
#250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UF9xA92UCa0xDrUUUUj
#250-STARTTLS
#250 8BITMIME
AUTH LOGIN #开始认证
#334 dXNlcm5hbWU6
ZXhhbXBsZQ== #base64编码的用户名,example@126.com为例,这里就是base64(example)
#334 UGFzc3dvcmQ6、
ZXhhbXBsZQ== #base64编码的密码
#235 Authentication successful
MAIL FROM:<example@126.com> #指定发送者,这个命令会重置发送者、接收者和邮件数据
#250 Mail OK
RCPT TO:<example@126.com> #指定接收者,这个命令可以执行多次,设置多个接收者
#250 Mail OK
DATA #这个命令没有参数,指定下面为邮件的正文
#354 End data with <CR><LF>.<CR><LF>
FROM:example@126.com #邮件的正文中也要包含邮件首部信息,from,to,cc,subject
TO:example@126.com
CC:example@126.com
SUBJECT:this is SUBJECT
this is body first line #邮件首部信息与邮件主体要用空行分隔
this is second line
. #邮件已单独的一个"."结束
#250 Mail OK queued as smtp2,DMmowAAnXgAI2wxgIaTcLQ--.8086S2 1611455494
QUIT #断开连接
#221 Bye
上面的 MAIL
和RCPT
两个命令就是在设置信封,让服务器知道邮件是发给谁的。
DATA
命令就是在设置邮件的正文,正文中又包含了首部和主体两部分的信息
SMTP协议的主要命令和响应
SMTP主要命令
命令 | 含义 |
---|---|
EHLO(Extended hello)/HELO(hello) | 这个命令用于说明自己是SMTP客户端身份,参数包含客户端的域名(domain)。其中EHLO是SMTP补充协议( RFC 5321 )中用于替换HELO命令的新命令,协议规定服务器支持EHLO命令的时候,尽量使用EHLO命令,为了兼容以前的版本,要求服务器继续支持HELO命令。如果收到回复OK,说明发送者和接收者处于初始状态,所有的状态表和缓存区都被清零。 |
这个命令的参数是发送者邮箱<reverse-path>,参数中有 FROM 关键字,这个命令会清空之前的发送者邮箱(the reverse-path buffer)、接收者邮箱(forward-path buffer)和邮件数据(the mail data buffer)。 | |
RCPT(recipient) | 用于指定一个邮件接收者,参数中有TO 关键字,指定多个接收者通过重复使用这个命令。 |
DATA | 这个命令没有参数,告诉服务器接着要发送邮件内容。 邮件内容包含邮件标题项(message header section )和邮件正文(message body), 标题项(Header Fields )是以项目名(field name)为行的起点,接着是冒号(":"),跟着是内容(field body)以回车换行结束 FROM:example@126.com TO:example@126.com CC:example@126.com SUBJECT:邮件主题 最后正文结束的地方,以单独的"."为一行,表示邮件正文结束 |
QUIT | 关闭传输通道 |
AUTH LOGIN | 登录认证 |
SMTP主要应答码
响应码 | 说明 |
---|---|
220 | 服务就绪 |
221 | 服务关闭传输通道 |
250 | 请求指定完成 |
251 | 用户不是本地用户,报文被转发 |
354 | 开始邮件输入 |
450 | 邮箱不可用 |
500 | 语法错误,不识别的命令 |
502 | 命令未实现 |
552 | 所有请求动作异常终止 |
553 | 请求的动作为发生,邮箱名不允许使用 |
SMTP协议的扩展协议:MIME
SMTP协议在传输报文时,只能够传输7位的ASCII格式的报文,不支持那些不使用7位ASCII格式的语种,同时它也不支持语音和视频数据的传输,因此我们需要一个辅助性协议帮忙传输报文,它就是MIME。
MIME协议定义了5种头部,用来加在原始的STMP头部,以便定义参数的转换。他们分别是:
头部 | 含义 |
---|---|
MIME-Version | MIME版本 |
Content-Type | 内容格式 |
Content-Tansfer-Encoding | 内容传输编码 |
Content-ID | 内容标识 |
Content-Description | 内容描述 |
MIME的使用方式
#和之前与服务器建立连接的方式一致,只是在执行DATA命令以后,发送的邮件正文有所不同,正文的示例如下:
From: <example@126.com>
To: <example@126.com>
Subject:this is subject
Date: Sun, 26 Nov 2006 19:01:04+0800
MIME-Version: 1.0
Content-Type:multipart/alternative;boundary="this_is_boundary"
This is a multi-part message in MIME format.
--this_is_boundary
Content-Type: text/plain;charset="gb2312"
Content-Transfer-Encoding:base64
123123123
--this_is_boundary
Content-Type: text/html;charset="gb2312"
Content-Transfer-Encoding:base64
PEI+MTIzMTIzMTIzPC9CPg==
--this_is_boundary
Content-Type: image/jpeg; name="image005.jpg"
Content-Transfer-Encoding:base64
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
--this_is_boundary--
.
注意在第一个
Content-Type
中设置boundary
,后面可以根据boundary
分隔多个内容部分,每个分隔符号为
"--"+boundary
最后一个结束的位置为
"--"+boundary+"--"
这个和html上传多文件的时候很像。