Browsed by
Tag: smtp

设置SPF记录

设置SPF记录

最近发现的一个问题,如果邮件没有 SPF 记录,某些邮件服务器可能会过滤为垃圾邮件甚至直接拉入黑名单,比如 outlook 的服务器。相对而言,gmail 服务器要聪明很多,似乎在没有 SPF 记录的情况下,会反查MX记录及IP地址并进行匹配检验。

SPF的全称是:Sender Policy Framework, 由RFC7208文档定义详细规格。具体细节就不介绍了,基本意思就是让接收方的邮件服务器对发送者的域名和IP地址等进行检查。

在Linode的DNS管理中,仅仅添加MX记录是不够的,需要单独添加一条TXT记录,如图所示:

添加SPF的DNS记录
添加SPF的DNS记录

根据RFC7208的定义,可以进行很细致的控制。如果想省事,就如上图一样,设置一条”-all”的记录即可:

v=spf1 mx -all
网站启用IPv6应注意的事项

网站启用IPv6应注意的事项

网站支持IPv6的步骤比较简单,基本上目前常用的软件,例如Apache、Postfix、dovecot等,都已经支持IPv4和IPv6双栈,只要服务商的设备提供IPv4和IPv6连接,这些软件本身无需为IPv6做特别配置。

需要注意的是服务商处的DNS配置。如果DNS配置不全面,某些服务器在鉴权时会拒绝接受来自IPv6地址的消息。例如gmail服务器在收到 email 消息时,会鉴定DNS和IPv6地址是否匹配,如果不匹配,则视为垃圾邮件直接拒绝,可以看到如下错误警示:

Our system has detected that this 550-5.7.1 message does not meet IPv6 sending guidelines regarding PTR records 550-5.7.1 and authentication.

下面以Linode中的配置做简单介绍(对DO而言也基本如此)。假设IPv4地址是“1.2.3.4”,IPv6地址是“1:2:3:4::5:6”,域名是“demo.com”。

Reverse DNS

Linode 为每个节点分配的DNS名默认是类似的成员名,例如“1234.members.linode.com”。在 Linux 系统 ping 域名”demo.com”时,首先显示的是”1234.members.linode.com”,然后才是跳转到”demo.com”。某些服务应用会认为是PTR错误。在linode中需要设置“ reverse DNS”记录,将节点的DNS名直接指定为“demo.com”。

具体措施请参考linode的在线文档

如果同时支持IPv4和IPv6,上述文档里指导的操作需要单独操作两次,分别指定IPv4地址和IPv6地址。

MX 记录

另外一个需要注意的是 MX 记录,即邮件服务器记录。如果我们将 MX 记录设置为“mail.demo.com”,那么在DNS的A和AAAA记录中,要分别对“mail.demo.com”设置IPv4和IPv6地址,例如以下DNS记录结果:

mail.demo.com. 300 IN AAAA 1:2:3:4::5:6
mail.demo.com. 300 IN A 1.2.3.4

仅仅指定一个地址,对端有可能以域名和地址不匹配为由拒绝消息请求。

TTL

Linode 默认的TTL是3600秒,建议修改为300秒。TTL 太长太短都不好,要根据自己的实际情况调整,以方便自己网络部署、同时又不增加太多网络负担为准则。

实现一个简单的SMTP发送库

实现一个简单的SMTP发送库

最近在优化“语音邮箱”业务时,发现采用python-smtplib库虽然能满足需要,但是还是有很多不足,因此决定自己重新写一个库,当然仅仅实现发送email(包含附件)即可。实现一个完整的SMTP服务可能比较复杂,而实现一个单纯的、高性能的SMTP客户端发送库却比较容易。

与SIP、HTTP等协议类似,SMTP也采用文本方式定义消息格式,而附件等二进制内容,则采用base64转码成文本,这样就极为方便开发和调试。以下是SMTP最基础的几个RFC文档:

RFC5321: SMTP
RFC5322: Internet message format
RFC4954: SMTP Service Extension for Authentication
RFC3207: SMTP Service Extension for Secure SMTP over Transport Layer Security
RFC2035: Multipurpose Internet Mail Extensions

我们结合SMTP的流程,来简要说明SMTP协议中的各个关键点。

一、标准端口

SMTP基于TCP连接,SMTP服务器默认打开的端口是25、587或者465。通常是采用25端口,后期设计加密SMTP(即SMTPS)时采用了465端口。而IANA在新业务端口规划时占用了465端口,因此将587端口定义为TLS加密的SMTP端口。

