Nextcloud SMTP Settings: Step-by-Step JustEmails Setup
Share notifications and password resets failing silently? Here are the Nextcloud SMTP settings that pass SPF, DKIM, and DMARC.
Share notifications and password resets failing silently? Here are the Nextcloud SMTP settings that pass SPF, DKIM, and DMARC.
Someone shares a folder with an external client. Nextcloud says "Shared successfully." The client never gets the email. Nobody notices for eleven days — until the client asks, politely, whether the files are coming.
Then a user forgets their password, clicks reset, and nothing arrives there either. Now it's an outage.
I've watched this play out on three different self-hosted instances, same root cause every time: someone pasted a Gmail address and an app password into the Nextcloud SMTP settings back when the instance was new, it worked for a month, then it quietly stopped. No alert. No red banner. Nextcloud logs the failure and moves on with its day.
Here's the fix — real SMTP settings, on your own domain, with authentication that receivers actually trust.
By the end of this you'll have a Nextcloud instance where:
config.php (set via occ), so it survives container rebuildsnextcloud.log with an error you can actually readNextcloud's admin manual covers the first half — enter a host, enter a port, click Send email. Where it stops is the part that decides whether mail lands: From-address and DNS alignment. That's the gap we're closing.
occ invocation changes)One pre-flight check before you touch anything. From the machine running Nextcloud:
nc -zv smtp.justemails.app 587
If that hangs, your host is blocking outbound submission and nothing below this line will work until the port opens. Hetzner blocks outbound 25 on new cloud accounts by default, and a handful of providers extend the same block to 587 — file a ticket, ask them to unlock it, and in my experience it comes back the same day.
Do this first. I once spent most of an afternoon rewriting a config.php that turned out to be completely correct, because it never occurred to me to check whether the packets were leaving the box at all.
In your JustEmails dashboard, create nextcloud@yourdomain.com. Not admin@, not your personal address — a mailbox that exists for exactly this one job.
Why bother? Because that SMTP password is going to sit in config.php in plaintext, readable by the web server user. No secret store, no env-var indirection, no vault. I don't love it — but that's how Nextcloud has always handled mail credentials, and being annoyed about it doesn't make the file any less readable. When you rotate the credential (and you should, especially after anyone new gets shell on the box), you want the blast radius to be one machine's notification mail. Not your inbox.
Mailboxes are unlimited on the $49/year All-In plan, so a single-purpose one costs nothing extra.
Note down four things:
smtp.justemails.app587nextcloud@yourdomain.com — the full addressDomains → your domain → DNS Status in the JustEmails dashboard. SPF, DKIM, DMARC, and MTA-STS are auto-configured, but your registrar has to actually serve those records before a receiver can check them.
Three green checks:
Fuzzy on which does what? The email security glossary explains each without quoting RFCs at you.
Do this before configuring Nextcloud, not after. Every hour of DNS propagation you burn is an hour of test emails failing for reasons that have nothing to do with your SMTP config, and you'll spend it debugging the wrong layer. (Done exactly that. Twice. The second time I even remembered the first time, halfway through.)
Log in as admin → your avatar → Administration settings → Basic settings. Scroll past background jobs to Email server.
| Field | Value |
|---|---|
| Send mode | SMTP |
| Encryption | STARTTLS |
| From address | nextcloud @ yourdomain.com |
| Authentication method | Login |
| Authentication required | ✅ checked |
| Server address | smtp.justemails.app : 587 |
| Credentials | nextcloud@yourdomain.com / your mailbox password |
Two fields trip people up.
The From address is split into two boxes. Left is the local part, right is the domain. Together they produce nextcloud@yourdomain.com — the address DMARC evaluates. It has to be on a domain JustEmails knows about. If it isn't, SMTP auth succeeds, the relay accepts your connection, and then it rejects the message. Confusing failure mode.
Encryption: STARTTLS, not SSL/TLS. Port 587 opens in the clear and upgrades via the STARTTLS command; 465 negotiates TLS immediately and pairs with SSL/TLS. Mismatch them and you get a handshake timeout that reads like a network problem. If 25 vs 465 vs 587 vs 993 has never fully clicked, the ports breakdown is worth five minutes.
Save. Recent versions autosave per field, which is either convenient or unnerving depending on your mood.
The UI writes to config.php. You can write there directly, and on anything you rebuild from a Dockerfile you probably should.
sudo -u www-data php occ config:system:set mail_smtpmode --value="smtp"
sudo -u www-data php occ config:system:set mail_sendmailmode --value="smtp"
sudo -u www-data php occ config:system:set mail_smtphost --value="smtp.justemails.app"
sudo -u www-data php occ config:system:set mail_smtpport --value="587"
sudo -u www-data php occ config:system:set mail_smtpsecure --value="tls"
sudo -u www-data php occ config:system:set mail_smtpauth --value=1 --type=boolean
sudo -u www-data php occ config:system:set mail_smtpname --value="nextcloud@yourdomain.com"
sudo -u www-data php occ config:system:set mail_smtppassword --value="your-mailbox-password"
sudo -u www-data php occ config:system:set mail_from_address --value="nextcloud"
sudo -u www-data php occ config:system:set mail_domain --value="yourdomain.com"
Running in Docker? Prefix each one:
docker exec -u www-data nextcloud php occ config:system:set mail_smtphost --value="smtp.justemails.app"
Three things worth knowing about that block:
mail_smtpsecure takes tls for STARTTLS and ssl for implicit TLS on 465. The naming is backwards from how everyone says it out loud, and it's bitten enough admins to count as a rite of passage.
mail_smtpauth wants a real boolean — hence --type=boolean. Without the flag you get the string "1", which mostly works, right up until it doesn't. And mail_smtpauthtype used to matter; Nextcloud 26 swapped SwiftMailer for Symfony Mailer and it stopped doing much of anything, so leave it out on a current instance.
That password is now in your shell history, by the way. Clean it up, or set that one field in the web UI and leave the other nine to the CLI.
Check your work:
sudo -u www-data php occ config:list system
The password comes back as ***REMOVED SENSITIVE VALUE***, which is the correct behavior and not a sign anything went wrong.
Back in Basic settings, next to the email field on your own account, click Send email.
A green banner means the SMTP transaction succeeded. It does not mean the message will land anywhere good. Open the test email, view the original, find the authentication block:
Authentication-Results: mx.google.com;
spf=pass
dkim=pass header.i=@yourdomain.com
dmarc=pass header.from=yourdomain.com
Three passes, and header.from matching your domain — that's alignment. If dkim=pass but dmarc=fail, the signature is valid for one domain while the visible From says another, which almost always means mail_domain doesn't match the domain you set up in JustEmails.
SPF passes and DKIM fails? Wait. It's DNS. Cloudflare picks up a record in under a minute; some registrars take most of a business day.
Once alignment holds, the DMARC enforcement walkthrough covers moving the policy from monitoring to actual rejection.
Password resets and share notifications send in-request. Activity digests, calendar reminders, and file-expiry warnings don't — they queue for the background job runner.
On AJAX cron, those jobs only fire when someone loads a page. On an instance that's idle overnight, the morning digest goes out whenever the first person logs in. Or never, on a quiet weekend.
Strong opinion, and I'll defend it: AJAX cron should never have been the default. It turns a scheduling problem into something that looks like a mail problem, it hides the failure behind whoever happens to open a browser tab first, and it has cost me more debugging hours over the years than any actual SMTP misconfiguration ever has.
Switch to system cron:
sudo -u www-data php occ background:job:mode -- cron
sudo crontab -u www-data -e # */5 * * * * php -f /var/www/nextcloud/cron.php
Admin overview complains when the last run goes stale. Genuinely useful alarm — one of the few in there I haven't muted.
"A problem occurred while sending the email. Please revise your settings."
Nextcloud's catch-all banner. The actual exception is in the log:
tail -f /var/www/nextcloud/data/nextcloud.log | grep -i smtp
Everything below is something you'll find in there.
Connection could not be established with host smtp.justemails.app :stream_socket_client(): Connection refused
Outbound 587 is blocked. Back to the nc check — this is your provider, not your config.
Expected response code 250 but got code "535"
Auth failed. The username must be the complete address. Check for a trailing space too — clear the password field entirely and retype rather than editing in place.
SSL operation failed ... unable to get local issuer certificate
No CA bundle in the container. Common on slim Alpine images: apk add --no-cache ca-certificates, or apt-get install ca-certificates on Debian-based ones, then restart.
550 Sender address rejected
mail_domain isn't a domain on your JustEmails account. Watch for the classic typo where From reads nextcloud@yourdomain.com.com because the full address went in the left-hand box. I have done this. Twice, on the same instance, about a year apart — which probably says something unflattering about how much I learn from my own mistakes.
Mail sends fine, lands in spam
Almost always DNS. Send a test to mail-tester.com and read the deductions — below 7/10 means something specific is wrong, usually a DKIM record the registrar's UI split mid-value.
Standard advice for self-hosted Nextcloud is to self-host the mail server too. Postfix, Dovecot, a rented IP.
Bad trade for most instances — and I say that as someone who ran exactly that setup for two years. File sync is a problem you solve once. Deliverability is a problem you re-solve every time a blocklist changes its mind about your IP range, and a Nextcloud instance sends maybe forty messages a month, nowhere near the volume that earns a dedicated IP its reputation. All the maintenance, none of the payoff. The longer argument, including where self-hosting mail is genuinely right, is in self-hosted mail vs managed hosting.
Reasonable people disagree with me here. Some of them run better infrastructure than I do.
Your instance sends authenticated mail now. Three things worth doing while you're in there:
mail_from_address; the display name comes from your instance name under Theming. "Nextcloud" is fine. "Acme Files" is better.One caveat: mail handling changed in the Symfony Mailer migration, so guides written for Nextcloud 25 and earlier reference settings that no longer do anything. If you're on an older release and something above doesn't match your screen, that's usually why.
In Settings → Administration → Basic settings, set Send mode to SMTP, Encryption to STARTTLS, Server address to smtp.justemails.app, Port to 587, and turn on Authentication required with the Login method. The From address should be a mailbox on a domain you control — nextcloud@yourdomain.com — and the SMTP username is that same full address, not just the local part.
That banner is generic on purpose — the real error only shows up in nextcloud.log. Check data/nextcloud.log and look for the Symfony Mailer exception. The four usual causes: port 25 blocked outbound by your host, a 535 authentication failure from a wrong username, missing CA certificates in a slim container, or a 550 rejection because the From domain isn't on your SMTP account.
It works until it doesn't. App passwords break when you change your Google password or add a 2FA method, Google applies per-day sending limits to consumer accounts, and mail sent from your personal address can't pass DMARC alignment for your Nextcloud domain. For an instance that sends password resets, use a dedicated mailbox on your own domain instead.
Use occ config:system:set — one call per key: mail_smtpmode, mail_smtphost, mail_smtpport, mail_smtpsecure, mail_smtpauth, mail_smtpname, mail_smtppassword, mail_from_address, and mail_domain. Run them as the web server user (sudo -u www-data php occ ...) or inside the container with docker exec -u www-data. Verify with occ config:list system, which masks the password in its output.
Unlimited custom domain email hosting for $49/year flat — unlimited domains, unlimited mailboxes, 10 GB storage, full IMAP/SMTP. Built for agencies, freelancers, and anyone managing email across more than one domain.