Отправка email на Rust: библиотеки lettre и async-smtp
Отправка электронных писем — базовая функция любого образовательного или коммерческого сайта. В экосистеме Rust для этой задачи есть несколько зрелых решений. В этой статье мы разберём две наиболее популярные библиотеки: lettre (синхронная отправка) и async-smtp (асинхронная отправка). Вы узнаете, как настроить SMTP-клиент, отправить простое письмо, добавить вложения и обработать ошибки.
1. Библиотека lettre — синхронная отправка
lettre — это модульная библиотека для работы с почтовыми протоколами (SMTP, SMTPS, STARTTLS). Она поддерживает:
- Отправку через внешний SMTP-сервер (Gmail, Яндекс, Mail.ru, самописный).
- Поддержку MIME-форматов (текст, HTML, вложения).
- Шифрование TLS/SSL.
- Работу с кодировками (Base64, quoted-printable).
1.1. Установка lettre
Добавьте в Cargo.toml:
[dependencies]
lettre = "0.11"
lettre_email = "0.11" # устаревший, но ещё используется
# Для асинхронной версии — lettre с feature "tokio1" или "async-std1"
1.2. Пример: отправка простого письма через SMTP
use lettre::transport::smtp::authentication::Credentials;
use lettre::transport::smtp::SmtpTransport;
use lettre::message::Message;
use lettre::MessageBuilder;
fn main() {
// Создаём письмо
let email = Message::builder()
.from("sender@example.com".parse().unwrap())
.to("recipient@example.com".parse().unwrap())
.subject("Привет из Rust!")
.body("Это тестовое письмо, отправленное с помощью библиотеки lettre.".to_string())
.unwrap();
// Настройки SMTP-сервера (пример для Gmail)
let creds = Credentials::new("your_email@gmail.com".to_string(), "your_password".to_string());
// Открываем защищённое соединение
let mailer = SmtpTransport::starttls_relay("smtp.gmail.com")
.unwrap()
.credentials(creds)
.build();
// Отправляем
match mailer.send(&email) {
Ok(_) => println!("Письмо отправлено успешно!"),
Err(e) => eprintln!("Ошибка отправки: {}", e),
}
}
1.3. Пример: письмо с HTML-содержимым и вложением
use lettre::message::{MultiPart, SinglePart};
use lettre::Message;
fn build_html_email() -> Message {
// HTML-часть
let html_part = SinglePart::builder()
.header(lettre::message::header::ContentType::TEXT_HTML)
.body(String::from("<h1>Привет!</h1><p>Это HTML-письмо.</p>"));
// Вложение (например, PDF-файл)
let attachment = SinglePart::builder()
.header(lettre::message::header::ContentType::parse("application/pdf").unwrap())
.body(vec![0x25, 0x50, 0x44, 0x46]); // заглушка для PDF
// Собираем многокомпонентное письмо
Message::builder()
.from("from@example.com".parse().unwrap())
.to("to@example.com".parse().unwrap())
.subject("Письмо с HTML и вложением")
.multipart(
MultiPart::mixed()
.multipart(MultiPart::alternative().singlepart(html_part))
.singlepart(attachment),
)
.unwrap()
}
2. Асинхронная отправка: async-smtp
Библиотека async-smtp предназначена для неблокирующей отправки писем в асинхронных приложениях (например, в связке с tokio или async-std). Она использует тот же API, что и lettre, но с async/await.
2.1. Установка async-smtp
[dependencies]
async-smtp = "0.6"
tokio = { version = "1", features = ["full"] }
2.2. Пример: асинхронная отправка
use async_smtp::{SmtpClient, SmtpTransport};
use async_smtp::authentication::Credentials;
use lettre::message::Message;
#[tokio::main]
async fn main() {
// Создаём письмо (как в lettre)
let email = Message::builder()
.from("sender@example.com".parse().unwrap())
.to("recipient@example.com".parse().unwrap())
.subject("Асин