今天需要做一个功能特性,利用Rust发送SMTP邮件,SMTP是非常成熟通用的发送邮件通讯协议,在Python,NodeJS,Golang,Java里都有比较好用稳定的类库,自然想着Rust里也一定很容易找到相关类库。
可惜Rust里却没有找到比较好用的类库,在Rust的官方类库网页crates.io
搜一下SMTP
,排名第一个是smtp
,描述写着Simple SMTP client
,觉得就是它了,我就想要一个简单的SMTP客户端发送文本文件,不需要附件,回执等其它功能。本想用它,结果发现它的文档页面404,再一看Last Updated是4年之前。
第一次怀疑crates.io
的质量,居然还有404文档链接,只能放弃它。
之后,我又搜了好一阵,也没什么收获,唯独比较满意的就属lettre
了,最后更新时间是几天之前,文档页https://lettre.at可以打开,一看好像还可以。
一顿配置操作之后,发现问题了,文档上的代码不可用,某些模块都报错提示找不到了。去看了一下它的仓库https://github.com/lettre/lettre,跟了一下错误模块,感觉是作者后期做了变动之后没有来得及同步更新文档,一个人做开源确实不容易~
最后贴出调整之后的可用代码案例,方便以后使用时用得着
use lettre_email::{ Email};
use lettre::{ smtp::authentication::Credentials, ClientSecurity, ClientTlsParameters, SmtpClient, Transport };
use native_tls::TlsConnector;
use log::{ info, error };
fn send_mail (
to_addr: String,
subject: String,
body: String,
smtp_port: String,
smtp_host: String,
smtp_passwd: String,
smtp_user: String
) {
let mail = Email::builder()
.to(to_addr)
.from("blog@qttc.net")
.subject(subject)
.html(&body)
.build();
let creds = Credentials::new(
smtp_user,
smtp_passwd,
);
let addr = String::from(format!("{}:{}", smtp_host, smtp_port));
let connector = TlsConnector::new().unwrap();
let tls_params = ClientTlsParameters::new(smtp_host, connector);
let security = ClientSecurity::Required(tls_params);
let mut mailer = match SmtpClient::new(addr, security) {
Ok(v) => v.credentials(creds).transport(),
Err(e) => {
error!("Connecting to SMTP server was error: {}", e);
return;
}
};
match mailer.send(mail.unwrap().into()) {
Ok(_) => info!("Sending email success!"),
Err(e) => error!("Sending email was error: {}", e),
}
}
以上代码支持HTML格式UTF-8中文编码发送,另外smtp_host
参数是不带端口的,因为TLS证书验证不需要端口,addr
是主机加端口
经过历史多次的使用腾讯企业邮箱踩坑的经验,我发现一个问题:在官方的文档上写着TLS需要使用465端口examil.qq.com:465
,可实际测试发现假如你使用465
端口基本上30秒后告诉你Timeout
,后来改成25
端口exmail.qq.com:25
并携带TLS参数发送秒成功。