LemonChannels. Adapters. Email. Outbound
(lemon_channels v0.1.0)
View Source
Sends mail for the email channel adapter over an SMTP relay.
Ported from LemonGateway.Transports.Email.Outbound. smtp_options/1 is the
same function it always was — its configuration semantics are pinned by
characterization tests that were written before the move and carried over
unchanged, so a difference there is a regression rather than a design choice.
What the port had to change
The gateway version was handed a finished run (deliver(job, completed)) and
read its reply headers out of job.meta.email_reply, which the inbound half
had put there. A LemonChannels.Plugin adapter is handed a
LemonChannels.OutboundPayload instead, which carries the recipient, the
thread and the id being replied to — but deliberately not a Subject or a
References chain, since neither means anything to a channel that is not
email. Those come from LemonChannels.Adapters.Email.ThreadStore, which the
inbound half populates; see its moduledoc for why that state is worth
keeping.
Two behaviours did not survive, both because they described the old entrypoint rather than email:
- The
job.metaguard that madedeliver/2a silent no-op for non-email runs.deliver/1is only ever called for payloads addressed to this channel, so a payload it cannot send is now an{:error, reason}— an unsendable message should be reported, not swallowed. - The "Attachment references" list appended to the body from the run's
output files. In this pipeline a file is its own
:filepayload and is attached to its own message, so there is nothing to reference.
Summary
Functions
The reply headers payload would be sent with.
Sends payload as a reply on its thread.
Builds :gen_smtp_client options from an email config map.
Functions
@spec build_envelope(LemonChannels.OutboundPayload.t(), map()) :: {:ok, map()} | {:error, term()}
The reply headers payload would be sent with.
Public so the threading decisions — which subject a reply carries, which
ancestors end up in References — are assertable without an SMTP server
standing by. Not part of the adapter's contract with the platform.
@spec deliver(LemonChannels.OutboundPayload.t() | term()) :: {:ok, binary()} | {:error, term()}
Sends payload as a reply on its thread.
Returns {:ok, message_id} with the Message-ID of the sent mail, which is
also recorded against the thread so the recipient's reply threads back.
Builds :gen_smtp_client options from an email config map.
{:error, :missing_smtp_relay} when no relay is configured, which is the
common case: this adapter is inert until someone points it at a relay.