Emails
Send a notification email every time a shipment changes to a given status. The plugin ships no default emails; you build each one.
Audience: store admins setting up customer and internal notifications.
Where to configure#
Shipments -> Settings -> Emails. Admin-only by default (grant shipments-manageEmails to give others access).
Per email, you configure:
- Basic fields: name, subject, recipient type, To / BCC / CC / Reply-To, HTML template path, optional plain-text template path, language, enabled toggle.
- Transition triggers: which status changes send this email.
The template path field autocompletes against your site templates.
Recipients#
- Customer, sends to the order’s customer email. Renders in the order’s language (or the site default).
- Custom, sends to whatever addresses you put in To. The field is Twig-rendered, so you can do dynamic addressing:
Separate multiple addresses with commas, semicolons, or whitespace.{% if shipment.carrier == 'UPS' %}[email protected]{% else %}[email protected]{% endif %}
Templates#
Templates render with shipment and order available, plus the to/from codes, the user who made the change, and any note the admin left. Authoring or customizing templates is developer work; see the email templates dev guide for the full variable list and a starter template.
Transition triggers#
This controls “when does this send.” Scroll to the bottom of the email edit page: a checkbox per status. Check one or more. The email sends when a shipment changes into any checked status.
Uncheck and save to remove a trigger. Multiple emails can share a trigger; every match queues on every change.
You have to save the email before you can check triggers. The UI shows a “Save the email first” note when you’re creating a new email.
How the send works#
- An admin (or webhook, or API) changes a shipment’s status.
- The plugin writes the new status and a history row in a single save.
- For every enabled email whose triggers match the new status, the plugin queues a send job.
- The queue push happens in the same save, so an email can’t queue if the status change rolls back. No orphan emails, no lost sends.
- The queued job runs in the background, renders the template, and sends through Craft’s mailer.
Disabled emails#
Flipping Enabled off stops all future sends. Jobs already in the queue still run. It’s all-or-nothing per email. Clone the email if you want one version live and another paused.
Language#
The email renders in the order’s language by default, or in a specific site language if you set the email’s language field. The plugin switches the active language before rendering, the same way Commerce does for its own emails.
Common patterns#
Customer-facing milestone:
- “Your order has shipped”, bound to
shipped.
Internal alerts:
- “Shipment on hold”, custom recipient
[email protected], bound toon_hold. - “Shipment cancelled”, custom recipient
[email protected], bound tocancelled.
A “please ship this” email for 3PLs:
- Custom recipient for the 3PL dispatch inbox, bound to
in_progress.
Testing#
There’s no “test email” button yet. To check an email:
- Create a test order and stage a shipment.
- Change the shipment to the status you’ve bound the email to.
- Check Craft’s queue (Utilities -> Queue Manager) for the send job.
- Check the recipient inbox (or
settings.toAddressin dev to catch all local mail).
What breaks if…#
- You delete an email. All its transition bindings delete with it. Future matching changes no longer fire it. History and already-sent emails are unaffected.
- You point the HTML template at a path that doesn’t exist. The next send fails, logs the error, and the queue marks the job failed per its retry policy. Fix the path; jobs don’t retry on their own after the queue gave up, so requeue them.
- A Custom recipient doesn’t render to a valid address. That portion of the send is skipped; the rest proceeds. Failures are logged.