The recommended authentication choice is a managed TLS client certificate. A static public IP connector is also documented for environments without certificate automation. Neither path requires a Microsoft 365 mailbox password on the relay.
- Approved applications and devicesPrivate network SMTP submission
- Ubuntu or RHEL running PostfixSource controls, TLS and durable queue
- Microsoft 365 inbound connectorCertificate or public IP identification
- Exchange Online transportInternal mailboxes and external recipients
Scope and use
Baseline: Ubuntu Server 24.04 LTS and RHEL 9 with distribution Postfix packages. Commands assume Bash and sudo access. Other releases require package, TLS and service checks before use. This is an implementation runbook, not a record of a deployment performed in your environment.
1Reading map and design choice
| Section | Purpose |
|---|---|
| 2 to 4 | Prepare identities, network rules and Microsoft 365 |
| 5 to 7 | Install Ubuntu or RHEL and apply common Postfix configuration |
| 8 to 10 | Configure certificates, application TLS and sender controls |
| 11 to 13 | Test delivery, understand the process and troubleshoot |
| 14 to 17 | Operate, recover, consider alternatives and approve production |
| 18 | Official references and screenshot attribution |
Choose the delivery method
| Method | Endpoint and identity | Use |
|---|---|---|
| Connector relay | Tenant MX endpoint, TCP 25; certificate or exclusive static public IP | Internal and external mail from your on-premises relay |
| SMTP AUTH | smtp.office365.com, normally TCP 587; OAuth and mailbox | Alternative when connector requirements cannot be met |
| Direct Send | Tenant MX endpoint, TCP 25; anonymous | Internal recipients only; does not prove external relay works |
For this design, prefer certificate identity where renewal and key protection are operationally supported. Otherwise use an exclusive static public egress IP, with a specific NAT rule and a firewall that prevents other machines using that identity to send SMTP. Microsoft describes this device-relay path as an on-premises scenario; do not assume a third-party hosted VM is eligible. [1]
What this server is responsible for
Postfix accepts messages only from approved clients, stores accepted messages on disk, retries temporary failures, and logs the upstream response. Microsoft 365 acceptance is a separate event from recipient delivery. Monitor both the local queue and Exchange Online message trace.
There is no inbound Internet mail service in this design. Keep public inbound TCP 25 closed. Existing hybrid connectors and transport rules must be reviewed by the messaging owner before adding an overlapping connector.
2Preparation worksheet
| Item | Example | Your deployment |
|---|---|---|
| Relay hostname | relay01.contoso.com | ________________ |
| Private relay IP | 10.20.30.10 | ________________ |
| Approved clients | 10.20.30.21/32 and .22/32 | ________________ |
| Public NAT address | 203.0.113.10 | ________________ |
| Accepted sender domain | contoso.com | ________________ |
| Envelope sender | alerts@contoso.com | ________________ |
| Microsoft tenant MX | Copy actual tenant value | ________________ |
| Connector identity | Certificate or static IP | ________________ |
| Alert mailbox and owner | Monitored mailbox and team | ________________ |
203.0.113.10 is a documentation-only address. The other names and addresses are examples, not values discovered from your environment. Use exact host addresses in the client allowlist; a whole subnet grants every machine in it relay privileges.
Before installing
Record the OS release, Postfix version, DNS resolver, time synchronization, NAT ownership, approved sender identities and expected message volume. Allocate persistent disk for /var/spool/postfix. Decide who handles queue growth, patching, connector changes and certificate expiration.
cat /etc/os-release
hostname -f
timedatectl status
df -h /var/spool
ip -4 address
ip route
Use a dedicated relay with no hosted local mailboxes. Inventory anything already listening on port 25 and any existing Postfix maps, transport overrides, virtual domains or content filters. Do not overwrite a working mail server with this baseline.
sudo ss -lntp 'sport = :25'
# If Postfix is already installed:
sudo postconf -n
sudo postconf -M
3Network and DNS preparation
| Source | Destination | Allow |
|---|---|---|
| Approved client IPs | 10.20.30.10 | TCP 25; STARTTLS preferred |
| Relay | Tenant Microsoft MX endpoint | TCP 25 with STARTTLS |
| Relay | Approved DNS and time services | DNS and NTP per local policy |
| Administration network | Relay | SSH and monitoring as approved |
| Internet and other clients | Relay TCP 25 | Deny |
For IP identity, confirm the actual outbound source address using firewall NAT logs. The connector must match what Microsoft sees after NAT. Ensure redundant firewalls do not silently change that source. Do not pin Microsoft destination IPs permanently; maintain the current endpoint policy through your network team.
Find the Microsoft endpoint
In Microsoft 365 admin center, open Settings, Domains, choose the sender domain, then DNS records. Copy the Exchange MX target. If public MX points to another security gateway, use the Microsoft-provided tenant target, not that gateway. Do not change production MX just to build this outbound relay. [1]
Screenshot in the PDF edition Official Microsoft MX record screenshot. Use your tenant target; the pictured value is an example. Source [1].
Inspect DNS and connectivity
dig +short MX contoso.com
dig +short A contoso-com.mail.protection.outlook.com
nc -vz contoso-com.mail.protection.outlook.com 25
These commands use example names. A successful TCP connection proves reachability only. Certificate validation, connector identity and recipient acceptance still require the tests in section 11.
4Create the Microsoft 365 connector
Open Exchange admin center, Mail flow, Connectors, then Add a connector. Choose your organization email server as the source and Office 365 as the destination. Name it Postfix OnPrem Relay. Enable it and leave internal Exchange header retention off. Review existing hybrid connectors first. [1, 7]
Screenshot in the PDF edition Official Microsoft connector direction screenshot. This guide requires only the direction into Microsoft 365. Source [1].
Choose exactly one identity path
Certificate: choose certificate identification and enter the accepted domain present in the certificate Subject or SAN. This guide uses contoso.com for both. Install the corresponding private key and full certificate chain on Postfix using section 8.
IP: choose IP identification and enter the exclusive static public NAT address. A private address is not the outbound Internet identity. Review and create the connector. [1]
The connector recognizes the relay; it does not validate each application operator. The Postfix client allowlist is therefore a separate security boundary. Use a narrowly scoped operational identity and retain an inventory of every permitted application.
Screenshot in the PDF edition Official Microsoft certificate identity screen. The certificate domain and accepted domain must align. Source [1].
Screenshot in the PDF edition Official Microsoft public IP identity screen. Enter the actual post-NAT address. Source [1].
For tenant attribution, the certificate domain or SMTP envelope sender domain must be accepted, and the IP or certificate must match the OnPremises connector. The visible From header alone is insufficient. Null-envelope bounces need particular attention with IP-only identity; certificate domain attribution addresses this case. [2]
5Install Postfix on Ubuntu
Use Ubuntu Server 24.04 LTS for the baseline. Keep inbound SMTP blocked during setup. Install packages from configured Ubuntu repositories. The package installation can start Postfix, so network isolation must already be in place. [4]
sudo apt update
sudo apt install postfix ca-certificates openssl \
dnsutils netcat-openbsd swaks
sudo systemctl stop postfix
If the installer asks for a configuration type, choose Satellite system. Set the system mail name to your accepted domain and the relay host to the bracketed Microsoft tenant MX on port 25. The explicit configuration in section 7 remains authoritative.
Save the initial state
sudo cp -a /etc/postfix /etc/postfix.pre-m365
sudo postconf -n | sudo tee /root/postfix-pre-m365.txt
postconf mail_version
sudo update-ca-certificates
If /etc/postfix.pre-m365 already exists, use a new backup name; do not overwrite the previous recovery copy. Record package versions and any installer choices in the change ticket.
Ubuntu certificate trust setting
sudo postconf -e \
'smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt'
Apply the shared configuration in section 7, then the inbound TLS settings in section 9. Ubuntu may run Postfix services in a chroot. Verify DNS and CA-file access from the actual service context if the command-line TLS test succeeds but mail delivery fails. Do not disable the chroot as a first fix. [4]
Ubuntu logging
sudo journalctl --since "15 minutes ago" | grep postfix
# If rsyslog mail logging is configured:
sudo tail -n 100 /var/log/mail.log
A missing mail.log is not proof of a stopped service. Confirm which journal or syslog route your image uses, then configure log retention and forwarding before production.
6Install Postfix on RHEL
Use RHEL 9 for the baseline, with subscription and approved repositories configured. Keep SELinux enforcing and SMTP restricted during installation. These steps install a network relay; the loopback-only null-client pattern is shown separately in section 15. [5]
sudo dnf install postfix ca-certificates openssl \
bind-utils nmap-ncat
sudo systemctl stop postfix
sudo cp -a /etc/postfix /etc/postfix.pre-m365
sudo postconf -n | sudo tee /root/postfix-pre-m365.txt
sudo update-ca-trust
postconf mail_version
getenforce
Use a unique backup path if that directory already exists. swaks is optional and may require an additional approved repository; the portable sendmail test in section 11 does not depend on it.
RHEL certificate trust setting
sudo postconf -e \
'smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt'
Check security contexts and service state
sudo restorecon -Rv /etc/postfix
sudo postfix check
sudo journalctl --since "15 minutes ago" | grep postfix
# If rsyslog mail logging is configured:
sudo tail -n 100 /var/log/maillog
# Investigate SELinux denials if audit tooling is installed:
sudo ausearch -m AVC -ts recent
Correct certificate file paths, ownership and SELinux contexts when access fails. Do not set SELinux permissive or enable broad booleans to mask an unexplained denial. Preserve the system crypto policy; resolve incompatible keys or certificates instead of lowering the host security level.
Complete section 7 before starting the service. Apply the source-specific firewall example in section 9 to the interface active zone, and inspect for broad SMTP allowances already present.
7Shared Postfix relay configuration
On either distribution, edit /etc/postfix/main.cf with sudoedit. Merge these settings into the file so each parameter has one intended value. Preserve distribution service settings and the OS-specific CA path from section 5 or 6. Replace every example address and hostname before starting.
myhostname = relay01.contoso.com
mydomain = contoso.com
myorigin = $mydomain
inet_interfaces = 127.0.0.1, 10.20.30.10
inet_protocols = ipv4
mydestination =
relay_domains =
local_transport = error:local delivery disabled
mynetworks = 127.0.0.0/8, 10.20.30.21/32, 10.20.30.22/32
smtpd_relay_restrictions = permit_mynetworks, reject
smtpd_recipient_restrictions = reject_non_fqdn_recipient
relayhost = [contoso-com.mail.protection.outlook.com]:25
smtp_sasl_auth_enable = no
smtpd_sasl_auth_enable = no
smtp_tls_security_level = secure
smtp_tls_secure_cert_match = nexthop
smtp_tls_mandatory_protocols = >=TLSv1.2
smtp_tls_loglevel = 1
disable_vrfy_command = yes
message_size_limit = 26214400
The relay restriction permits the listed networks and rejects everyone else, including attempts addressed to your accepted domain. An empty mydestination avoids accidental local delivery. The bracketed relayhost selects a fixed next-hop hostname instead of performing MX routing for it. [6]
The 25 MiB message limit is a local example, not a Microsoft service limit; MIME encoding enlarges attachments. Set a size appropriate for the application and recipient path. IPv4-only operation makes the public-IP identity predictable; add IPv6 only with equivalent controls and verified routing.
secure requires encryption and valid server identity. encrypt alone does not verify the peer name or trust chain. Keep the exact Microsoft host name and validate its certificate before use. The >=TLSv1.2 syntax requires a sufficiently recent Postfix; the baseline packages should be checked with postconf mail_version. [3]
sudo postfix check
sudo postconf -n
sudo postconf -M
8Configure certificate identity
Skip the outbound client-certificate settings if using IP identity. For certificate identity, obtain a publicly trusted certificate whose Subject or SAN includes the exact accepted domain configured on the connector. Use contoso.com consistently in this example. Ensure the certificate is valid for its SMTP TLS use and includes required intermediate certificates. [1, 2]
Install certificate material
The staged files below are example input locations. The full-chain file contains the leaf certificate followed by intermediate certificates. The private key is unencrypted for unattended service startup and must remain root-readable only.
sudo install -d -m 700 /etc/postfix/tls
sudo install -m 600 /secure-staging/relay.key \
/etc/postfix/tls/relay.key
sudo install -m 644 /secure-staging/relay-fullchain.pem \
/etc/postfix/tls/relay-fullchain.pem
sudo postconf -e \
'smtp_tls_cert_file = /etc/postfix/tls/relay-fullchain.pem'
sudo postconf -e \
'smtp_tls_key_file = /etc/postfix/tls/relay.key'
# On RHEL:
sudo restorecon -Rv /etc/postfix/tls
Check identity and key pairing
sudo openssl x509 -in /etc/postfix/tls/relay-fullchain.pem \
-noout -subject -issuer -dates -ext subjectAltName
sudo openssl x509 -in /etc/postfix/tls/relay-fullchain.pem \
-pubkey -noout | openssl pkey -pubin -outform DER | sha256sum
sudo openssl pkey -in /etc/postfix/tls/relay.key \
-pubout -outform DER | sha256sum
The two public-key hashes must match. Verify certificate expiration, the accepted domain and the full chain separately; matching hashes alone do not prove certificate trust. Never paste the private key into a ticket or log.
Renew without an outage
Stage renewed files, verify them, install with the same ownership and permissions, restore RHEL contexts, then run postfix check and reload. Send a fresh external test and inspect the TLS log. Alert at 30, 14 and 7 days before expiration. Coordinate any domain-name change with the Microsoft connector owner before replacement.
9Secure application submission
The outbound smtp_ TLS settings protect Postfix to Microsoft 365. The separate smtpd_ settings protect applications to Postfix. For the standard production path, provision a server certificate covering relay01.contoso.com from a CA the applications trust, then require STARTTLS.
# Install inbound-fullchain.pem and inbound.key under
# /etc/postfix/tls using the permissions from section 8.
sudo postconf -e \
'smtpd_tls_cert_file = /etc/postfix/tls/inbound-fullchain.pem'
sudo postconf -e \
'smtpd_tls_key_file = /etc/postfix/tls/inbound.key'
sudo postconf -e 'smtpd_tls_security_level = encrypt'
sudo postconf -e 'smtpd_tls_mandatory_protocols = >=TLSv1.2'
If a legacy device cannot negotiate TLS, document that exception and isolate its traffic on a dedicated relay or restricted network segment. On a dedicated exception relay, may permits plaintext on the client leg; it does not change the secure outbound leg. Do not silently lower TLS for all applications. [3]
Ubuntu firewall example
On an already enabled UFW firewall with a default-deny incoming policy, add one rule per approved client. Review existing rules first; preserve administration access when enabling a firewall on a new host.
sudo ufw status numbered
sudo ufw allow from 10.20.30.21 to 10.20.30.10 port 25 proto tcp
sudo ufw allow from 10.20.30.22 to 10.20.30.10 port 25 proto tcp
RHEL firewall example
Identify the active interface zone. Replace public below if different. Add both clients and remove any pre-existing broad SMTP allowance after confirming its purpose.
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --list-all
rule='rule family="ipv4" source address="10.20.30.21/32" '
rule+='port port="25" protocol="tcp" accept'
sudo firewall-cmd --permanent --zone=public --add-rich-rule="$rule"
# Repeat for 10.20.30.22/32, then:
sudo firewall-cmd --reload
10Sender identity and domain protection
Set the application envelope sender (MAIL FROM) and visible From address explicitly, for example alerts@contoso.com. myorigin supplies a domain for unqualified local addresses; it does not rewrite arbitrary fully qualified application senders. Use a monitored address for failures wherever practical.
Optional envelope sender allowlist
On a dedicated application relay, an envelope sender allowlist can reject unexpected addresses. It is not proof of who sent the message: any trusted client can claim any listed sender. Per-application sender enforcement requires separate listeners or a policy service tied to source identity.
# /etc/postfix/allowed_senders
alerts@contoso.com OK
scanner@contoso.com OK
<> OK
Confirm the distribution supports the chosen map backend with postconf -m. lmdb is shown; use an available supported indexed type consistently if lmdb is absent.
postconf -m
sudo postmap lmdb:/etc/postfix/allowed_senders
sudo postconf -e \
"smtpd_sender_restrictions = check_sender_access \
lmdb:/etc/postfix/allowed_senders, reject"
sudo postmap -q alerts@contoso.com \
lmdb:/etc/postfix/allowed_senders
The empty sender entry preserves SMTP bounce semantics; it does not solve Microsoft tenant attribution for IP-only connectors. Test null-sender behavior separately. Do not rewrite all null senders into a normal address. These SMTP restrictions also do not constrain local processes submitting through sendmail.
SPF and recipient authentication checks
Merge authorized sending sources into the domain existing SPF record; do not create a second SPF TXT record. For this example, a record might include the relay public address and Microsoft 365. Preserve other legitimate senders and stay within SPF lookup limits. [8]
v=spf1 ip4:203.0.113.10 include:spf.protection.outlook.com -all
Coordinate DKIM and DMARC with the messaging owner. Inspect an externally received test message for the actual signing domain and SPF/DMARC alignment rather than assuming connector acceptance guarantees authentication success. Do not add broad spam bypass rules just to force tests through.
11Validation and acceptance tests
Start the service and check listener scope
sudo postfix check
sudo systemctl enable --now postfix
sudo systemctl restart postfix
sudo ss -lntp 'sport = :25'
sudo postqueue -p
A restart applies inet_interfaces and inet_protocols changes. Verify the listener is on the intended private address and loopback. On some Ubuntu installations the parent service status is not a complete daemon health check; confirm the listener and mail flow.
Verify Microsoft TLS independently
# Ubuntu trust path; use the RHEL CA path on RHEL.
openssl s_client -starttls smtp \
-connect contoso-com.mail.protection.outlook.com:25 \
-servername contoso-com.mail.protection.outlook.com \
-verify_hostname contoso-com.mail.protection.outlook.com \
-verify_return_error \
-CAfile /etc/ssl/certs/ca-certificates.crt </dev/null
Require a successful chain and hostname verification. This checks the upstream server certificate, not the connector client identity. Verify the actual Postfix TLS session and external delivery next.
Send a local transport test
/usr/sbin/sendmail -f alerts@contoso.com -t <<'EOF'
From: alerts@contoso.com
To: testrecipient@contoso.com
Subject: Postfix relay acceptance test
Controlled test from the relay host.
EOF
sudo postqueue -p
sudo journalctl --since "10 minutes ago" | grep postfix
Replace the recipient with an owned test mailbox. Repeat to an owned external mailbox. Local sendmail bypasses SMTP client restrictions, so it cannot validate application access control or inbound TLS.
Test from an approved client
swaks --server relay01.contoso.com --port 25 --tls \
--tls-verify --from alerts@contoso.com \
--to testrecipient@contoso.com \
--header "Subject: Approved client relay test"
| Test | Expected result | Evidence |
|---|---|---|
| Approved client to internal mailbox | Accepted and received | Queue ID, trace, received message |
| Approved client to owned external mailbox | Accepted and received | External headers and trace |
| Unapproved client to external address | Blocked or SMTP 5xx at RCPT | Firewall log or SMTP transcript |
| Unapproved client to internal address | Blocked or SMTP 5xx at RCPT | Same restriction applies |
| Plaintext from approved client | STARTTLS required | SMTP rejection without TLS |
| Temporary upstream outage in a lab | Mail deferred then delivered | Queue grows then drains |
| Null-envelope message if required | Correct connector attribution | Certificate path and delivery |
| Relay restart | Queue retained and service recovers | Queue IDs and successful retry |
To test the SMTP restriction separately from the firewall, temporarily allow a designated test host through the firewall only, leave it outside mynetworks, and stop the test at RCPT. Remove the temporary firewall rule immediately afterward. Do this only within the approved validation window.
swaks --server relay01.contoso.com --port 25 --tls \
--tls-verify --from probe@contoso.com \
--to owned-test@external.example --quit-after RCPT
Expect rejection for an untrusted source. Do not use arbitrary third-party recipient addresses. If the connection is blocked by the firewall, that proves the network boundary but not the Postfix rule; retain both forms of evidence when required.
Correlate the message
Record UTC time, envelope sender, recipient, Message-ID and Postfix queue ID. Find the upstream 250 response and status=sent in the log. Then open Exchange admin center, Mail flow, Message trace, and search by sender, recipient and time. A Microsoft handoff success is not confirmation of Inbox placement.
Capture your own screenshots of listener state, TLS verification, an approved submission, rejected unauthorized submission, queue state and message trace. Redact user addresses and message content according to local policy. Microsoft's example screenshots (in the PDF edition) are navigation references, not evidence of these tests.
12Message processing and failure flow
- Application connects to private relay on TCP 25Firewall checks source and client negotiates STARTTLS
- Postfix checks client and envelope policyRejected clients receive 5xx before message acceptance
- Postfix accepts DATA and assigns a queue IDA 250 here means the local relay has accepted responsibility
- SMTP client connects to tenant MX on TCP 25TLS verifies Microsoft identity and presents client cert if used
- Microsoft matches connector and accepted-domain identityTransport policies determine acceptance or rejection
- Microsoft returns 250 after DATALocal queue entry clears for that successful recipient
Temporary and permanent errors
4xx, timeouts or TLS failure: Postfix defers delivery and retries according to its queue schedule. Alert on growing queue age; do not make the application immediately resubmit messages the relay already accepted.
5xx: delivery fails for the affected recipient and Postfix normally generates a nondelivery report to the envelope sender. Multi-recipient messages can have mixed outcomes. Track recipient status, not only the queue entry.
Ambiguous connection loss: if the upstream accepted DATA but the acknowledgement was lost, a retry can cause a duplicate. Applications sending business transactions should use stable identifiers and tolerate duplicates.
13Troubleshooting by symptom
| Symptom | Check next | Corrective direction |
|---|---|---|
| Connection timeout to Microsoft | Port 25 egress, firewall, routing, DNS | Resolve network policy; do not substitute port 587 with the same connector settings |
| Relay access denied at Postfix | Client IP in logs and mynetworks | Correct exact approved source; check unexpected NAT |
| Tenant attribution or relay denied upstream | NAT IP, connector, envelope domain or client certificate | Match connector identity and accepted domain; header From alone is insufficient |
| TLS certificate verification failure | Clock, CA bundle, hostname and chain | Repair trust or endpoint; keep peer verification enabled |
| Internal mail works, external fails | Connector matching and external SMTP response | Internal Direct Send success does not validate relay |
| Authentication required on upstream | relayhost and inherited SASL overrides | Connector relay uses tenant MX TCP 25 with SASL off |
| Queue grows with temporary errors | Remote response, rate, DNS, storage | Fix cause and allow normal retry; avoid repeated global flushes |
| Delivered to Junk or quarantine | Trace and authentication headers | Review domain authentication and content with messaging owner |
| Certificate file permission denied | File ownership, directory traversal, SELinux | Restore intended access and context |
| Mail vanishes locally | mydestination, transport maps and logs | Remove unintended local delivery only after review |
Useful inspection commands
sudo postqueue -p
sudo postcat -q QUEUE_ID
sudo postconf -n
sudo postconf -M
sudo journalctl --since "30 minutes ago" | grep postfix
14Operations and monitoring
Monitor the entire path
Alert on service or listener failure, oldest queued message age, deferred-message count, disk and inode exhaustion, TLS errors, certificate expiration and unexpected sender or volume changes. Queue age is often a better signal than queue count for low-volume notification systems.
Suggested starting thresholds are operational examples: warn after 10 minutes of unexpected queue age and escalate after 30 minutes for time-sensitive alerts. Tune for normal bursts and business impact. Send monitoring alerts through a separate path so a broken relay can still be reported.
sudo postqueue -p
df -h /var/spool/postfix
df -i /var/spool/postfix
sudo postconf maximal_queue_lifetime bounce_queue_lifetime
sudo openssl x509 -in /etc/postfix/tls/relay-fullchain.pem \
-checkend 2592000 -noout
The certificate command exits nonzero when expiration is within 30 days. Run only for a configured certificate. Query queue lifetimes instead of assuming defaults; adjust them only to a documented delivery and failure-notification policy.
Routine changes
Back up /etc/postfix, certificate files, relevant firewall rules and connector settings securely. Restrict backups containing keys. After changes, run postfix check, reload for ordinary settings, and restart when required by listener or protocol changes. Complete a new approved-client and external-delivery test.
Controlled retries
# After correcting a failure, retry one verified queued message:
sudo postqueue -i QUEUE_ID
# Hold or release one message during investigation:
sudo postsuper -h QUEUE_ID
sudo postsuper -H QUEUE_ID
Do not delete or requeue the entire queue as routine troubleshooting. Deletion loses mail; requeueing can change processing and cause duplicates. Pause the offending application first during an abuse incident, then assess queued messages with the messaging owner.
15Resilience and optional local mode
Two independent relays
- Applications with primary and secondary SMTP targets
- Relay A queue + Relay B queueIndependent persistent storage and identical source policy
- Known egress identity for every pathCertificate identity or registered static NAT addresses
- Microsoft 365 connector and transport
Use two relays in separate failure domains where the application supports failover. Each queue is local: a second server does not deliver messages stranded on a failed first server. Recover that server or its storage, or rely on documented application behavior for messages never accepted.
A load balancer must preserve client identity or be designed with an explicitly tested trust model. If every source becomes the load balancer IP, trusting that IP can unintentionally trust all clients. Do not share the Postfix spool between active instances.
Loopback only for host generated messages
If the server sends only its own notifications and will not relay for other machines, use a null-client variant. It removes the network submission surface while keeping upstream transport settings. [5]
sudo postconf -e 'inet_interfaces = loopback-only'
sudo postconf -e 'mynetworks = 127.0.0.0/8'
sudo systemctl restart postfix
This IPv4-only example follows the shared baseline. Remove client firewall allowances in this variant. Local processes still need governance: a local sendmail submission is not subject to SMTP client access rules.
16Alternatives and authentication changes
When connector relay is not suitable
If outbound TCP 25 is blocked or you cannot provide a supported connector identity, select an alternative service deliberately. Do not change relayhost to smtp.office365.com:587 and expect the connector to authenticate the session. That endpoint is a different submission method.
For SMTP AUTH with OAuth, plan the SASL OAuth mechanism, token acquisition and renewal, application permissions, mailbox authorization, secret storage and failure monitoring. A static access token in a Postfix password map is not a complete solution. Treat it as a separate implementation with its own acceptance tests.
Current Basic authentication timeline
Microsoft revised its published schedule in January 2026. Behavior remains unchanged through December 2026; at the end of that month Basic authentication is to be disabled by default for existing tenants, with administrative re-enablement still possible. New tenants after December 2026 have it unavailable by default. Microsoft plans to announce the final removal date in the second half of 2027. Recheck the official notice before any migration. [9]
This guide therefore does not introduce a username/password relay recipe or recommend disabling tenant security defaults. Connector certificate and IP identity do not use SMTP AUTH passwords.
High volume or cloud application requirements
Microsoft 365 relay is not an unlimited bulk-mail platform. For transactional cloud applications or large-volume workloads, assess a service designed for that use case, its sender-domain verification, throughput, bounce handling and delivery reporting. Keep the Postfix queue and application retry requirements explicit in the selected design.
17Cutover and rollback checklist
Before the change window
- Confirm the approved hosts, envelope senders, recipient scope and message sizes. Record the tenant MX, connector identity and firewall change reference.
- Back up current configuration and certificate material; record ownership and permissions. Verify that the previous route can still be restored.
- Complete all acceptance tests, including unauthorized-client rejection and external delivery. Assign the queue and certificate monitoring owner.
During cutover
4. Move one low-risk application to the new relay. Record its old SMTP target first. Send a uniquely identified message and confirm receipt.
5. Review TLS logs, queue age, failures and duplicate behavior. Migrate remaining clients in controlled groups, retaining timestamps and evidence.
6. Confirm monitored envelope sender addresses can receive failure notifications. Test a null-envelope case if the workload generates bounces.
Rollback procedure
7. Pause or redirect application submissions to the previously validated route. Record queued message IDs and status before touching the service.
8. Restore the exact approved configuration and firewall changes from backup. Preserve the spool; do not copy over a live queue or clear it. Run postfix check and restart if listener settings changed.
9. Test delivery on the restored route. Reconcile messages already accepted by the new relay to avoid sending them twice. Retire its connector only after the queue is empty or a documented recovery plan covers remaining mail.
Production signoff record
| Owner | Required evidence | Signoff |
|---|---|---|
| Linux operations | Configuration, TLS, listener, restore plan | __________ |
| Network team | Source ACLs, NAT and egress tests | __________ |
| Messaging team | Connector, domain identity and trace | __________ |
| Application owner | Internal and external tests, retries | __________ |
| Service owner | Monitoring and response ownership | __________ |
18Official references
- Microsoft device and application mail setuphttps://learn.microsoft.com/en-us/exchange/mail-flow-best-practices/how-to-set-up-a-multifunction-device-or-application-to-send-email-using-microsoft-365-or-office-365
- Microsoft updated SMTP relay requirementshttps://learn.microsoft.com/en-us/exchange/mail-flow-best-practices/updated-requirements-smtp-relay
- Postfix TLS supporthttps://www.postfix.org/TLS_README.html
- Ubuntu install and configure Postfixhttps://ubuntu.com/server/docs/how-to/mail-services/install-postfix/
- Red Hat Enterprise Linux 9 deploying mail servershttps://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html-single/deploying_mail_servers/index
- Postfix configuration parameter referencehttps://www.postfix.org/postconf.5.html
- Microsoft New InboundConnector referencehttps://learn.microsoft.com/en-us/powershell/module/exchangepowershell/new-inboundconnector?view=exchange-ps
- Microsoft SPF configurationhttps://learn.microsoft.com/en-us/defender-office-365/email-authentication-spf-configure
- Microsoft updated SMTP AUTH Basic authentication timelinehttps://techcommunity.microsoft.com/blog/exchange/updated-exchange-online-smtp-auth-basic-authentication-deprecation-timeline/4489835
Screenshot and diagram provenance
The PDF edition includes four official Microsoft screenshots embedded in reference [1], accessed 20 September 2026. They show the Microsoft example interface and tenant values, not a live configuration in your organization, and are not reproduced on this page. The process diagrams and operational procedures were prepared for this guide.