说明文章来源于:Rust使用SMTP发邮件 - 幻化成风的文章 - 知乎
https://zhuanlan.zhihu.com/p/682908539
一、Rust使用SMTP发邮件
幻化成风
各主流邮件服务(个人免费版本)对SMTP的支持情况:
支持SMTP服务
Gmail: 支持SMTP服务。使用SMTP发送邮件时,你需要在Google账户的安全性设置中生成一个专用的应用密码或开启两步验证。
QQ邮箱: 支持SMTP服务。和Gmail类似,你需要在账户设置中开启“POP3/SMTP服务”并生成一个授权码来代替密码进行认证。
126邮箱和163邮箱:支持SMTP服务。和Gmail类似,你需要在账户设置中开启“POP3/SMTP服务”并生成一个授权码来代替密码进行认证。
139和189邮箱: 通常提供SMTP服务,需要在邮箱设置中启用或验证,但是笔者在实际使用过程中没有成功过,发不出邮件去。
Yandex: 支持SMTP服务。Yandex允许使用标准的SMTP设置发送邮件,但需要在账户设置中确认并需要生成一个专用密码。
SwisscowsMail: 支持SMTP服务。直接使用邮箱密码。
受限或不支持SMTP服务
Tutanota: 不提供传统的SMTP服务。Tutanota着重于端到端加密,因此它使用自己的服务器和客户端应用来处理邮件,而不是标准的电子邮件协议。
ProtonMail: 默认情况下不支持SMTP服务。ProtonMail同样专注于提供端到端加密的电子邮件服务。不过,它提供了一个名为ProtonMail Bridge的工具,这个工具可以让ProtonMail账户通过IMAP/SMTP在电子邮件客户端中使用,但仅限于付费用户。
Rust程序
依赖库
[dependencies]
lettre = "0.11.4"
代码
下面的代码会用多线程发送邮件
use std::sync::Arc;
use std::thread;
use lettre::{Message, SmtpTransport, Transport};
use lettre::transport::smtp::authentication::Credentials;
struct Email<'a> {
address: &'a str,
password: &'a str,
smtp_address: &'a str,
}
impl<'a> Email<'a> {
pub fn new(address: &'a str, password: &'a str, smtp_address: &'a str) -> Self {
Email {
address,
password, // 邮箱的密码或者授权码
smtp_address,
}
}
}
fn send_email() -> Result<(), Box<dyn std::error::Error>> {
// 发信人邮件列表,要改成自己的(邮箱地址改成自己的;密码/授权码 要到邮箱官网进行设置、获取;SMTP地址不用改动)
let accounts = vec![
Email::new("demo@gmail.com", "xxx", "smtp.gmail.com"),
Email::new("demo@126.com", "xxx", "smtp.126.com"),
Email::new("demo@163.com", "xxx", "smtp.163.com"),
Email::new("demo@qq.com", "xxx", "smtp.qq.com"),
Email::new("demo@icloud.com", "xxx", "smtp.mail.me.com"),
Email::new("demo@swisscows.email", "xxx", "swisscows.email"),
Email::new("demo@yandex.com", "xxx", "smtp.yandex.com"),
];
// Convert accounts into a thread-safe structure
let accounts = Arc::new(accounts);
// Collect handles for joining threads later
let mut handles = vec![];
for i in 0..accounts.len() {
let accounts_clone = Arc::clone(&accounts);
// Spawn a thread for each account
let handle = thread::spawn(move || {
let account = &accounts_clone[i];
let email = Message::builder()
.from(account.address.parse().unwrap())
.to("dionecyan@puabook.com".parse().unwrap()) // 改成收件人邮箱,建议用临时邮箱
.subject("Greeting")
.body("Hi, how are you?".to_string())
.unwrap();
let creds = Credentials::new(account.address.to_string(), account.password.to_string());
let mailer = if account.address.ends_with("@icloud.com") || account.address.ends_with("swisscows.email") {
SmtpTransport::starttls_relay(account.smtp_address).unwrap()
} else {
SmtpTransport::relay(account.smtp_address).unwrap()
};
let mailer = mailer.credentials(creds).build();
match mailer.send(&email) {
Ok(_) => println!("Sending email succeeded: {}", account.address),
Err(e) => eprintln!("Sending email failed:{}:\n{:#?}", account.address, e),
}
});
handles.push(handle);
}
// Wait for all threads to complete
for handle in handles {
handle.join().unwrap();
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
send_email()
}
二、QQ验证说明
以上的代码来自于知乎。
本人已经对QQ邮件进行了验证,是Ok的。
当然,需要在QQ邮箱内,进行手机绑定后,生成相应的授权码,把授权码替代“ Email::new(“demo@qq.com”, “xxx”, “smtp.qq.com”),”中"xxx"。