Отправка email на Rust: библиотеки lettre и async-smtp для почтовых рассылок

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Отправка 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("Асин                    

Рекомендаций