MyronCMS Developers Hub Docs sandbox review

Reference

Mail Envelope And Result Reference

MailEnvelope is the normalized message object passed into a MailTransportInterface. MailDispatchResult is the stable success or failure object returned by a transport.

These objects are intentionally narrow. Provider transports can translate them into provider-specific payloads, but the source contract for extension authors is the object shape below.

Human Path

Extension authors read this page while implementing MailTransportInterface::send():

public function send(MailEnvelope $envelope): MailDispatchResult
{
    if (!$this->isConfigured()) {
        return MailDispatchResult::failed('x.my_vendor.api', 'mail_provider_not_configured');
    }

    return MailDispatchResult::ok('x.my_vendor.api', 'provider-message-id');
}

AI Path

An AI coding agent can use this reference while authoring a local transport class. It should treat source files as authoritative and avoid inventing provider fields.

An installed MCP client can inspect loaded transport descriptors when scoped, but this reference page itself is local documentation. It does not expose a standalone MCP resource.

Scopes

Reading this reference requires no runtime scope.

Runtime descriptor inspection uses administration.read through /api/v1/administration/mail/transports. Sending mail happens through MyronCMS mail callers and the active transport, not by granting callers direct access to these objects.

MailEnvelope Fields

Constructor fields:

FieldTypeRequiredMeaning
tostringYesRecipient email address.
subjectstringYesMessage subject.
htmlBodystringYesHTML message body.
textBodystringYesPlain text body.
fromEmailstringYesSender email address.
fromNamestringYesSender display name.
replyTo?stringNoOptional reply-to email address.
headersarray<string, string>NoOptional allowlisted Myron headers.

toArray() emits:

[
    'to' => $this->to,
    'subject' => $this->subject,
    'htmlBody' => $this->htmlBody,
    'textBody' => $this->textBody,
    'fromEmail' => $this->fromEmail,
    'fromName' => $this->fromName,
    'replyTo' => $this->replyTo,
    'headers' => $this->headers,
]

fromArray() reads the same keys and casts missing scalar values to empty strings. It only preserves these header names:

HeaderCurrent behavior
x-myron-contextPreserved when supplied in headers.
x-myron-sourcePreserved when supplied in headers.

Other headers passed into fromArray() are ignored. Do not document arbitrary provider headers as core envelope fields.

MailDispatchResult Fields

Constructor fields:

FieldTypeRequiredMeaning
okboolYesWhether the transport completed successfully.
transportIdstringYesCore slug such as smtp or extension id such as x.my_vendor.api.
providerMessageId?stringNoOptional id returned by the provider on success.
error?stringNoStable error string on failure.

Use the named constructors:

MailDispatchResult::ok('x.my_vendor.api', 'provider-message-id');
MailDispatchResult::failed('x.my_vendor.api', 'mail_provider_not_configured');

toArray() emits:

[
    'ok' => $this->ok,
    'transportId' => $this->transportId,
    'providerMessageId' => $this->providerMessageId,
    'error' => $this->error,
]

Artifacts

Source artifacts:

  • app/system/mail/MailEnvelope.php
  • app/system/mail/MailDispatchResult.php
  • app/system/mail/MailTransportInterface.php

Runtime usage:

  • MyronMailer creates MailEnvelope from saved mail settings and message content.
  • MyronSmtpTransport reads MailEnvelope and returns MailDispatchResult.
  • Extension transports implement the same object contract.

Safety Boundary

Do not add fields in documentation before they exist in source. Provider-specific concepts such as categories, templates, attachments, batch sends, or webhook metadata are not current MailEnvelope fields.

Do not use the headers array as an escape hatch for arbitrary provider headers. The current fromArray() path allowlists only x-myron-context and x-myron-source.

Do not leak provider exception payloads that may contain secrets. Convert provider failures into stable error strings where possible.

Verification

Run:

php app/tests/verify-forms-mail-substrate.php

The test verifies the active transport implements MailTransportInterface, the SMTP descriptor is present, and a MailEnvelope round trip through toArray() and fromArray() preserves expected fields.

For documentation review, compare field tables directly against:

  • MailEnvelope::__construct()
  • MailEnvelope::toArray()
  • MailEnvelope::fromArray()
  • MailDispatchResult::__construct()
  • MailDispatchResult::ok()
  • MailDispatchResult::failed()
  • MailDispatchResult::toArray()

Failure Modes

FailureLikely causeSafe response
Header missing after fromArray()Header name is not in the allowlist.Use only current allowlisted headers or evaluate a source change separately.
ok is false with no stable remediationTransport returned a raw or vague provider error.Map provider failures to stable error strings.
Provider payload needs unsupported fieldsProvider has requirements outside the current envelope.Use provider settings or a future contract; do not document unsupported core fields.
Caller treats descriptor listing as send accessDescriptor discovery was confused with mail dispatch authority.Keep listing, setup, and send-time behavior separate.