幻化成风:Rust使用SMTP发邮件

说明文章来源于: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"。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值