目前各email服务商通常都会同时打开25和587端口,有些为了和以前老客户端程序兼容,也会打开465端口。

这里面其实可能存在一个误解,似乎25端口就是不加密的SMTP,而587、465就是加密的SMTP。实际上不是这样,现代SMTP服务器一般都已经支持STARTTLS(即RFC3207),因此在25端口也可以启动SSL/TLS加密,这取决于客户端是否具备SSL/TLS加密、解密能力,这点在后续流程中会详细描述。

二、基础流程

2.1 建立与SMTP服务器的连接

建立TCP连接,连接到服务器的25端口或者587端口。如果是25端口,则是建立普通TCP连接即可。如果是587端口,通常可以直接建立SSL/TLS连接。需要注意的是,有些SMTP服务器的587端口也是要求普通TCP连接,后续STARTTLS流程中再启动SSL/TLS加密。这种情况下,587端口的流程与25端口的流程一致。

我们的示例流程中,采用QQMail的SMTP服务器做参考,因此我们首先向“smtp.qq.com”服务器的25端口建立连接。连接成功后,服务器应返回220消息,告诉客户端连接成功:

220 smtp.qq.com Esmtp QQ Mail Server

2.2 初次握手

SMTP客户端发送EHLO命令给服务器,进行初次握手协商:

EHLO 192.168.1.101

“EHLO”实际是ESMTP(Extended SMTP)的指令,意思是要进行用户名和密码的鉴权。远古时代的SMTP不需要鉴权的情况下,可以直接发送HELO命令进行握手。目前的SMTP服务器基本都是支持ESMTP,因此如果不刻意区分的话,后续的SMTP实际就是指ESMTP。

SMTP服务器器收到上述消息后,返回本服务器的一些能力信息给客户端:

250-smtp.qq.com
250-PIPELINING
250-SIZE 73400320
250-STARTTLS
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN
250-MAILCOMPRESS
250 8BITMIME

其中最关键的就是STARTTLS能力,也就是该SMTP服务器具备加密连接能力。通常都建议采用加密连接以确保数据安全,毕竟互联网上总有一些黑暗势力在窥探您的信息。

如果客户端不具备SSL/TLS能力,则直接跳到“账户鉴权”流程即可。此时就不能采用PLAIN鉴权模式,必须采用MD5等加密鉴权模式。

2.3 加密连接

既然服务器明确了SSL/TLS能力,因此客户端只要启动SSL/TLS加密TCP连接即可。客户端发送STARTTLS命令,通知服务器准备加密:

STARTTLS

服务器返回响应消息,通知客户端可以开始加密:

220 Ready to start TLS

接下来就是在TCP连接上建立SSL/TLS加密连接,后续通信以后都基于SSL/TLS连接。

请注意,QQMail服务器目前似乎只支持SSLv2、SSLv3加密,不支持TLSv1.0,TLSv1.1和TLSv1.2加密,其他的SMTP服务器(例如outlook、gmail等)则支持全部加密方式。

2.4 第二次握手

加密连接建立后,再次发送EHLO命令进行握手:

EHLO 192.168.1.101

同样,服务器返回相应能力进行响应。此时,通常不再包含STARTTLS指令了:

250-smtp.qq.com
250-PIPELINING
250-SIZE 73400320
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN
250-MAILCOMPRESS
250 8BITMIME

2.5 账户鉴权

鉴权有多种方式,其中PLAIN方式是要求所有SMTP服务器都必须具备的。在未加密的情况下,采用PLAIN方式无疑会泄露账户密码信息。而在已经加密的SSL/TLS连接里,则不存在这个问题,因此我们采用了最简单的PLAIN方式传递账户密码信息进行鉴权。

PLAIN方式很简单,采用”\0user name\0password”进行编码,然后base64转化成文本格式即可。

客户端发送以下鉴权命令:

AUTH PLAIN my_demo_base64_string_here

服务器鉴权成功,返回响应消息:

235 Authentication successful

2.6 提交邮件地址信息

鉴权成功后,客户端可以开始告诉服务器邮件地址信息,例如发送者、接收者等。此类消息不一一累述,请直接参考以下消息流:

MAIL From:<Iloveu@foxmail.com>
250 Ok
RCPT To:<Iloveu2@msn.com>
250 Ok

2.7 准备递交邮件内容

客户端发送DATA命令,告诉服务器准备提交内容:

DATA

服务器返回响应消息,通知客户端可以开始发送数据:

