SemitraMailer and SemitraMailbox are the mail subsystem in Semitra.
Use them for outbound and inbound email workflows.
Mailers
Section titled “Mailers”SemitraMailer turns validated params into a message object.
Core capabilities:
- payload validation through a schema
- direct delivery through
deliver() - queued delivery through
enqueue()anddeliverLater() - tenant propagation
- delivery observation hooks
Example mailer:
import { s } from "@semitra/cli";import ApplicationMailer from "./application_mailer.ts";
export const WelcomeMailParams = s.object({ email: s.string(), title: s.string().min(3)});
export default class WelcomeMailer extends ApplicationMailer<{ email: string; title: string;}> { static params = WelcomeMailParams;
mail(payload: { email: string; title: string }) { return { to: payload.email, subject: `Welcome to ${payload.title}`, text: `Hello from ${payload.title}` }; }}Mailboxes
Section titled “Mailboxes”SemitraMailbox handles inbound mail.
It is the inverse of a mailer:
- parse and validate payloads
- receive an inbound message
- perform the application-specific side effect
- optionally observe the receive flow
Example mailbox:
import { SemitraEvents, s } from "@semitra/cli";import ApplicationMailbox from "./application_mailbox.ts";
const SupportInboundParams = s.object({ from: s.string().email(), subject: s.string().min(3), text: s.string().min(1)});
export default class SupportMailbox extends ApplicationMailbox<{ from: string; subject: string; text: string;}> { static params = SupportInboundParams;
async receive(payload: { from: string; subject: string; text: string; }): Promise<void> { await SemitraEvents.emitAsync("support:email_received", { from: payload.from, subject: payload.subject, excerpt: payload.text.slice(0, 120) }); }}That shape works well when inbound support email should be validated once and then handed off to the rest of the app as a normal domain event.
Example use cases
Section titled “Example use cases”- send a welcome email after user creation
- notify a user when a background report is ready
- process inbound support email into a ticket
- react to inbound webhook-style email events through a mailbox
Good use cases
Section titled “Good use cases”- transactional email
- operational email
- inbound email handling
- scheduled or queued mail delivery
Mail discipline
Section titled “Mail discipline”Keep the mail subsystem focused on message composition and message handling. If the work is really domain logic, put the domain decision in the controller, model, or job that calls the mailer or mailbox.