Mailglass.Message (Mailglass v1.0.0)

Copy Markdown View Source

A rendered or partially-rendered email message.

Mailglass.Message wraps %Swoosh.Email{} and carries mailglass-specific metadata. It is the central data structure passed through the render pipeline and returned from Mailglass.Renderer.render/2.

Domain Language

A Message is the rendered form of a Mailable (a source-level definition). The Renderer populates swoosh_email.html_body and swoosh_email.text_body by transforming the HEEx template through the CSS inliner and plaintext extractor.

Mailglass never bypasses Swoosh for content — it enriches the inner struct. The Message adds the metadata Swoosh doesn't model: which mailable built it, which tenant it belongs to, which stream it rides on, and adopter-supplied tags and metadata.

Fields

  • :swoosh_email — the inner %Swoosh.Email{} struct. All email content (to, from, subject, html_body, text_body, headers, attachments) lives here.
  • :mailable — the adopter module that built this message (e.g. MyApp.UserMailer). Used for telemetry, the Mailglass-Mailable header, and preview auto-discovery.
  • :mailable_function — the mailable function that built this message (e.g. :welcome, :password_reset). Populated by the use Mailglass.Mailable macro's injected builder (D-38). Used by the runtime auth-stream tracking guard. Default: nil.
  • :tenant_id — multi-tenant scope. Carried on every record (CORE-03, D-09 project-level). nil in single-tenant mode.
  • :stream — message stream: :transactional, :operational, or :bulk. Auth and security emails must use :transactional (no tracking, per D-08 project-level). Default: :transactional.
  • :tags — free-form string tags for filtering and analytics. Default: [].
  • :metadata — adopter-supplied extras. PII-free by convention (not included in telemetry). Default: %{}.

Examples

iex> email = Swoosh.Email.new(subject: "Welcome")
iex> msg = Mailglass.Message.build(email, mailable: MyApp.UserMailer)
iex> msg.stream
:transactional
iex> msg.mailable
MyApp.UserMailer

Summary

Functions

Merges a keyword list or map into the message assigns.

Sets a single key-value pair in the message assigns.

Adds an attachment to the message.

Sets the sender of the message.

Sets a custom header on the message.

Sets the HTML body of the message.

Creates a new Mailglass.Message wrapping the given %Swoosh.Email{}.

Creates a new Mailglass.Message from use Mailglass.Mailable opts.

Stamps the :mailable_function field on a %Message{}.

Returns a new %Message{} with the given key put into metadata.

Sets the stream for the message.

Appends a tag to the message.

Sets the subject of the message.

Sets the text body of the message.

Sets the recipient of the message.

Updates the inner %Swoosh.Email{} via a transformation function.

Types

stream()

@type stream() :: :transactional | :operational | :bulk

t()

@type t() :: %Mailglass.Message{
  assigns: %{required(atom()) => term()},
  mailable: module() | nil,
  mailable_function: atom() | nil,
  metadata: %{required(atom()) => term()},
  stream: stream(),
  swoosh_email: Swoosh.Email.t(),
  tags: [String.t()],
  tenant_id: String.t() | nil
}

Functions

assign(msg, attrs)

(since 0.4.0)
@spec assign(t(), map() | keyword()) :: t()

Merges a keyword list or map into the message assigns.

assign(msg, key, value)

(since 0.4.0)
@spec assign(t(), atom(), term()) :: t()

Sets a single key-value pair in the message assigns.

attach(msg, attachment)

(since 0.2.0)
@spec attach(t(), Swoosh.Attachment.t() | map()) :: t()

Adds an attachment to the message.

Delegates to Swoosh.Email.attachment/2.

from(msg, sender)

(since 0.2.0)
@spec from(t(), Swoosh.Email.address() | Swoosh.Email.mailbox()) :: t()

Sets the sender of the message.

Delegates to Swoosh.Email.from/2.

header(msg, name, value)

(since 0.2.0)
@spec header(t(), String.t(), String.t()) :: t()

Sets a custom header on the message.

Delegates to Swoosh.Email.header/3.

html_body(msg, html_body)

(since 0.2.0)
@spec html_body(t(), String.t()) :: t()

Sets the HTML body of the message.

Delegates to Swoosh.Email.html_body/2.

