Microsoft 365 split-delivery migration
A step-by-step guide for migrating a team off Microsoft 365 / Exchange Online onto Cirrux gradually, without moving the primary MX records up front.
The core idea is identical to the Google Workspace playbook: the team keeps Microsoft 365 as the authoritative inbox for domain.com(MX stays on M365), and a copy of each user’s mail is routed into Cirrux via a subdomain whose MX points at Cirrux. M365 forwards each mailbox to its counterpart on the subdomain, Cirrux accepts it, and because every Cirrux mailbox owns an address on both the main domain and the subdomain, users can already send and receive as their real domain.com address from within Cirrux. When the team is confident, the main-domain MX cutover is a small, reversible final step.
This de-risks the migration: nothing breaks on day one, both systems run in parallel, and rollback is just “stop forwarding.”
The big difference from Google: there is no workspace-level M365 sync. History migration is manual and per-userusing Cirrux’s built-in IMAP, VCF, and ICS importers (Phase 6). Mail comes over IMAP; contacts and calendar are exported from M365 and uploaded.
Concepts
The moving parts
- Main domain — the team’s real domain, e.g.
domain.com. Its MX records stay on Microsoft 365 for now. - Cirrux subdomain — a subdomain added purely to receive forwarded mail, e.g.
cirrux.domain.com. Its MX records point at Cirrux. Pick a subdomain that won’t collide with anything the team already uses. - Mailbox address— an email address attached to a Cirrux mailbox. A single mailbox can own multiple addresses across multiple domains. Each mailbox gets an address on both the main domain and the subdomain.
- Split delivery— both M365 and Cirrux end up with a copy of inbound mail. Cirrux’s spam filter already recognises authenticated forwarders, including Outlook SRS (
Resent-From) and Outlook inbox-rule forwards (X-MS-Exchange-Inbox-Rules-Loop), and skips the envelope-from / domain-mismatch penalty for them.
How mail flows during the parallel phase
┌─────────────────────────────────────┐
sender ──MX──▶ │ Microsoft 365 (domain.com) │
│ user@domain.com ── forward rule ─┐ │
└────────────────────────────────────┼─┘
│
forwards to ▼
user@cirrux.domain.com ──MX──▶ Cirrux
│
resolves to mailbox via
MailboxAddress (subdomain)
▼
Cirrux mailbox
(also owns user@domain.com,
so it can send as the real
address, accepted by others)- Inbound: sender → M365 (MX) → forward rule →
user@cirrux.domain.com(MX → Cirrux) → resolved to the Cirrux mailbox. - Outbound from Cirrux: the user sends as
user@domain.com. Because the main domain’s SPF/DKIM are configured for Cirrux (Phase 2), receiving servers accept it. - M365 keeps its own copy in the original mailbox, so nothing is lost and the team can fall back at any time.
Prerequisites
Before you begin
- You have admin access to the team’s DNS (for both the main domain and the subdomain).
- You have Microsoft 365 Global admin (or Exchange admin) access (needed to set forwarding and, later, SSO).
- DNS TTLs on the main domain are reasonably low (helps the eventual cutover; not blocking for the parallel phase).
Migration phases
Create the Cirrux workspace and add both domains
Create the workspace for the team in Cirrux (via /admin/workspaces or the normal onboarding flow).
Add the main domain (domain.com). Do notchange its MX records yet — they stay on M365. The main domain is added so Cirrux can own the sending identity (SPF/DKIM/DMARC) and so mailboxes can hold a @domain.com address.
Add the Cirrux subdomain (cirrux.domain.com, or your chosen subdomain). This is the domain whose MX will point at Cirrux so it can actually receive the forwarded mail. Enable auto-alias members for the subdomain: whenever a new mailbox is created for the main domain, it will automatically add a mailbox address for the subdomain.
Why two domains? You can’t point domain.com’s MX at Cirrux without breaking M365 delivery. The subdomain gives Cirrux a real inbound path (MX → Cirrux) while the main domain stays on M365.
Configure DNS
A domain becomes active in Cirrux only when ownership, SPF, DKIM, and DMARC all pass. MX is allowed to stay in a warning state for split delivery.
Subdomain DNS (cirrux.domain.com)
- MX → point at Cirrux (
smtp.cirrux.co). This is what makes Cirrux receive the forwarded mail. - Ownership TXT →
cirrux-verification=<token>from the Cirrux domain page. - SPF →
v=spf1 include:_spf.cirrux.co ~all. - DKIM→ publish the CNAME records Cirrux generates for the subdomain.
- DMARC →
_dmarc.cirrux.domain.comTXT starting withv=DMARC1. - Confirm the subdomain reaches active status in the admin panel.
Main domain DNS (domain.com)
- MX → leave on Microsoft 365 (
<tenant>.mail.protection.outlook.com). Cirrux will report this domain’s MX as awarning(non-Cirrux MX present) — that’s expected and fine for split delivery. - Ownership TXT →
cirrux-verification=<token>from the Cirrux domain page. - SPF → add Cirrux to the existing record so mail sent from Cirrux as
@domain.compasses SPF. Keep Microsoft’s include too while both systems send:v=spf1 include:spf.protection.outlook.com include:_spf.cirrux.co ~all. - DKIM→ publish Cirrux’s DKIM CNAMEs for the main domain. Cirrux uses its own selectors, so they coexist with Microsoft’s DKIM (
selector1/selector2._domainkey). - DMARC→ ensure a DMARC record exists; if tightening policy, do it cautiously while two senders are active.
- Confirm the main domain reaches active (MX
warningis acceptable).
The point of configuring the main domain’s SPF/DKIM in Cirrux is outbound: it lets users send from Cirrux as their real user@domain.com and be accepted by receiving servers, even though inbound MX still points at M365.
Create mailboxes with dual-domain addresses
Do this for one pilot mailbox first, validate the whole loop, then repeat for the rest of the team.
- Create the Cirrux mailbox for the user (e.g. via the workspace member flow).
- Ensure the mailbox has both
user@cirrux.domain.comanduser@domain.comaddresses linked.
A single mailbox holding addresses on multiple domains is a first-class capability. Mail addressed to either the subdomain or the main domain resolves to the same mailbox.
Configure forwarding in Microsoft 365
The goal: mail arriving at user@domain.com in Microsoft 365 is forwarded to user@cirrux.domain.com, so Cirrux receives a copy while M365 keeps the original.
Pilot (single mailbox) approach — recommended starting point
- Open the Exchange admin center.
- Go to Recipients → Mailboxes.
- Select the pilot user’s mailbox, e.g.
user@domain.com. - Open the Mailbox tab → Manage email forwarding.
- Enable Forward all emails sent to this mailbox and enter
user@cirrux.domain.com. - Tick Keep a copy of forwarded messages so M365 retains the original as fallback.
- Send a test mail to
user@domain.comand confirm it lands in both M365 and the Cirrux mailbox.
Org-wide approach (later, once the pilot is validated)
- Use an Exchange mail flow rule(Exchange admin center → Mail flow → Rules) to Bcc / redirect mail for a group to the corresponding
@cirrux.domain.comaddress. - Decide scope: a single distribution group, a security group, or the whole domain.
Microsoft 365 blocks automatic external forwarding by default (Defender outbound anti-spam policy). If forwarded mail never reaches Cirrux, you likely need to allow it — see Troubleshooting. Mail flow rules are not subject to the same block.
Also relevant: Microsoft’s mail-flow documentation.
Validate the parallel phase
- Inbound: external mail to
user@domain.comappears in Cirrux (via the subdomain forward) and in M365. - Outbound: a mail sent from Cirrux as
user@domain.comis accepted by an external provider (check it doesn’t land in spam — confirm SPFpassand DKIMpassin the received headers). - Cirrux does not flag the forwarded mail as spam (the Outlook SRS / inbox-rule forwarder handling should cover it).
- Repeat for a few more mailboxes before scaling to the whole team.
History migration: manual IMAP + VCF + ICS import
There is no workspace-level M365 sync. Migrate existing data per-user with Cirrux’s built-in importers. Do this for the pilot user first, validate, then repeat.
Mail: IMAP importer
- Generate an app passwordfor the M365 mailbox (the IMAP importer is username/password only — it does not do OAuth, so a normal password won’t work when MFA is on). Ensure IMAP is enabled for the mailbox in M365.
- Create an IMAP import account (via the import flow in Settings → Sync & Import) pointing at host
outlook.office365.com, port993with SSL on, usernameuser@domain.com, the app password, and the user’s Cirrux mailbox as the destination. - Run folder discovery, then enable the folders to import. The folder/label structure is preserved (Inbox, Sent, Trash, etc. are mapped automatically).
- Start the import run and monitor progress. Runs are resumable, and individual failed messages can be retried.
See the IMAP import guide for full details.
Contacts: VCF importer
- Export contacts from Outlook / OWA as a
.vcf(vCard) file. - Upload it via the Cirrux VCF import flow, choosing the destination address book. One bad card is skipped rather than aborting the whole import.
Calendar: ICS importer
- Export the calendar from Outlook / OWA as an
.icsfile. - Upload it via the Cirrux ICS import flow, choosing the destination calendar.
These importers are one-shot snapshots, not continuous sync. Run them close to cutover (or re-run the IMAP import) so the gap between the last import and cutover is small. New mail in that gap still arrives via the Phase 4 forwarding.
Scale-out: Single Sign-On
Set up OIDC SSO so users sign into Cirrux with their Microsoft Entra ID (Azure AD) identity. Follow the dedicated SSO setup guide for the Cirrux-side steps (create connection, set default domain, activate, test).
On the IdP side, register an app in Entra ID, use issuer https://login.microsoftonline.com/<tenant-id>/v2.0, and add the Cirrux callback URL as a redirect URI.
Cut over (when the team is ready)
- Confirm all mailboxes exist in Cirrux with both addresses, and users are comfortable in Cirrux.
- Run a final IMAP import (and fresh VCF/ICS exports) so recent history is captured.
- Lower the main domain’s MX TTL ahead of time.
- Switch
domain.com’s MX records to Cirrux (smtp.cirrux.co). - Remove the M365 forwarding rules (no longer needed, Cirrux now receives directly).
- Tighten SPF: drop Microsoft’s include once M365 no longer sends for the domain.
- Monitor for bounces / routing issues during DNS propagation.
- Keep the Microsoft 365 mailboxes around briefly as a safety net before decommissioning.
Rollback before cutover is trivial: disable forwarding and users keep using M365. After cutover, rollback means pointing MX back at M365.
Troubleshooting
Forwarded mail never reaches Cirrux
M365 blocks automatic external forwarding by default. In the Microsoft 365 Defender portal, check the outbound spam filter policy(Email & collaboration → Policies → Anti-spam → Outbound) and allow automatic forwarding for the relevant users, or use a mail flow rule (which is not subject to the same block) instead of mailbox forwarding.
IMAP import fails to authenticate
Confirm IMAP is enabled for the mailbox, that you’re using an app password (not the account password) when MFA is on, and host/port outlook.office365.com:993 with SSL.
Forwarded mail flagged as spam in Cirrux
Confirm the M365 forwarder is authenticated; the Outlook SRS / X-MS-Exchange-Inbox-Rules-Loop handling should skip the domain-mismatch penalty. Check the received headers for the forwarding hop.
Outbound @domain.com mail rejected or spam-foldered
Verify the main domain shows SPF valid and all DKIM keys valid in the admin panel, and that the receiving server sees dkim=pass.
Main domain stuck not active
MX in warning is expected (it points at M365); the blocker is usually ownership TXT, SPF, DKIM, or DMARC. Check each in the domain settings.
Forwarded mail doesn't arrive in Cirrux
Verify the subdomain’s MX points at Cirrux and the mailbox actually owns the @cirrux.domain.com address (the resolver needs an exact mailbox-address match, or a domain catch-all).
User can't send as their real address
Confirm the mailbox owns the @domain.com address, not just the subdomain one.
In short
Both systems run side by side throughout the migration. M365 stays authoritative until you’re confident in Cirrux, every Cirrux mailbox can already send and receive as its real address, history comes across with the IMAP/VCF/ICS importers, and the final MX cutover is a small, reversible step.