cratefield_core/ports/
mailer.rs1use async_trait::async_trait;
5use std::time::Duration;
6use thiserror::Error;
7
8#[derive(Debug, Clone)]
10pub struct Message {
11 pub to: String,
12 pub from: String,
13 pub reply_to: Option<String>,
14 pub subject: String,
15 pub html: String,
16 pub text: String,
17 pub idempotency_key: Option<String>,
19 pub tags: Vec<String>,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum SendOutcome {
25 Sent { id: String },
27 NotConfigured,
31}
32
33#[derive(Debug, Clone, Error)]
37pub enum MailError {
38 #[error("mailer rejected the request as unauthorized (check the API key)")]
39 Unauthorized,
40 #[error("sending domain {domain:?} is not verified with the mailer")]
41 DomainNotVerified { domain: String },
42 #[error("mailer rejected the message as invalid: {detail}")]
43 Invalid { detail: String },
44 #[error("mailer rate limited the request; retry after {retry_after:?}")]
45 RateLimited { retry_after: Option<Duration> },
46 #[error("mailer upstream error: {0}")]
47 Upstream(String),
48 #[error("mailer transport error: {0}")]
49 Transport(String),
50}
51
52#[async_trait]
53pub trait Mailer: Send + Sync {
54 async fn send(&self, message: Message) -> Result<SendOutcome, MailError>;
55}