使用 Rust 发送电子邮件:lettre 和 mailparse 库
Rust 是一种系统编程语言,越来越多地被用于构建高负载的 Web 服务和微服务。这类项目中的典型任务之一是发送电子邮件。在 Rust 生态系统中,有几个成熟的电子邮件处理库,其中突出的是 lettre 和 mailparse。
在本文中,我们将详细讲解如何使用 SMTP 在 Rust 中配置邮件发送、如何添加附件和生成 HTML 邮件,以及如何解析传入消息。本文面向已经熟悉 Rust 基础的开发者。
lettre 库:邮件发送的基础
Lettre 是一个用于在 Rust 中处理电子邮件的现代、异步和同步库。它支持:
- SMTP 传输(包括 STARTTLS 和 SSL/TLS);
- 生成 MIME 格式的邮件(文本、HTML、附件);
- 处理编码(Base64、Quoted-Printable);
- 通过 tokio 或 async-std 实现异步传输。
要将 lettre 添加到项目中,请执行以下命令:
cargo add lettrecargo add tokio --features full # 用于异步模式通过 SMTP 发送基本邮件
让我们看一个最简单的例子——通过 Gmail(或任何其他提供商)的 SMTP 服务器发送文本邮件。
use lettre::transport::smtp::authentication::Credentials;use lettre::{Message, SmtpTransport, Transport};
fn main() -> Result<(), Box<dyn std::error::Error>> { // 构建邮件 let email = Message::builder() .from("发件人 <from@example.com>".parse()?) .to("收件人 <to@example.com>".parse()?) .subject("来自 Rust 的问候!") .body("这是一封用 Rust 发送的测试邮件。".to_string())?;
// SMTP 设置(以 Gmail 为例) let creds = Credentials::new( "your_email@gmail.com".to_string(), "your_app_password".to_string(), );
// 创建传输器 let mailer = SmtpTransport::relay("smtp.gmail.com")? .credentials(creds) .build();
// 发送 match mailer.send(&email) { Ok(_) => println!("邮件发送成功!"), Err(e) => eprintln!("发送错误:{}", e), }
Ok(())}请注意:对于 Gmail,您需要使用应用密码,而不是主密码。对于其他提供商(Yandex、Mail.ru、自己的 SMTP 服务器),请更改服务器地址和端口。
发送带附件的 HTML 邮件
Lettre 可以轻松生成多部分 MIME 消息。让我们添加 HTML 正文和附件:
use lettre::message::header::ContentType;use lettre::message::{Attachment, MultiPart, SinglePart};use lettre::{Message, SmtpTransport, Transport};
fn send_html_with_attachment() -> Result<(), Box<dyn std::error::Error>> { // HTML 邮件正文 let html_body = "<h1>你好!</h1><p>这是一封来自 Rust 的 HTML 邮件。</p>".to_string();
// 构建多部分邮件 let email = Message::builder() .from("发件人 <from@example.com>".parse()?) .to("收件人 <to@example.com>".parse()?) .subject("带附件的 HTML 邮件") .multipart( MultiPart::mixed() .singlepart( SinglePart::builder() .header(ContentType::TEXT_HTML) .body(html_body), ) .singlepart( Attachment::new("document.pdf".to_string()) .body(vec![0x25, 0x50, 0x44, 0x46], ContentType::parse("application/pdf")?), ), )?;
// 发送(类似于前面的例子)