Moodle emails a lot: enrolment and password messages, forum posts, assignment notifications and daily digests. With no SMTP host configured it hands everything to PHP's mail(), which on most servers either goes nowhere or lands in spam. The fix is a built-in admin page — no plugin required.
| Setting | Value |
|---|---|
| SMTP host | smtp.postwing.app |
| Port | 587 |
| Encryption | STARTTLS (the connection is upgraded to TLS before login) |
| Username | The login of an SMTP token for your domain |
| Password | The password of that token — shown once, when the token is created |
Go to Site administration → Server → Email → Outgoing mail configuration:
| Setting | Value |
|---|---|
| SMTP hosts | smtp.postwing.app:587 |
| SMTP security | TLS |
| SMTP auth type | PLAIN |
| SMTP username | The login of an SMTP token for your domain |
| SMTP password | That token's password |
| SMTP session limit | Optional. Values above 1 reuse one connection for several messages |
| No-reply address | noreply@your-domain.com — on your verified domain |
| Allowed email domains | Leave empty, or list only your verified domain |
:587 it connects to port 25. Pair TLS with 587 or SSL with 465. Much of Moodle's mail is sent on behalf of a user — a forum post, a message from a teacher. Unless that user's domain is in Allowed email domains, Moodle writes the No-reply address into From and uses it as the envelope sender too. That address carries every message, so it must be on the domain you verified; otherwise DKIM and SPF do not align and the mail goes to spam. Do not add gmail.com or your students' domains to the allowed list.
Any admin setting can be forced from config.php, which is useful when several sites share a deployment:
<?php
// config.php — above the require_once of lib/setup.php.
// Settings forced here are locked in the admin UI.
$CFG->smtphosts = 'smtp.postwing.app:587';
$CFG->smtpsecure = 'tls'; // 'tls' = STARTTLS, 'ssl' = port 465
$CFG->smtpauthtype = 'PLAIN'; // the relay does not offer LOGIN
$CFG->smtpuser = 'token-login@your-domain.com';
$CFG->smtppass = 'your-token-password';
$CFG->noreplyaddress = 'noreply@your-domain.com'; Save the settings first, then follow the Test outgoing mail configuration link at the bottom of the page (or open /admin/testoutgoingmailconf.php). Enter an address and press Send a test message. For the full SMTP exchange, add $CFG->debugsmtp = true; to config.php while you test.
| Error | Cause and fix |
|---|---|
| Your site couldn't communicate with your mail server | Port missing from SMTP hosts, wrong security setting, or an outbound port block — try smtp.postwing.app:8587. |
SMTP Error: Could not authenticate | Wrong token login or password. |
| Test works, forum emails do not arrive | Cron is not running. Check Server → Tasks. |
| Settings cannot be edited | They are forced in config.php. |
| No email is sent at all | $CFG->noemailever is set in config.php — typical for a copied test site. |
| Mail goes to spam | No-reply address is not on your verified domain, or Allowed email domains lists other domains. |
Site administration → Server → Email → Outgoing mail configuration. Enter the server in SMTP hosts as host:port, then set SMTP security, SMTP auth type, SMTP username and SMTP password. If SMTP hosts is left blank, Moodle falls back to PHP's mail() function.
TLS with port 587 — in Moodle 'TLS' means the connection is upgraded with STARTTLS. SSL goes with port 465, where the connection is encrypted from the first byte. Mixing them up is the most common reason the test page reports that it cannot talk to the mail server.
Moodle sends many messages on behalf of users. When a sender's domain is not listed in Allowed email domains, Moodle puts the No-reply address in From and the user's name in the display name. Keep it that way: an address on someone else's domain cannot pass DKIM and SPF for your domain.
Save the outgoing mail settings, then follow the Test outgoing mail configuration link at the bottom of the same page, or open /admin/testoutgoingmailconf.php. Enter a To address and press Send a test message; Moodle reports whether the mail server accepted it.
Forum notifications and digests are sent by scheduled tasks, not when the post is saved. If cron is not running every minute, those emails pile up. Check Site administration → Server → Tasks for the last run time.
Add $CFG->debugsmtp = true; to config.php and send from the test page. Moodle prints the full SMTP exchange, which shows exactly where the connection, TLS or login fails. Remove it afterwards.