NetSendo
Platform Updates

NetSendo v2.11.0: Built-In MTA, Port 25 & PTR Checks

NetSendo Team7 min read

Running your own mail server comes with some well-known problems. Your hosting provider may block outbound port 25 without telling you. Your server's IP may have no reverse DNS (PTR) record. Your SPF record may not list the IP your mail actually leaves from. Any one of these can send your emails to spam, or leave them stuck in a queue.

NetSendo v2.11.0 deals with all of this. The NetSendo MTA now ships with every installation as a standard service. It also checks its own setup the way a receiving mail server would, and tells you exactly what to fix.

TL;DR: In v2.11.0, the NetSendo MTA (nmi-mta) is part of the default docker-compose.yml and uses a published image. It relays mail for GOLD installations. A new "Can this server send mail" panel checks outbound port 25, your PTR record and your SPF entry. The MTA now uses your server's PTR name in HELO, and the SPF checks look for ip4:/ip6: instead of an include: that never worked.

🚀 What's New in v2.11.0

The MTA Is Now a Standard Service

Before this release, the MTA container started only with docker compose --profile nmi. It was built on your server from files that install.sh never downloaded. The provider was also hidden unless NMI_ENABLED=true was set, and no installation had that setting. In practice, almost nobody could use it.

Now the MTA works like any other NetSendo service:

  • ✅ It's defined in docker-compose.yml and starts with everything else
  • ✅ It uses a published image, ghcr.io/netsendo/netsendo:mta-<version>, built by the same workflow as the app
  • ✅ Its configuration and plugins are inside the image, so nothing is mounted from your installation folder
  • ✅ It publishes no ports on the host, so several installations on one server no longer clash on 2525/2587

The NetSendo MTA provider appears in Settings → Mailboxes whenever the MTA responds. Without GOLD, the provider shows a GOLD badge. The MTA relays nothing until a GOLD installation saves a mailbox with this provider, because it only accepts sessions that log in with credentials NetSendo issued.

⚠️ Important: NMI_ENABLED is no longer read. .env files copied from older examples contain NMI_ENABLED=false even though nobody chose that value. To opt out, use NMI_DISABLED=true instead. This hides the provider and stops NMI's scheduled jobs.
# .env — optional NMI settings
NMI_DISABLED=true          # hide the provider and stop NMI scheduled jobs
NMI_MTA_HOST=nmi-mta       # service name the app uses to reach the MTA
NMI_HELO_HOST=mail.example.com  # override the HELO name (optional)
NMI_EGRESS_PROBE=false     # turn off the outbound check (optional)

The app reaches the MTA by its service name, nmi-mta. The old name, netsendo-mta, keeps working for as long as the container uses it.

"Can This Server Send Mail?"

This check appears in the NetSendo MTA section of the mailbox form and in Settings → Mail Infrastructure. The MTA runs it on startup and again every few hours. It tests from the outside, the way a receiving server sees you: it connects to a Gmail MX on port 25, sends nothing, and reads back the address the MX reports for you.

🔌

Outbound Port 25

Shows whether port 25 is open or blocked by your provider. If it's blocked, mail would stay in the queue, and the panel tells you what to do.

🔁

Public IP & PTR

Shows your public address, its PTR record, and whether the PTR name resolves back to the same address.

📋

SPF Entry

Gives you the exact ip4:… entry to add to your sending domain's SPF record, with a copy button.

HELO Uses Your Server's PTR Name

Mail sent without a dedicated IP used to introduce itself in HELO with the container's hostname, which no receiver can resolve. Now, if your public IP's PTR points to a hostname that resolves back to that IP, the MTA uses that hostname. Think of it as giving a real return address instead of a room number inside the building. NMI_HELO_HOST still overrides this if you need to.

Corrected SPF Checks

Deliverability checks used to ask for include:_spf.<installation host>, a record nobody publishes. They now look for your server's public IP, or the mailbox's dedicated IP, as an ip4:/ip6: entry, including ranges. You get a warning if it's missing, and the generated record adds it:

example.com.  TXT  "v=spf1 include:_spf.google.com ip4:203.0.113.10 ~all"

💼 Benefits & Use Cases

🛒

E-commerce: Reliable Transactional Mail

Abandoned cart reminders and order confirmations need to arrive on time. With port 25, PTR and SPF checked before you go live:

  • You learn about a blocked port before cart emails sit in a queue
  • Post-purchase sequences go out with matching PTR, HELO and SPF
  • No per-email fees from a third-party relay
🚀

SaaS: Onboarding That Reaches the Inbox

Onboarding and churn-prevention emails only work if users see them. The built-in MTA keeps the whole sending path on your own infrastructure, and the regular re-checks catch DNS or network changes before they affect deliverability.

🏢

Agencies: Several Installations on One Host

Because the MTA no longer publishes ports, you can run separate NetSendo installations for different clients on the same server without conflicts on 2525/2587. Each client keeps its own data and configuration.

🛠️ Step-by-Step Upgrade Guide

  1. Get the New Compose File

    Replace your docker-compose.yml with the v2.11.0 version. It adds the nmi-mta service and the nmi-* volumes.

  2. Clean Up .env

    Remove NMI_ENABLED. If you don't want the MTA at all, add NMI_DISABLED=true.

  3. Pull and Restart
    docker compose pull && docker compose up -d

    If you used to run the MTA with --profile nmi and --build, stop using both flags. The service now runs from the published image.

  4. Review the Sending Check

    Open Settings → Mail Infrastructure. You'll see the status of port 25, your public IP and PTR, and the SPF entry you need.

  5. Fix PTR and SPF

    Set the PTR in your hosting provider's panel, then copy the ip4: entry into your domain's existing SPF record. Don't create a second SPF record.

  6. Create a Mailbox (GOLD)

    In Settings → Mailboxes, choose NetSendo MTA and save. The MTA starts relaying once this mailbox exists.

ℹ️ Note: If you keep your old compose file, the installation still works. The mailbox form will simply report that the MTA isn't responding.

Common Pitfalls

  • Port 25 blocked: Many cloud providers block it by default. The new guide in docs/NMI.md covers Google Cloud, AWS, Azure, DigitalOcean, Hetzner, Vultr, Linode, OVHcloud and Contabo.
  • Two SPF records: A domain can have only one. Add the ip4: entry to the record you already have.
  • PTR without forward DNS: The PTR hostname must also have an A/AAAA record that points back to the same IP.

🎯 Expert Tips

1
Check Forward-Confirmed rDNS Yourself

Run dig -x 203.0.113.10 +short, then dig A on the hostname it returns. Both should match, which is what the panel checks.

2
Keep SPF Lean

ip4: entries don't count toward SPF's 10-DNS-lookup limit, so they're a good way to authorize your server.

3
Leave the Egress Probe On

The probe re-runs every few hours and catches changes such as a new IP or a provider policy change. Only set NMI_EGRESS_PROBE=false if outbound checks aren't allowed on your network.

4
Smaller Attack Surface

With no published host ports and authentication limited to credentials NetSendo issues, the MTA can't be used as an open relay. Keep it that way: don't add port mappings to the service.

🎉 Conclusion

NetSendo v2.11.0 makes self-hosted sending much easier to set up. The MTA ships with every installation, runs from a tested image, and tells you whether your server can actually deliver mail. Correct SPF guidance and PTR-based HELO give your emails a better chance of reaching the inbox, all on infrastructure you own.

Ready to Send From Your Own Server?

Upgrade to v2.11.0 and run the new sending check today:

Explore more integrations and ⭐ star us on GitHub.

#mta#deliverability#spf#reverse-dns#self-hosted#docker#release
Share