2mail — SMTP relay from Belgian infrastructure

SMTP for Laravel — application mail that arrives

Laravel ships with a full mail layer, including queues, templates and notifications. What it does not provide is deliverability: that depends on the server you send through, and the default configuration on a fresh server rarely makes a good sender.

Laravel reads its mail settings from the environment configuration. You change the SMTP details there and the rest of your application stays untouched — no changes to mailables, notifications or queues needed.

Why it goes wrong without a relay

An application in development sends to a test address and everything looks fine. At go-live the audience changes: real addresses at real providers, which do check authentication and reputation. That is the moment password reset emails suddenly stop arriving — for a subset of users, which makes it hard to spot.

Setting up SMTP in Laravel

1

Collect your details

Log in to your 2mail account and retrieve your SMTP server, username and password there.

2

Fill them in inside Laravel

The mail settings live in your application's environment file, not in the code. You set the mailer to SMTP and fill in the five details below. Do not forget the sender address and sender name: those are separate settings alongside the connection details.

3

Authenticate your domain

Make sure SPF, DKIM and DMARC are set correctly for your domain, so recipients can verify that the mail comes from you.

4

Test

From your platform, send a test message to an address at a major provider and check that it arrives in the inbox and not in the spam folder.

The fields Laravel asks for

Every platform names them slightly differently, but it is always the same five. The actual values are tied to your account and can be found in your 2mail account — take them from there, so you are sure to use the right ones.

Field What you enter
SMTP server (host)The server name from your 2mail account.
PortThe port that matches your chosen encryption; your account shows which one.
EncryptionTLS. Never send unencrypted — your credentials would otherwise travel in plain text.
UsernameThe SMTP login of your 2mail account.
PasswordThe matching password. Never use the password of an employee's mailbox.

SMTP configuration for Laravel in code

Working examples for port 587 with STARTTLS, ready to copy. Replace the sender address with an address on your own domain and check the server name and login in your 2mail account. The password belongs in an environment variable — never in the code and never in version control.

The .env file: the MAIL_* variables

Laravel reads all connection details from .env. Port 587 works with STARTTLS: the connection starts in plain text and is upgraded to TLS before your login ever crosses the wire. The password lives only in the .env file on the server — that file does not belong in version control. Replace example.com with a domain you have authenticated in 2mail.

MAIL_MAILER=smtp
MAIL_HOST=relay.2mail.eu
MAIL_PORT=587
MAIL_USERNAME="<2mail-smtp-login>"
MAIL_PASSWORD="<2mail-smtp-password>"
MAIL_FROM_ADDRESS="noreply@example.com"
MAIL_FROM_NAME="${APP_NAME}"

# Only when config/mail.php still has an 'encryption' key (older projects):
MAIL_ENCRYPTION=tls

# When config/mail.php has a 'scheme' key instead: leave MAIL_SCHEME unset.
# "smtp" on port 587 upgrades to STARTTLS by itself; "tls" is not a valid scheme.

config/mail.php: the smtp mailer

In a standard project you do not need to change anything here: the file simply reads the variables from .env. Do check it when a setting seems to have no effect — a hardcoded host in this file always wins over your .env. Recent projects have a scheme key, older ones an encryption key; the rest is identical.

// config/mail.php
'default' => env('MAIL_MAILER', 'smtp'),

'mailers' => [
    'smtp' => [
        'transport' => 'smtp',
        'scheme' => env('MAIL_SCHEME'),                    // newer projects
        // 'encryption' => env('MAIL_ENCRYPTION', 'tls'),  // older projects use this key instead
        'host' => env('MAIL_HOST', 'relay.2mail.eu'),
        'port' => env('MAIL_PORT', 587),
        'username' => env('MAIL_USERNAME'),
        'password' => env('MAIL_PASSWORD'),
        'timeout' => null,
    ],
],

'from' => [
    'address' => env('MAIL_FROM_ADDRESS', 'noreply@example.com'),
    'name' => env('MAIL_FROM_NAME', 'Example'),
],

Sending a test email with Tinker

Clear the configuration cache first, otherwise you are still testing the old settings. Mail::raw sends synchronously: a mistake in host, port or login shows up in the terminal straight away, not later in the queue log. Send to an external address at a large provider.

