Markdown

Craft CMS email with Groundmail

Send Craft CMS email through Groundmail with the official plugin for Craft 5. Account activation, password resets, Craft Commerce order email, form notifications and anything else your site sends with Craft's mailer go out from your own domain, over the API.

Updated Nov 15, 20263 min read


Prerequisites

  • A Groundmail account with a verified sending domain.
  • An API key (gm_…): in the dashboard, open API keys and create one. A send-only key is enough.
  • Craft CMS 5 with PHP 8.2 or later, and shell access to run Composer.

Craft's email goes out as transactional email by default, so use it for account, order and notification email. Never send cold email.


Install the plugin

In your Craft project, add the plugin's repository, install it with Composer, then install it in Craft:

Terminal
composer config repositories.groundmail-craft vcs https://github.com/Groundmail/groundmail-craft
composer require groundmail/craft-plugin
php craft plugin/install groundmail

Connect Craft

  1. Add your API key to the project's .env file:

    Terminal
    GROUNDMAIL_API_KEY=gm_your_key
  2. In the control panel, go to Settings, then Email.

  3. Set System Email Address to an address on your verified domain, for example noreply@yourdomain.com, and set Sender Name.

  4. Change Transport Type to Groundmail.

  5. Set API Key to $GROUNDMAIL_API_KEY. Craft reads the key from the environment, so it stays out of your project config.

  6. Leave Email category on Transactional unless the site only sends email about your product (see Email category).

  7. Click Save.

If allowAdminChanges is off in production, make the change in development and deploy the project config as usual. The key itself lives in each environment's .env.


Test it

Groundmail's simulator addresses never reach a real inbox. Send Craft's test email to one:

Terminal
php craft mailer/test --to=delivered@simulator.groundmail.dev

Or click Test on the Email settings page, which sends to your own address. The email shows up under Emails in the Groundmail dashboard. Sent to the simulator it has the status delivered and "test": true; use bounce@simulator.groundmail.dev to see a hard bounce. See Testing.


Email category

Groundmail sends transactional, product and newsletter email from separate IPs. Email category sets the stream for the email Craft sends:

  • Transactional (default): account email, password resets, order and form notifications.
  • Product: email about your product to its users, such as onboarding tips. Recipients can opt out of product email and keep getting transactional email.

A single message can set its own category with an X-Groundmail-Category header, and add tags with X-Groundmail-Tag: name=value:

PHP
Craft::$app->getMailer()->compose()
    ->setTo($user->email)
    ->setSubject('Your order has shipped')
    ->setHtmlBody($html)
    ->addHeader('X-Groundmail-Tag', 'order=' . $order->number)
    ->send();

X-Groundmail-Category: newsletter sends an opt-in newsletter, once your account is approved for newsletters (email support@groundmail.dev). Until then those sends are refused with a 403 and nothing is sent.


Craft Commerce

Commerce sends order emails through Craft's mailer, so once Groundmail is the transport they go out through it too. Each Commerce email has its own Status Email Address (under Commerce, then System Settings, then Emails). Leave it empty to send from the system email address, or set it to an address on your verified domain.

To know whether an order email was delivered or bounced, create a webhook for email.delivered, email.bounced and email.complained, or check Emails in the dashboard.


Troubleshooting

"Groundmail API keys start with gm_". The API Key setting, or the environment variable it names, holds something else, such as an SMTP credential (gmsmtp_…). Create an API key under API keys.

The email is refused because of the From address. The system email address, and the Status Email Address of any Commerce email, must be on a verified domain.

A recipient never receives the email. The address may be on your suppression list after a hard bounce or complaint. Sends to it return 422. See Suppressions.

Sends are deferred. New accounts have a daily ramp-up limit. See Sending limits.


Was this page helpful?