Docs / Mautic

Send email from Mautic over SMTP

Mautic is marketing automation, so what it sends is mostly bulk mail: segment emails, campaign steps, newsletters. Since version 5 it sends through Symfony Mailer, and an SMTP relay is configured as a DSN on one settings screen. Below is the setup for Postwing, plus the three things bulk mail needs beyond a working connection — unsubscribes, bounces and pacing.

✓
You can get them on the token management page. For security reasons, a token is shown only once — at the moment it is created.

SMTP connection settings

SettingValue
SMTP hostsmtp.postwing.app
Port587
EncryptionSTARTTLS (the connection is upgraded to TLS before login)
UsernameThe login of an SMTP token for your domain
PasswordThe password of that token — shown once, when the token is created
ℹ
Every mode is also available on a high port: 8465 (SSL/TLS), 8587 (STARTTLS) and 8025 (plain). Many hosting providers and clouds block outbound 25, 465 and 587 — if the connection times out, switch to the matching high port.

Configure Mautic

Open Settings (the cog, top right) → Configuration → Email Settings. Under Mail Send Settings:

FieldValue
Name to send mail asYour brand or team name
E-mail address to send mail fromnews@your-domain.com — on your verified domain
Reply to addressA mailbox someone reads, if the sender is not one
Custom return path (bounce) addressLeave empty — see Bounces below

Under Email DSN:

FieldValue
Schemesmtp
Hostsmtp.postwing.app
Port587
UserThe login of an SMTP token for your domain
PasswordThat token's password
Path, OptionsLeave empty

Save, then use Send test email — it goes to your own user's address. The form URL-encodes the login for you; if you edit the file instead, encode the @ yourself:

config/local.php
<?php
// config/local.php — the @ in the login must be written as %40
$parameters = array(
    // ...
    'mailer_from_name'  => 'Acme',
    'mailer_from_email' => 'news@your-domain.com',
    'mailer_dsn'        => 'smtp://token-login%40your-domain.com:your-token-password@smtp.postwing.app:587',
);

Unsubscribes

Mautic adds List-Unsubscribe and the one-click List-Unsubscribe-Post to marketing emails on its own. When we classify a message as bulk, the relay puts our one-click pair in their place, so the unsubscribe is recorded in the domain's unsubscribe list rather than in Mautic. Later mail to that address is dropped rather than delivered, and Mautic's contact stays subscribed until you sync it — the unsubscribed webhook is the event to act on. The {unsubscribe_text} link in the body still goes to Mautic.

Bounces

With a monitored inbox set up under Monitored Inbox Settings, Mautic puts a tagged bounce address (…+bounce_…@) in the envelope, and mautic:email:fetch reads the bounces that come back.

⚠
The relay accepts only an envelope sender on your domain, so a monitored inbox on Gmail makes every send fail with 550 from must be equal to …. Also leave the domain's return path in the dashboard empty — it replaces the envelope Mautic chose, and the tag Mautic matches bounces by is lost.

A rejection our servers receive during delivery is not sent back as a bounce message: it is in the domain's log and in the bounced webhook. Hard bounces are not suppressed for you, so mark those contacts Do Not Contact in Mautic, or the next campaign mails them again and your bounce rate climbs.

Pacing campaigns

Segment emails are sent by cron, which is where you control speed. Keep one hour of runs under your plan's hourly limit — above it the relay refuses with 550 hourly limit exceeded. A new domain's warm-up never refuses; it delivers over-cap mail later. Both are described in sending limits.

crontab
# Send segment emails, at most 500 contacts per run
*/15 * * * * php /var/www/mautic/bin/console mautic:broadcasts:send --limit=500

# Read the monitored inbox for bounces and unsubscribe requests
*/10 * * * * php /var/www/mautic/bin/console mautic:email:fetch

Troubleshooting

ErrorCause and fix
Connection could not be established Outbound port blocked — set Port to 8587, or 8465 for implicit TLS.
Failed to authenticate on SMTP server Wrong token credentials, or an unencoded @ in a hand-edited mailer_dsn.
550 from must be equal to … The sender or the monitored inbox address is not on your verified domain.
550 hourly limit exceededLower --limit or run the cron less often.
Test email works, campaign sends nothing The mautic:broadcasts:send cron is not running, or the queue is enabled with no messenger:consume email worker.
Mail goes to spam The From address is not on your verified domain, or the list has not been cleaned of bounces.

Frequently asked questions

Where are Mautic's SMTP settings?

Settings (the cog, top right) → Configuration → Email Settings. Since Mautic 5 the connection is an Email DSN with Scheme, Host, Port, User, Password and Options fields, which Mautic assembles into smtp://user:pass@host:port.

Do I need to choose TLS or SSL separately?

No. The encryption follows the port: with the smtp scheme, port 587 upgrades the connection with STARTTLS and port 465 is encrypted from the first byte. Use 587 unless your host blocks it.

Why does the Send test email button do nothing?

The DSN is tested only after it is saved — Mautic tells you to save changes to test the DSN. Save the configuration first, then send the test.

Does Mautic add a List-Unsubscribe header?

Yes, on marketing emails: Mautic adds List-Unsubscribe and List-Unsubscribe-Post itself. Transactional emails get none. Messages we classify as bulk carry our own one-click pair instead, and an unsubscribe through it is recorded on our side — see below.

How does Mautic learn about bounces?

Through the monitored inbox. Mautic puts its bounce address in the envelope, and the recipient's server sends the bounce there; mautic:email:fetch reads it and marks the contact Do Not Contact. Rejections our servers receive during delivery are not sent back as bounce messages — they are in the domain's log and the bounced webhook.

How do I keep a campaign inside my plan's limits?

Pace mautic:broadcasts:send with --limit and a cron interval, so an hour's worth of runs stays under your hourly limit. Above it the relay refuses the message with 550 hourly limit exceeded, and that send fails rather than waiting.

Next steps