php artisan config:clear
php artisan tinker

# At the tinker prompt:
Mail::raw('Sent through the 2mail SMTP relay.', fn ($m) => $m->to('you@example.org')->subject('SMTP test'));

Which emails Laravel sends

As soon as the relay is set up, all of these run through 2mail — you do not have to configure them one by one.

Password resets and email verification
Notifications and event mail from the application
Invoices and subscription messages
Reports from scheduled tasks
Error notifications to administrators

Pitfalls with Laravel

The queue has to be running

If you queue mail without an active worker, nothing leaves and you see no error at all. On a delivery problem this should be the first check, not the last.

Configuration cache after a change

If your application runs with a cached configuration, changed mail settings have no effect until that cache is refreshed. A setting that "does not work" often simply has not been re-read yet.

Test environments that really send

A staging environment with a copy of the production database can send to real customers unnoticed. Restrict the recipients there explicitly, or use a separate login.

Common error messages with Laravel

The messages you get when host, port, encryption or login are wrong — quoted literally, so you recognise them in your log, with the cause and the fix next to them.

Message Cause Fix
Connection could not be established with host "relay.2mail.eu:587": stream_socket_client(): Unable to connect to relay.2mail.eu:587 (Connection timed out) Your server cannot reach the relay. Usually your host's firewall blocks outbound traffic on port 587, or there is a typo in MAIL_HOST or MAIL_PORT. Test from the same server with openssl s_client -starttls smtp -connect relay.2mail.eu:587. If nothing answers, ask your host to open outbound traffic on port 587.
Connection could not be established with host "ssl://relay.2mail.eu:587": stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: error:…:SSL routines::wrong version number The scheme is set to smtps (or, in an older project, MAIL_ENCRYPTION=ssl). Laravel then expects TLS from the first byte, whereas port 587 starts in plain text and only upgrades afterwards through STARTTLS. Leave MAIL_SCHEME empty or set it to smtp; in an older project, set MAIL_ENCRYPTION=tls. The port stays 587.
Failed to authenticate on SMTP server with username "…" using the following authenticators: "LOGIN", "PLAIN". … Expected response code "235" but got code "535" The relay rejects the login: a wrong username or password, a password containing a space or # that is not quoted in .env, or a cached old configuration. Wrap the value in double quotes, run php artisan config:clear and use the SMTP login from your 2mail account — not the password of a mailbox.
The "tls" scheme is not supported; supported schemes for mailer "smtp" are: "smtp", "smtps". MAIL_SCHEME contains tls. That variable is not a successor to MAIL_ENCRYPTION: it only knows smtp and smtps. Remove MAIL_SCHEME or set it to smtp. On port 587 the mailer switches to STARTTLS by itself.
Expected response code "250/251/252" but got code "554", with message "554 5.7.1 <noreply@example.com>: Sender address rejected" The login is fine, but the sender address is on a domain that is not linked to your 2mail account. Often MAIL_FROM_ADDRESS still holds the default value from the example file. Set MAIL_FROM_ADDRESS to an address on a domain you have added in 2mail, and check that no Mailable sets its own from() on a different domain.
SPF, DKIM & DMARC explained About deliverability

A different platform?

SMTP is a standard protocol: any system that speaks SMTP — a CRM, an ERP, a custom application or a server — can send through 2mail using the same five fields.

Frequently asked questions about SMTP for Laravel

Laravel provides the mail layer, not deliverability: that depends on the server you send through. The default configuration on a fresh server rarely makes a good sender, because there is no authentication and no established reputation.
In your application's environment file, not in the code. You set the mailer to SMTP and fill in host, port, username, password and encryption. Do not forget the sender address and sender name — those are separate settings alongside.
If your application runs with a cached configuration, changed mail settings have no effect until that cache is refreshed. A setting that 'does not work' often simply has not been re-read yet.
Check that the queue is being processed. If you queue mail without an active worker, nothing leaves and no error appears either. This should be the first check, not the last.
A staging environment with a copy of the production database can send to real addresses unnoticed. Restrict the recipients there explicitly, or use a separate login so you can track that traffic separately.
Call us
Send an email