Documentation
¶
Overview ¶
Package mail integrates an outbound e-mail provider as a server-registered Atlas connector: a BPMN mail connector task sends a model-authored message through a configured provider via the job path (ADR-0079), mirroring how the clio package delegates an append to a registry-managed endpoint (ADR-0036). The integration inherits the job protocol's durability and non-blocking properties (ADR-0007):
- A connector task creates a job carrying the reserved compiler.MailJobType. The processor never performs the outbound send itself, so it stays allocation-free (invariant I1) and free of any SMTP dependency.
- The in-process Handler — a job worker — pulls those jobs, sends the message off the processor goroutine and after fsync (invariant I2, never inside applyToState / I4), and completes the job, which drives the token onward.
- The provider host and credentials live in a server-side Registry keyed by connector name, so a model refers to a provider by name only and never carries a host or a secret (ADR-0036/0041). Only the message (recipients, subject, body) is authored in the model, like a REST task's endpoint (ADR-0067).
The first provider is SMTP (SMTPClient), which reaches Google, Microsoft 365, and any standards-compliant server via its submission endpoint; native Gmail / Microsoft Graph API providers are additive behind the same Client seam (ADR-0079).
Delivery is at-least-once (a crash between "the provider accepted the message" and "job completed" replays the send); every message carries the job key as its RFC 5322 Message-ID so a provider or downstream de-duplicator can recognize a replayed send rather than delivering it twice.
Index ¶
Constants ¶
const ( ProviderSMTP = "smtp" ProviderGmail = "gmail" ProviderMicrosoft = "microsoft" )
Provider identifiers for a managed mail connector. SMTP (the default) reaches any submission server; Gmail and Microsoft are the native provider APIs (ADR-0079/0081).
Variables ¶
This section is empty.
Functions ¶
func Handler ¶
Handler builds a job handler that performs an outbound mail connector task. Register it with a job.Runner for the reserved compiler.MailJobTypeIndex; the runner then pulls activatable mail jobs, and for each the handler resolves the task's connector/recipients/subject/body from the compiled process — evaluating any FEEL field over the instance's variables (the fx toggle, ADR-0067) — resolves the named connector's provider client from reg, and sends the message keyed by the job key so an at-least-once retry de-duplicates (ADR-0079). Returning an error leaves the job pending (retry, then an incident, ADR-0061); the runner completes it only on success.
Types ¶
type Client ¶
Client sends a Message through one configured mail provider. It is an interface so the worker is testable without a live server and so a connector name binds to exactly one provider (SMTP today; a native Gmail / Graph provider is additive).
func NewProviderClient ¶
func NewProviderClient(cfg ProviderConfig) (Client, error)
NewProviderClient builds the mail client for a managed connector, dispatching on its provider. SMTP is the default; Gmail and Microsoft Graph parse the credential bundle and build an OAuth token source. A misconfigured connector returns an error so the caller can skip it (its tasks park) rather than sending wrongly. This is the single place a new provider is added.
type Connector ¶
Connector is the server-side configuration of one SMTP mail provider: the submission Endpoint ("host:port"), the auth Username and Password (the Password is the resolved secret — an app password or account password — held only at call time, never persisted, I6), and the default From address a task that authors no sender falls back to.
type GmailClient ¶
type GmailClient struct {
// contains filtered or unexported fields
}
GmailClient sends mail through the Gmail API (ADR-0093). It posts a base64url-encoded RFC 5322 message to /users/me/messages/send with a bearer token from its TokenSource; "me" resolves to the authenticated user (the impersonated subject under a service account, or the refresh token's user). It frames the message with the same MIME builder the SMTP client uses.
func NewGmailClient ¶
func NewGmailClient(tokens TokenSource, baseURL, sender string) *GmailClient
NewGmailClient builds a Gmail mail client. baseURL defaults to the Gmail v1 API when empty; sender is the default From address a task without one falls back to.
type GraphClient ¶
type GraphClient struct {
// contains filtered or unexported fields
}
GraphClient sends mail through the Microsoft Graph sendMail API (ADR-0093). It posts a structured message to /users/{mailbox}/sendMail with a bearer token from its TokenSource; the mailbox is the message's From or the connector's default sender. It reaches Microsoft 365 mailboxes with an app-only or refresh-token grant.
func NewGraphClient ¶
func NewGraphClient(tokens TokenSource, baseURL, sender string) *GraphClient
NewGraphClient builds a Graph mail client. baseURL defaults to the Graph v1.0 API when empty; sender is the default mailbox to send as.
type Message ¶
type Message struct {
From string
To []string
Cc []string
Bcc []string
Subject string
Body string
MessageID string
}
Message is one e-mail an outbound mail connector task sends. To is the required recipient list; Cc and Bcc are optional. From overrides the provider's default sender when set. MessageID is deterministic (the job key), so an at-least-once retry carries the same RFC 5322 Message-ID and can be de-duplicated rather than delivered twice.
type ProcessLookup ¶
type ProcessLookup func(defKey uint64) *compiler.CompiledProcess
ProcessLookup resolves a process-definition key to its compiled process. The worker uses it to find the connector name and message fields a mail job belongs to, so one handler serves every deployed process.
type ProviderConfig ¶
ProviderConfig is the per-connector data the server resolves before building a client: the provider, an optional endpoint override, the default sender, and the resolved Secret — an SMTP password, or (for a native provider) the OAuth credential JSON bundle held in the vault under the connector's credentialsRef (ADR-0093). The secret lives only here at build time, never in a model or an event (I6).
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry resolves a connector name to the Client for its mail provider. Connectors are registered at the server from managed configuration (endpoint plus credentials), so a model refers to a connector by name only (ADR-0036/0041). A Registry is read-only once populated and safe for concurrent use by workers.
func (*Registry) Client ¶
Client returns the client bound to name, or nil and false if none is registered.
func (*Registry) Register ¶
Register binds a connector name to its client. Registering the same name again replaces the earlier binding (last write wins), so reconfiguration is simple.
func (*Registry) Replace ¶
Replace swaps the whole set of registered connectors at once, so a server can rebuild the registry from managed configuration after a change (ADR-0041). The caller must serialize Replace with the workers that read the registry — the Atlas server does both on its run-loop goroutine — so no lock is needed. A nil map clears the registry.
type SMTPClient ¶
type SMTPClient struct {
// contains filtered or unexported fields
}
SMTPClient sends a Message over SMTP (the submission endpoint of any standards compliant provider, including Google and Microsoft 365). It authenticates with the connector's username/password when a username is configured, and frames the message as a UTF-8 text/plain e-mail.
func NewSMTPClient ¶
func NewSMTPClient(conn Connector) *SMTPClient
NewSMTPClient builds an SMTP mail client for a configured connector, backed by net/smtp's SendMail.
func (*SMTPClient) Send ¶
func (c *SMTPClient) Send(ctx context.Context, m Message) error
Send frames m as a UTF-8 text/plain e-mail and submits it to the connector's SMTP endpoint. The sender is the message's From, or the connector's default From when the task authored none; a message with no sender and no default is a configuration error. Recipients are the union of To, Cc and Bcc (the SMTP envelope); Bcc addresses are delivered but never written into a header. A missing recipient or a send failure returns an error so the job stays pending and is retried (at-least-once).