Actix Web¶
Инструкция для приложений на Actix Web (Rust). Mailexam подключается как SMTP-сервер; для отправки используется крейт lettre с асинхронным транспортом под Tokio (Actix Web 4 работает на Tokio).
Что понадобится¶
- Аккаунт Mailexam и проект с SMTP-учётными данными.
- Rust 1.70+ и проект на Actix Web 4.
Скопируйте из приветственного письма (или кабинета) для вашего проекта:
ВАШ_ЛОГИН— SMTP-логин (например,xxxxx);ВАШ_ПАРОЛЬ— SMTP-пароль (уникальная пара к логину);- хост —
ВАШ_ЛОГИН.mailexam.ru(совпадает с логином, см. код ниже).
1. Зависимости¶
В Cargo.toml:
[dependencies]
actix-web = "4"
serde = { version = "1", features = ["derive"] }
lettre = { version = "0.11", default-features = false, features = [
"builder",
"smtp-transport",
"tokio1-rustls-tls",
] }
Для загрузки настроек из окружения (по желанию):
2. Переменные окружения¶
Файл .env в корне проекта (не коммитьте пароли в git):
MAILEXAM_LOGIN=ВАШ_ЛОГИН
MAILEXAM_PASSWORD=ВАШ_ПАРОЛЬ
MAILEXAM_PORT=587
MAIL_FROM=noreply@example.test
Хост собирается из логина: {MAILEXAM_LOGIN}.mailexam.ru.
Адрес отправителя
MAIL_FROM может быть любым тестовым адресом — письмо попадёт в Mailexam, а не реальному получателю.
Альтернативные порты¶
3. Модуль отправки почты¶
Тот же модуль, что и для Axum: MailConfig::from_env() и send_test через lettre.
// src/mail.rs
use lettre::message::header::ContentType;
use lettre::transport::smtp::authentication::Credentials;
use lettre::{AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor};
#[derive(Clone)]
pub struct MailConfig {
pub host: String,
pub port: u16,
pub username: String,
pub password: String,
pub from: String,
}
impl MailConfig {
pub fn from_env() -> Self {
let login = std::env::var("MAILEXAM_LOGIN").expect("MAILEXAM_LOGIN");
Self {
host: format!("{login}.mailexam.ru"),
port: std::env::var("MAILEXAM_PORT")
.unwrap_or_else(|_| "587".into())
.parse()
.expect("MAILEXAM_PORT"),
username: login,
password: std::env::var("MAILEXAM_PASSWORD").expect("MAILEXAM_PASSWORD"),
from: std::env::var("MAIL_FROM")
.unwrap_or_else(|_| "noreply@example.test".into()),
}
}
}
pub async fn send_test(
config: &MailConfig,
to: &str,
subject: &str,
body: &str,
) -> Result<(), lettre::transport::smtp::Error> {
let email = Message::builder()
.from(config.from.parse().expect("MAIL_FROM"))
.to(to.parse().expect("recipient"))
.subject(subject)
.header(ContentType::TEXT_PLAIN)
.body(body.to_string())
.expect("message");
let creds = Credentials::new(config.username.clone(), config.password.clone());
let mailer = AsyncSmtpTransport::<Tokio1Executor>::starttls_relay(&config.host)?
.port(config.port)
.credentials(creds)
.build();
mailer.send(email).await
}
4. Обработчик Actix Web¶
// src/main.rs
mod mail;
use actix_web::{post, web, App, HttpResponse, HttpServer, Responder};
use mail::MailConfig;
use serde::Deserialize;
#[derive(Deserialize)]
struct SendRequest {
to: String,
subject: Option<String>,
body: Option<String>,
}
#[post("/mail/test")]
async fn send_mail(
config: web::Data<MailConfig>,
payload: web::Json<SendRequest>,
) -> impl Responder {
mail::send_test(
&config,
&payload.to,
payload.subject.as_deref().unwrap_or("Actix + Mailexam"),
payload.body.as_deref().unwrap_or("Тест Mailexam из Actix"),
)
.await
.expect("smtp send");
HttpResponse::Ok().body("ok")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenvy::dotenv().ok();
let config = web::Data::new(MailConfig::from_env());
HttpServer::new(move || {
App::new()
.app_data(config.clone())
.service(send_mail)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Запуск и проверка:
curl -X POST http://127.0.0.1:8080/mail/test \
-H 'Content-Type: application/json' \
-d '{"to":"user@example.test","subject":"Проверка","body":"Привет"}'
Письмо появится в кабинете Mailexam → ваш проект → входящие.
5. Локальная разработка и CI¶
| Среда | Рекомендация |
|---|---|
local |
.env с личным проектом Mailexam |
| CI | Секреты MAILEXAM_LOGIN, MAILEXAM_PASSWORD в GitLab CI/CD Variables |
Пример для .gitlab-ci.yml:
variables:
MAILEXAM_LOGIN: $MAILEXAM_LOGIN
MAILEXAM_PASSWORD: $MAILEXAM_PASSWORD
MAILEXAM_PORT: "587"
MAIL_FROM: "noreply@example.test"
После интеграционного теста с отправкой письма проверьте доставку через API Mailexam.
6. Типичные проблемы¶
Ошибка TLS или подключения
- Хост должен быть
{логин}.mailexam.ru, где{логин}— то же значение, чтоMAILEXAM_LOGINиз письма. - Логин и пароль — пара из письма; не комбинируйте данные разных проектов.
- Для порта 587 используйте
starttls_relay, не SMTPS на 465.
Письмо не в кабинете
- Убедитесь, что смотрите входящие того же проекта Mailexam.
- Проверьте логи воркеров Actix: ошибки SMTP видны при падении
send_test.
Сборка lettre
- Для TLS нужен feature
tokio1-rustls-tls(илиtokio1-native-tlsпри необходимости).
Порт занят
- По умолчанию сервер слушает
8080; измените адрес в.bind(...)при конфликте.
См. также¶
- Каталог примеров
- Пример реализации (Actix Web)
- Axum — тот же
mail‑модуль, другой HTTP-фреймворк - Документация REST API Mailexam
- Документация Actix Web
- Документация lettre