Временная почта
на Rust.
Одноразовые ящики и извлечение OTP для Rust — обычный HTTP, без SDK.
use serde_json::{json, Value};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let key = std::env::var("EVILMAIL_KEY")?;
let res: Value = reqwest::blocking::Client::new()
.post("https://evilmail.pro/api/temp-email")
.header("X-API-Key", key)
.json(&json!({ "ttlMinutes": 30 }))
.send()?
.json()?;
let email = res["data"]["email"].as_str().unwrap_or("");
println!("Inbox: {email}");
Ok(())
}Создание временного почтового ящика в Rust позволяет тестировать процессы регистрации, подтверждение email и доставку OTP без настоящего почтового ящика или ненадёжного общего аккаунта. EvilMail предоставляет обычный HTTP API: создайте одноразовый ящик, опрашивайте его на входящие письма и извлекайте код подтверждения прямо в свои интеграционные тесты или CI-пайплайн. Не нужно поднимать SMTP-сервер и подключать SDK — только reqwest, serde_json и API-ключ из переменной окружения.
Зачем использовать временную почту на Rust
Сквозные тесты регистрации
Регистрируйте настоящий аккаунт в staging-окружении, используя свежий одноразовый email, а затем проверяйте, что приветственное письмо или письмо с подтверждением действительно доходит. Никакого общего ящика, который нужно чистить между запусками.
Автоматизация OTP и 2FA
Дождитесь письма для входа или подтверждения, извлеките шестизначный код из тела письма регулярным выражением и передайте его обратно в ваш процесс. Идеально для тестирования беспарольных и двухфакторных входов в Rust.
Проверка email в CI-пайплайне
Считывайте API-ключ из переменной окружения и запускайте весь цикл «создать — опросить — прочитать» внутри GitHub Actions или GitLab CI. Каждая сборка получает чистый изолированный почтовый ящик.
Извлечение ссылок подтверждения
Получайте URL активации или magic-ссылки из текста или HTML сообщения, переходите по ним через reqwest и проверяйте, что весь путь онбординга работает без участия человека.
Процесс — временная почта Rust за 3 вызова
Создайте одноразовый ящик
use serde_json::{json, Value};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let key = std::env::var("EVILMAIL_KEY")?;
let client = reqwest::blocking::Client::new();
// Ask EvilMail for a fresh inbox that lives 30 minutes.
let res: Value = client
.post("https://evilmail.pro/api/temp-email")
.header("X-API-Key", &key)
.json(&json!({ "ttlMinutes": 30 }))
.send()?
.json()?;
let email = res["data"]["email"].as_str().unwrap_or("");
let token = res["data"]["sessionToken"].as_str().unwrap_or("");
println!("Inbox {email} ready (token {token})");
Ok(())
}Опрашивайте, пока не придёт письмо
use serde_json::Value;
use std::{thread::sleep, time::Duration};
// Poll the session ~20 times, 3s apart, until mail lands.
fn wait_for_message(
client: &reqwest::blocking::Client,
key: &str,
token: &str,
) -> Result<u64, Box<dyn std::error::Error>> {
let url =
format!("https://evilmail.pro/api/temp-email/{token}");
for _ in 0..20 {
let res: Value = client
.get(&url)
.header("X-API-Key", key)
.send()?
.json()?;
// messages is empty until something is delivered.
if let Some(msg) = res["data"]["messages"].get(0) {
let uid = msg["uid"].as_u64().unwrap_or(0);
let subject = msg["subject"].as_str().unwrap_or("");
println!("Got mail: {subject} (uid {uid})");
return Ok(uid);
}
sleep(Duration::from_secs(3));
}
Err("timed out waiting for email".into())
}Прочитайте сообщение и извлеките код
use regex::Regex;
use serde_json::Value;
// Fetch the message body and pull out a 6-digit OTP.
fn extract_code(
client: &reqwest::blocking::Client,
key: &str,
token: &str,
uid: u64,
) -> Result<Option<String>, Box<dyn std::error::Error>> {
let url = format!(
"https://evilmail.pro/api/message/{uid}?token={token}"
);
let res: Value = client
.get(&url)
.header("X-API-Key", key)
.send()?
.json()?;
let body = res["data"]["text"].as_str().unwrap_or("");
// A one-time code is six consecutive digits.
let re = Regex::new(r"\b(\d{6})\b")?;
let code = re.captures(body).map(|c| c[1].to_string());
match &code {
Some(c) => println!("OTP = {c}"),
None => println!("No 6-digit code found"),
}
Ok(code)
}Временная почта Rust — FAQ
Q1Как получить временный почтовый адрес в Rust?−
Отправьте POST на https://evilmail.pro/api/temp-email с заголовком X-API-Key и JSON-телом вида {"ttlMinutes": 30}. В ответе будут data.email (одноразовый адрес) и data.sessionToken, который используется для опроса и чтения сообщений. Смотрите сниппет в шапке — это около десяти строк с reqwest и serde_json.
Q2Можно ли использовать это для автоматизированного тестирования?+
Да — это основной сценарий использования. Считывайте API-ключ из переменной окружения, создавайте свежий ящик для каждого теста и запускайте цикл «создать — опросить — прочитать» внутри своего набора интеграционных тестов или CI. Поскольку каждый ящик изолирован и живёт недолго, тесты не мешают друг другу и после них нечего чистить.
Q3Как извлечь OTP?+
Вызовите GET /api/message/{uid}?token={sessionToken}, чтобы получить сообщение, а затем примените регулярное выражение к data.text (или data.html). Для стандартного шестизначного одноразового кода подходит шаблон \b(\d{6})\b; код находится в группе захвата 1. Сниппет для шага 3 показывает это с использованием крейта regex.
Q4Нужен ли API-ключ / есть ли ограничения по частоте запросов?+
Да, каждому запросу нужен заголовок X-API-Key — храните ключ в переменной окружения, например EVILMAIL_KEY, а не в коде. Запросы ограничены по частоте для каждого ключа, поэтому при опросе придерживайтесь разумного интервала (в примерах используется 3 секунды между примерно 20 попытками опроса) вместо частого зацикливания.
Q5Как долго живёт ящик?+
Вы управляете этим через поле ttlMinutes при создании ящика — в примерах используется 30 минут. Как только TTL истекает, адрес и его сообщения удаляются, поэтому опрашивайте и читайте сообщение в пределах этого окна. Для большинства процессов подтверждения и OTP короткого TTL в 10–30 минут вполне достаточно.
Временная почта на других языках
Один API-ключ. Одноразовые ящики в масштабе.
Создавайте неограниченное число одноразовых адресов, опрашивайте их по HTTP и получайте коды подтверждения прямо в тесты и CI. Бесплатно на старте; собственные домены и повышенные лимиты на платных тарифах.

