Skip to content

Send one message to a list of people

Create an audience, send a broadcast, check delivery, and manage unsubscribes.

To send the same marketing message to a list of people, add contacts to an audience, then create and queue a broadcast for that audience. Mail attempts to create a separate email for each eligible contact.

You need a verified sending domain for the from address. To personalize the message for each contact, you also need a published template. All audiences, contacts, and broadcasts belong to one product.

Use the MCP tools linked below or the REST API. Audiences, contacts, and broadcasts have no workspace screens. The suppression list is available at Mail → Suppressions.

Check your unsubscribe handling before sending: a broadcast unsubscribe suppresses the address across the product, including receipts and password resets. Handle unsubscribes explains the effect and how to resume sending when a recipient asks to return. For individual messages triggered by a user’s action, see how system email works.

Put people in an audience

  1. Create an audience with mail_audience_create. Give it a name of 1–200 characters, such as “Product updates.” An audience stores only its name; contact details belong on its contacts.
  2. Add contacts with mail_contact_create. Each needs an email address and the audience to join. Add properties if your template needs them.
  3. Check the list with mail_contact_list. It returns one audience’s contacts, 50 per page by default. You can request 1–100, follow the cursor to the next page, and filter for subscribed or unsubscribed contacts. Confirm the intended recipients are subscribed before you queue a broadcast.

Each contact has these fields:

Field
What it holds
email
The address, with surrounding whitespace removed and letters lowercased
properties
Your JSON key/value pairs, such as first_name or plan
unsubscribed
Whether the contact has opted out
audienceId
The audience the contact belongs to

Mail supplies first_name and last_name to templates. Other property names are yours to choose, and their JSON values are stored with the contact.

Use mail_contact_get to read a contact and mail_contact_update to change its properties or unsubscribed flag. An update replaces the whole properties object. Include every property you want to keep. Remove a contact with mail_contact_delete.

A contact belongs to exactly one audience. The same address can appear once in each of several audiences: for example, “Product updates” and “Beta testers” can each have a separate contact with its own properties and opt-out flag. To move a contact, create it in the destination audience and delete the original.

To manage the audience itself, use mail_audience_get, mail_audience_list, or mail_audience_update. Deleting an audience with mail_audience_delete also deletes its contacts.

Send a broadcast

  1. Prepare the content. Choose either inline content—a subject and HTML, plain text, or both—or a published template with its variables. You cannot mix the two forms. See send from a template.
  2. Create a draft with mail_broadcast_create. Supply the content, a name, the audience, and a from address on a verified sending domain. You can also supply reply-to addresses and custom headers. Creating the draft sends nothing.
  3. Review the draft. Read it with mail_broadcast_get. Use mail_broadcast_update to edit it or mail_broadcast_delete to remove it. Both actions are available only while its status is draft.
  4. Queue the broadcast with mail_broadcast_queue. This starts creating emails for the audience. You can no longer edit or delete the broadcast, and canceling it cannot recall emails already created.
  5. Check progress with mail_broadcast_get. The status is queued while Mail processes the audience and sent when it has handed on the last message. Use mail_broadcast_list to find other broadcasts. Check delivery separately in the broadcast statistics.

What queuing does

Before queueing, Mail checks the plan allowance once for the eligible audience. A refusal returns HTTP 402 with entitlement_exhausted or entitlement_unavailable, leaves the broadcast in draft, and sends nothing. Read the returned reason and resolve that condition before queueing again. A successful check covers this broadcast’s audience processing; the allowance is not checked again for each contact.

Mail processes the audience in pages and creates one email per eligible contact:

  • Contacts with unsubscribed set are excluded.
  • Addresses on the product’s suppression list are counted as skipped, and no email is created for them.

Each created email follows the normal send process, with its own status, events, and unsubscribe headers. A broadcast’s sent status means audience processing has finished; delivery outcomes can still arrive afterward.

For template content, Mail combines the broadcast’s variables with these per-contact values:

Variable
Value
FIRST_NAME
The contact’s first_name property, or empty
LAST_NAME
The contact’s last_name property, or empty
EMAIL
The contact’s email address
UNSUBSCRIBE_URL
The contact’s unsubscribe link

Use UNSUBSCRIBE_URL for a visible unsubscribe link in the email body. The email also carries headers that let the mail client offer its own unsubscribe action.

Cancel one

Call mail_broadcast_cancel while the broadcast is draft or queued. Canceling a draft prevents it from sending. Canceling a queued broadcast stops audience processing between pages; emails already created continue through the send process and cannot be recalled.

You cannot cancel a broadcast that is already sent, failed, or canceled. If audience processing fails, the broadcast has status failed and retains the reason for the failure.

Read what happened

Call mail_broadcast_stats for the broadcast’s counts:

Field
Meaning
recipients
Contacts whose message was accepted, created, and queued
suppressed
Contacts skipped because their address was suppressed
failed
Contacts whose message could not be created or accepted into the queue; excludes later delivery failures
delivered
Messages accepted by receiving servers
bounced
Messages rejected by receiving servers
opened, clicked
Messages opened at least once; messages with at least one tracked click, when enabled for the sending domain

recipients, suppressed, and failed are separate sets. Their sum is the number of contacts processed by Mail. This can differ from recipientCount, which counts the eligible audience when you queue: contacts can change between queueing and processing. Delivery, bounce, open, and click counts can continue to rise after the broadcast reaches sent.

To collect opens and clicks, enable the corresponding tracking settings on the sending domain. For individual message events, use delivery webhooks.

Handle unsubscribes

Every broadcast email includes List-Unsubscribe with a signed, per-contact link and List-Unsubscribe-Post to support a mail client’s one-click unsubscribe action. The signature prevents someone from changing the link to target a different contact. The link does not expire.

Opening it in a browser displays a confirmation button and does not unsubscribe anyone. This prevents mailbox scanners from opting people out when they inspect links. The opt-out occurs when the recipient presses the button or the mail client submits the unsubscribe action. Reusing the link has no additional effect.

An unsubscribe makes both of these changes:

  1. It sets the contact’s unsubscribed flag, excluding that contact from later broadcasts to the audience.
  2. It adds the email address to the product’s suppression list with reason unsubscribe. This blocks mail to the address across all audiences and transactional email, including receipts and password resets.

If the recipient asks to subscribe again:

  1. Remove the address from Mail → Suppressions or call mail_suppression_remove.
  2. Clear the contact’s unsubscribed flag with mail_contact_update.
  3. Read the contact back and check mail_suppression_list. Confirm the contact is subscribed and the address is no longer suppressed. Both changes are needed before the contact can receive broadcasts again.

Next steps

Was this page helpful?
Esc

Start typing to search the docs.

↑↓navigate↵select