Postfix & Office 365: relay all outbound email (including local) but deliver inbound email

We're slowly migrating over to Office 365 away from Postfix/Dovecot, with the goal of enabling a few users at a time. Mail for our domain should come in to Office 365 then if there's no address match found within Office 365, it should get forwarded on to Postfix which delivers it to a Dovecot mailbox (we are using a virtual users setup, all users being stored in a separate LDAP server). This allows us to use Office 365 for users that have been set up, but for others that haven't, mail goes to the existing Postfix/Dovecot system.

I have followed these instructions on making connectors etc and it works - after whitelisting EOP IPs, Office 365 will deliver to Postfix fine. The problem is getting things to go in the opposite direction. All outgoing email should be relayed through Office 365, and if I set a relayhost variable and remove our local domain from mydestinations then this works... but then Postfix won't deliver any incoming mail (results in a bounce loop). If I keep our domain in mydestinations then mail gets delivered locally and doesn't go through the relay, which means that users still on the Postfix system are unable to send email to Office 365 users.

Is there a way to force all outbound email (including locally delivered) to go via the relay yet still accept inbound email for the same domain? I've been running up against a wall all yesterday and the only real solution I can think of is to run two separate Postfix instances - one that relays everything and the other that is just used for incoming mail. But surely there's a way to do this with just one instance? I've searched but everywhere just seems to assume you're only relaying email and doing nothing else.

postconf -n looks like this (domain changed to example.com). I've taken out all the changes I made in the attempt to get Office 365 relaying:

alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
append_dot_mydomain = no
biff = no
content_filter = smtp-amavis:[127.0.0.1]:10024
dovecot_destination_recipient_limit = 1
inet_interfaces = all
inet_protocols = all
mailbox_command = /usr/lib/dovecot/deliver
mailbox_size_limit = 0
mailbox_transport = dovecot
message_size_limit = 20480000
mydestination = $myhostname, silver.example.com, localhost.example.com, localhost, example.com
myhostname = smtp.example.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 192.168.0.0/24 192.168.10.0/24
myorigin = /etc/mailname
readme_directory = no
receive_override_options = no_address_mappings
recipient_bcc_maps = hash:/etc/postfix/recipient_bcc
recipient_delimiter = +
relayhost =
smtp_tls_note_starttls_offer = yes
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/recipient_access, check_sender_access hash:/etc/postfix/sender_access, check_sender_access cidr:/etc/postfix/o365, reject_authenticated_sender_login_mismatch, permit_sasl_authenticated, permit_mynetworks, reject_invalid_hostname, reject_non_fqdn_hostname, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain, reject_unauth_pipelining, reject_unauth_destination, reject_rbl_client bl.spamcop.net, reject_rbl_client b.barracudacentral.org, reject_rbl_client zen.spamhaus.org, reject_rbl_client cbl.abuseat.org
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = private/auth
smtpd_sasl_type = dovecot
smtpd_sender_login_maps = hash:/etc/postfix/local_senders, ldap:/etc/postfix/ldap_senders.cf
smtpd_tls_CAfile = /etc/ssl/certs/example.com.cabundle
smtpd_tls_cert_file = /etc/ssl/certs/example.com.crt
smtpd_tls_key_file = /etc/ssl/private/example.com.key
smtpd_tls_loglevel = 1
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3
smtpd_tls_received_header = yes
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_session_cache_timeout = 3600s
smtpd_use_tls = yes
tls_random_source = dev:/dev/urandom
virtual_alias_domains = events.example.com
virtual_alias_maps = hash:/etc/postfix/redirect, ldap:/etc/postfix/ldap_virtual_users.cf, ldap:/etc/postfix/ldap_virtual_groups.cf
virtual_transport = dovecot

To get all mail relaying, I could set relayhost = example-com.mail.protection.outlook.com and remove example.com from the mydestinations list, which gets delivery working for Office 365 but then breaks the old system.

I looked into using transport_maps to try sending all emails for specific email addresses (ie. the ones moved to Office 365) via the relay and everything else works locally, but the values in there seem to always get ignored.

I'm totally out of ideas, so if anyone has any I'd be grateful.


Solution 1:

OK I'm not totally happy with this, but I got it working. I feel like there's a more straightforward way though, but I can't figure it out.

After further research, I found that virtual_alias_maps is run before anything in transport_maps, which is why I thought it was being ignored. So if you have addresses being rewritten then whatever the output from the virtual alias rewrites needs to match what you're going to feed into transport_maps. Then my transport_maps hash looks like this:

[email protected]        smtp:example-com.mail.protection.outlook.com
@example.com  :
*       :

This would cause email sent to [email protected] to be relayed to Office 365, but everything else gets delivered locally.

It works, but I still feel like there's a better way to handle this.