354 End data with <CR><LF>.<CR><LF>

由于后续数据都采用文本编码,因此标准规定用“\r\n.\r\n”标识数据发送结束,也就是SMTP服务器在上述响应消息中指示的“<CR><LF>.<CR><LF>”。

2.8 发送邮件内容

邮件采用文本格式,附件采用base64编码,可以分多次发送,以下为一个简单示例:

From: <Ilovu@foxmail.com>
To: <Iloveu2@msn.com>
Subject: You have a new voice mail: From 301 Day 2015-12-14 Time 10.29.7
MIME-Version: 1.0
Content-type: multipart/mixed; boundary="==491D4D07305F440E009A0125=="

--==491D4D07305F440E009A0125==
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="From 301 Day 2015-12-14 Time 10.29.7.wav"

UklGRpKaAABXQVZFZm10IBIAAAAGAAEAQB8AAEAfA......
--==491D4D07305F440E009A0125==--
.

对于有附件的情况,应在Content-Type中指明boundary参数,例如本例中的“==491D4D07305F440E009A0125==”。而附件内容起始处用“–boundary参数”标识,附件结尾用“–boundary参数–”标识。

发送完数据后,服务器响应消息:

250 Ok: queued as

2.9 结束

发送完邮件后,客户端友好地向服务器告别:

QUIT

服务器也友好地告别:

221 Bye

最后关闭TCP连接,完成整个流程。

常用SMTP服务器地址

常用SMTP服务器地址

简单记录一下各大常用电子邮箱服务商的SMTP服务器地址。以下邮件服务器默认都没有打开SMTP/POP功能,需要在账户设置中明确打开该项功能。

1、outlook.com,端口25或者587。用户名应为邮箱地址的全称,例如demo@msn.com等。

smtp-mail.outlook.com

2、gmail.com,端口25或者587。用户名应为邮箱地址全称,例如demo@gmail.com等。

smtp.gmail.com

gmail还要允许低安全度程序接入。似乎在google看来,SMTP属于安全度比较低的技术,尽管SMTP也是支持同样的TLS加密连接。

3、qq.com,端口为25或者587。用户名应为邮箱地址全称,例如demo@foxmail.com。

smtp.qq.com
Ubuntu环境搭建email系统

Ubuntu环境搭建email系统

网上的一些文档大部分是基于其他linux的版本,因此对比之下配置比较复杂,让人望而却步。而Ubuntu则已经将一些基本的配置都打包好了,只需要稍做修改即可。

以下配置基于Ubuntu10.04,全部从官方软件中心下载安装。采用Postfix+Dovecot搭建邮件系统。请先切换到root用户安装和配置。

step1: 安装Postfix

apt-get install postfix

安装时,会提示选择类型。一般选择”internet site”,输入网站域名即可。安装后,先不要着急配置postfix,我们在后续dovecot安装成功后,大部分配置会自动完成。

step2: 安装dovecot

一般网文介绍是直接安装dovecot,实际上Ubuntu提供了与postfix配合的dovecot包,因此请按以下方式安装:

apt-get install dovecot-common dovecot-postfix

安装时,系统会自动根据dovecot的要求,对postfix进行配置。

step3:配置postfix

配置文件为:/etc/postfix/main.cf。如果不对email进行限制的话,其实已经不用再配置了。下面我们修改该配置文件,增加一些额外的控制,例如用户邮件大小等:

mailbox_size_limit = 20000000 <--限定邮件账户不超过20M字节
message_size_limit = 200000  <-- 每封邮件不超过20K字节
myhostname = mail.xxxx.com
mydomain = xxxx.com

step4: 配置dovecot

一般也不需要配置,但是在使用gmail托管时,ssl/tls似乎没起作用,因此稍作修改采用普通访问方式即可。注意,此时dovecot的配置文件是/etc/dovecot/conf.d/01-dovecot-postfix.conf

listen = *  
disable_plaintext_auth = no

缺省情况下,dovecot没有被配置为自启动,因此我们需要手工添加:

update-rc.d dovecot start 99 0 1 2 3 4 5 6 .

其他

email用户账户就是当前Ubuntu的用户。建议对email用户单独处理,并设置在mail组内,设置单独的用户目录等,如下所示,创建一个名为support的用户:

mkdir /home/mail-users
useradd -m -d /home/mail-users/support -g mail support 
passwd support

Debian系統的差異:

如果需要支持pop3的話,需要安裝以下軟件:

apt-get install dovecot-pop3d