new(swoosh_email, opts \\ [])

(since 0.1.0)
This function is deprecated. Use native Mailglass.Message setters instead; retained as a compatibility bridge during the 1.x upgrade path.
@spec new(
  Swoosh.Email.t(),
  keyword()
) :: t()

Creates a new Mailglass.Message wrapping the given %Swoosh.Email{}.

This retained v0.1 constructor remains available as a deprecated compatibility path so older integrations can land on the 1.x stable lane in stages. New code should prefer native Mailglass.Message setters on the value returned by new/0 from use Mailglass.Mailable, or use new_from_use/2 inside builder-driven flows.

Options

  • :mailable — the module that built this message
  • :mailable_function — the mailable function atom (e.g. :welcome, :password_reset)
  • :tenant_id — tenant scope (nil in single-tenant mode)
  • :stream:transactional (default), :operational, or :bulk
  • :tags — list of string tags
  • :metadata — map of adopter-supplied extras (PII-free)

Examples

iex> email = Swoosh.Email.new(subject: "Welcome")
iex> msg = Mailglass.Message.build(email, mailable: MyApp.UserMailer)
iex> msg.stream
:transactional

new_from_use(mailable, use_opts)

(since 0.1.0)
@spec new_from_use(
  module(),
  keyword()
) :: t()

Creates a new Mailglass.Message from use Mailglass.Mailable opts.

Called by the injected new/0 function. Seeds :stream, :mailable, :tenant_id from the compile-time use opts. Applies :from_default from opts as the Swoosh.Email from header when present.

Examples

iex> msg = Mailglass.Message.new_from_use(MyMailer, stream: :transactional)
iex> msg.mailable
MyMailer
iex> msg.stream
:transactional

put_function(msg, fun_name)

(since 0.1.0)
@spec put_function(t(), atom()) :: t()

Stamps the :mailable_function field on a %Message{}.

Called in adopter mailable functions to record which function built the message. Required by the D-38 runtime tracking guard (Mailglass.Tracking.Guard.assert_safe!/1).

Examples

iex> msg = Mailglass.Message.new_from_use(MyMailer, stream: :transactional)
iex> msg2 = Mailglass.Message.put_function(msg, :welcome)
iex> msg2.mailable_function
:welcome

put_metadata(msg, key, value)

(since 0.1.0)
@spec put_metadata(t(), atom(), any()) :: t()

Returns a new %Message{} with the given key put into metadata.

Used by the send pipeline (Plan 05) to stamp delivery_id into the message's metadata AFTER the Delivery row is inserted but BEFORE the adapter is called — so Mailglass.Adapters.Fake records the same delivery_id that the DB persisted (otherwise TestAssertions.last_delivery() de-correlates from the real row).

put_stream(msg, stream)

(since 0.2.0)
@spec put_stream(t(), stream()) :: t()

Sets the stream for the message.

Valid streams are :transactional, :operational, and :bulk. Raises FunctionClauseError if an invalid stream atom is provided.

put_tag(msg, tag)

(since 0.2.0)
@spec put_tag(t(), String.t()) :: t()

Appends a tag to the message.

Modifies the :tags list on the %Mailglass.Message{} struct.

subject(msg, subject)

(since 0.2.0)
@spec subject(t(), String.t()) :: t()

Sets the subject of the message.

Delegates to Swoosh.Email.subject/2.

text_body(msg, text_body)

(since 0.2.0)
@spec text_body(t(), String.t()) :: t()

Sets the text body of the message.

Delegates to Swoosh.Email.text_body/2.

to(msg, recipient)

(since 0.2.0)

Sets the recipient of the message.

Delegates to Swoosh.Email.to/2.

update_swoosh(msg, fun)

(since 0.1.0)
@spec update_swoosh(t(), (Swoosh.Email.t() -> Swoosh.Email.t())) :: t()

Updates the inner %Swoosh.Email{} via a transformation function.

Enables adopters to pipe through Swoosh builder functions while keeping the outer %Message{} wrapper intact. Adopters building a mailable function use this pattern:

new()
|> Mailglass.Message.update_swoosh(fn e ->
     e
     |> Swoosh.Email.to(user.email)
     |> Swoosh.Email.subject("Welcome!")
   end)
|> Mailglass.Message.put_function(:welcome)