最近把自己的博客网站使用 Rust 语言重写了,利用的是 actix-web 这个框架。然后就一直想实现文章评论的回复邮件提醒这个功能,由于是自己写的网站,而且 actix-web 也没有提供像 wordpress 那样丰富强大的插件系统,所以这个需求就只能自己实现了。查了一圈之后,发现 lettre 这个库的 API、doc 什么的都比较完善,甚至直接提供了一个发邮件的 example,于是就准备利用这个库来实现一个发邮件的功能。
环境
截至现在写文章时,lettre的最新版本为0.9.0,所以文章中的代码都是在这个版本下编译测试通过的。我先是参考它的 Github 项目里 examples 目录中的smtp_google这个例子进行试验————很不幸,虽然能编译过,但是认证一直有问题,无法发送邮件。
一路坎坷
开源项目的示例代码更新缓慢早就不是新闻了,能编译过其实已经算是庆幸。为什么这么说呢,我大概查了一下这个库,发现他不久前才从0.8.0跳到了0.9.0,并且带来了一系列的 Break Changes。网上能找到的讨论及代码都是用旧 API 编写的,没有什么参考意义,但是这个认证失败让我感觉很诧异,既然能认证失败,那至少说明是与服务器成功建立了连接的。
后来我感觉可能是密码的问题,于是又专门去 Google 的应用专用密码那里弄了个 App Password 去登陆,发现还是登陆不上。不过这次偶然发现 Google 有一个新的认证方式叫XOAuth2(链接)。又去 lettre 项目中查找这个协议的相关 issue,果然,这个协议列在计划当中,还没有完全实现(链接)。
同时在Google的一个页面上也找到了一个可能的解决方案:可以在 Google 账户中设定允许较低安全等级的认证来兼容旧应用。那我估计就是因为这个问题了,因为这个新的XOAUTH2协议似乎就是去年才新出来的,不过我并不准备去调整账户的安全策略,于是又摸索了几下lettre的 API,然后利用Outlook的服务器发送邮件成功。
成功实现
核心代码如下,主要注意的是server addr要带上端口,否则会使用465端口,这个需要去邮件服务提供商那里查询,但是很多如Outlook并不使用465了。再一个就是要注意认证方式,一般都是STARTLS,如果要改的话,也是更改ClientSecurity这个选项。
虽然lettre提供了一个new_simple的函数直接为你设置了像TlsConnector、ClientSecurity这样的参数,但是由于它都取的默认值,在很多情况下并不适用,还是分开设定每个参数比较好。有时候,封装过度也挺坑的~~~
除了上面的GMail XOAUTH2认证问题之外,还发现在连接QQ Mail服务器的时候存在UTF-8解码出错,因为lettre直接把收到的字符串给String::from_utf8了,这也是一个小 bug 吧。不过总体来说,一旦调试完成,发起邮件来还是很好用的。