Email message, Mime multipart types, and sync transports live in serenade-mailer (#153, #152, #228, #253).
| Type | Role |
|---|---|
Address |
Mailbox (email@host or Name <email@host>), parse / parse_list, Display |
Body |
Plain text and/or HTML |
Attachment |
Downloadable or inline (CID) part: filename, MIME type, bytes, disposition |
ContentDisposition |
Attachment vs Inline |
Email |
Builder for headers, subject, body, attach / embed |
MimeTree / MimePart |
Multipart layout: alternative / related / mixed |
MailerError |
Build / send failures |
Email::mime_tree() returns the nested structure SMTP encode uses:
- text + HTML →
multipart/alternative - HTML + CID embeds →
multipart/related(HTML alternative sibling when text is present) - downloadable files → outer
multipart/mixed
| Transport | Role |
|---|---|
NullTransport |
Discards messages (default DI mailer) |
FileTransport |
Writes a readable dump under a directory |
SmtpTransport |
SMTP via lettre (Cargo feature smtp, on by default) |
EspHttpTransport |
HTTP ESP mail API (Cargo feature esp, off by default) |
All implement Transport with sync send.
FrameworkExtension adds [RegisterDefaultMailerPass], which registers service id mailer (DEFAULT_MAILER_SERVICE) tagged mailer.transport with a NullTransport when missing. Resolve MailerService and call send.
Apps replace the default by registering their own mailer service (file or SMTP) before compile.
use serenade_mailer::{Attachment, Email, FileTransport, NullTransport, Transport};
let email = Email::new()
.from("Shop <shop@example.test>")?
.to("buyer@example.test")?
.subject("Order confirmation")
.text("Thanks for your order.")
.html("<p>Thanks <img src=\"cid:logo@shop\" /></p>")
.embed(Attachment::inline_from_bytes(
"logo.png",
"image/png",
"logo@shop",
b"\x89PNG".as_slice(),
))
.attach(Attachment::from_bytes(
"receipt.txt",
"text/plain",
b"order-1".as_slice(),
));
assert_eq!(email.mime_tree().multipart_subtype(), Some("mixed"));
NullTransport::new().send(&email)?;
FileTransport::new("var/mail").send(&email)?;SMTP (feature smtp):
use serenade_mailer::{SmtpTransport, Transport};
let smtp = SmtpTransport::relay("smtp.example.test")
.credentials("user", "pass")
.build()?;
smtp.send(&email)?;Enable with serenade-mailer feature esp. Serenade shapes a SendGrid-class JSON mail
API and a sync [EspHttpPoster] trait; apps own the HTTP client (no mandatory vendor SDK).
| Piece | Role |
|---|---|
EspApiConfig |
Endpoint URL + API key (Authorization: Bearer <api_key>) |
EspHttpPoster / MockEspHttpPoster |
Sync POST trait + test double |
EspHttpTransport |
Builds JSON from Email, POSTs, requires 2xx |
build_esp_payload |
Shared JSON encoder (text/HTML; attachments omitted) |
use serenade_mailer::{
EspApiConfig, EspHttpTransport, MockEspHttpPoster, Transport,
};
let poster = MockEspHttpPoster::accepted();
let transport = EspHttpTransport::new(
EspApiConfig::new("https://api.example/v3/mail/send", "api-key"),
poster,
);
transport.send(&email)?;