The direct answer
Drive explicit SMTP envelope addresses and controlled visible headers from the same approved message record. Interpret the documented submission outcome for each intended recipient, including partial refusal and uncertainty. A visible To field, recipient-command acceptance or successful relay submission does not prove mailbox delivery.
Review the transport destination as well as the message display
An AI application reviews a plain-text maintenance note for two known recipients, R-A and R-B. Its preview looks correct, but the sending adapter obtains transport recipients from a different object. An unchanged preview cannot establish where that adapter will submit the note.
This original worksheet selects Python’s smtplib reference and EmailMessage reference, both identifying Python 3.15.2, with RFC 5321 for SMTP outcome meaning. No installed Python, relay or account was inspected.
Current authorization and exact message approval remain prerequisites. This guide adds the adapter’s routing-field and submission-evidence decision. It does not authorize contacting anyone, and every worksheet case is PROPOSED_UNRUN.
Choose explicit envelope arguments instead of inference
The smtplib documentation distinguishes transport-envelope arguments from headers: sendmail uses from_addr and to_addrs for the envelope without modifying message headers. send_message delegates to sendmail. When envelope arguments are omitted, send_message extracts Sender/From and To/Cc/Bcc, with documented Resent handling. It suppresses Bcc and Resent-Bcc in transmitted headers.
Our stricter profile always supplies both from_addr and to_addrs explicitly. It excludes Cc, Bcc, Sender and every Resent field entirely. Bcc suppression is not an approval control: removing a visible field does not establish that the envelope contains only reviewed recipients. Adding R-C to an explicit list would still be an unauthorized expansion.
Keep message routing independent of model output. Resolve sender S-A and recipient records R-A/R-B through a trusted approved registry. Their separately validated, already suitable ASCII mailbox values are prerequisites; this article supplies no address parser, normalization rule or recipient-identity assurance.
Declare a complete controlled construction contract
Invent immutable action A-A binding configured sender record S-A, exactly R-A and R-B, reviewed subject revision H-2, plain-text body revision T-4 and trusted date value D-1. Approval covers those associations. The positive path uses a newly constructed standard EmailMessage owned only by the adapter, not a model-provided instance, subclass, raw MIME message or callable object.
| Field or component | Exclusive trusted source |
|---|---|
| Explicit from_addr | S-A’s approved envelope mailbox |
| Explicit to_addrs list | Exactly R-A and R-B mailbox values |
| Single From and To headers | The same sender and two recipient records, rendered by the trusted fixed template |
| Single Subject and Date headers | Reviewed single-line H-2 and fixed D-1 values |
| Payload and content metadata | Only approved ASCII plain text T-4 and the trusted template’s fixed plain-text MIME/encoding configuration |
| All other caller-supplied headers, parts and options | Not admitted; no Cc/Bcc/Resent/Reply-To, attachments, HTML or model-selected ESMTP options |
This is a construction contract, not a runnable factory or proof of safe serialization. The actual policy/content manager, encoding and generated header inventory need independent implementation verification before use. Python documents set_content as delegation to a content manager; do not infer that this call sanitizes arbitrary objects or preserves a desired policy automatically.
The EmailMessage reference also documents duplicate headers and undefined single-field lookup when duplicates exist; assignment does not simply overwrite. Do not approve a message by reading one To value from arbitrary input. The narrow profile prevents unreviewed fields from entering construction rather than repairing unknown MIME with a few accessor calls.
Separate recipient acceptance from message acceptance
RFC 5321 sections 3.3 and 4.2.5 distinguish recipient commands from the final response after message data. Positive final completion transfers responsibility to the receiving SMTP server; it does not establish completed mailbox delivery. A preliminary recipient acceptance or permission to start data is insufficient.
Python documents a normal sendmail return when at least one recipient is accepted, with a dictionary of refused recipients; all-recipient refusal raises SMTPRecipientsRefused. Interpret that through send_message’s documented delegation and the complete submission outcome. Under the stated relay prerequisites, a normal return with R-B refused supports R-A submitted-to-relay and R-B refused. An empty refusal map supports all intended recipients submitted, not delivered.
If recipient commands were accepted but the message data is refused, do not promote those earlier acceptances to submitted status. Keep refusal phases and actual evidence distinct. A disconnect or unavailable final result can leave submission unknown. RFC 5321 section 4.5.3.2.6 explains duplicate risk around final-response timeouts; this application must not blindly replay the whole approved set.
Review eight inert routing and outcome cards
| Inert case | Proposed disposition |
|---|---|
| A-A unchanged; explicit envelope and controlled headers contain exactly R-A/R-B | Eligible for the specifically authorized submission plan only after every prerequisite |
| Model observation proposes R-C or another sender | Reject expansion; retain approved registry associations |
| Envelope argument omitted or sourced from another object | Hold under this explicit-envelope profile |
| Hidden, Resent or duplicate routing-related header appears | Reject outside controlled construction; no silent repair |
| Normal complete submission return identifies only R-B refused | Record R-A submitted-to-relay, R-B refused and partial overall status |
| Documented all-recipient refusal | Record that refusal; no accepted-submission claim from the visible To list |
| Connection or final outcome evidence is lost | Keep affected submission unknown; reconcile before any separately authorized retry |
| Relay submission accepted without downstream evidence | Delivery, mailbox presence, reading and later forwarding remain unknown |
Keep the evidence claim at the boundary actually observed
A useful status names recipients separately: “R-A submitted to relay; R-B refused.” Preserve the attempted recipient set and supported refusal categories in protected records without copying raw message contents or credentials into ordinary logs. Do not repeat the accepted subset merely to recover a refused or unknown entry; any later attempt needs its own supported recovery and current authority decision.
Configured relay trust, authentication, TLS, mailbox validation and aliases or list expansion are unverified prerequisites or exclusions here. Neither explicit arguments nor matching visible From establishes universal sender authentication, confidentiality, consent or ultimate destination behavior. This guide supplies no Message-ID deduplication or exactly-once guarantee.
No Python email/smtplib import, message/header construction, serialization, SMTP connection, send, account access, API/model or runtime fixture occurred for these cases. Boundary is prelaunch and does not claim a shipped mail sender. Its synthetic demo checks concern separate policy, JSON-export and approval-status behavior.
Primary sources
Official references supporting the guidance. Examples in this guide are synthetic and are not reports of a production incident.