Skip to content

Repository files navigation

Mail_Migrate

Windows desktop console for migrating Exchange Server 2019 → mailcow. Inventories Exchange, transforms it into mailcow objects, pushes them over the mailcow API + SSH, and runs the mailbox mail copy.

Single ~155 KB .exe. No .NET SDK, no Visual Studio, no runtime install — builds with the csc.exe already on every Windows box and runs on in-box .NET Framework 4.x.

Download the latest release


Tabs

1 · Inventory & Export

Inventory & Export

30 read-only inventory categories (Get-* only) → a timestamped folder of CSVs, SUMMARY.csv, and a log. With Generate mailcow artifacts on, it also writes the mailcow\ folder: domains.json, mailboxes.json (size-derived quotas), aliases.json, forwarding-filters.json, relayhost.json, forwarding-hosts.json, mailbox-credentials.csv, postfix-extra.cf, sasl_passwd, and MIGRATION-REPORT.md.

Leave the FQDN blank to auto-connect when run on the Exchange server.

2 · mailcow Server

mailcow Server

Connection config shared by tabs 3 and 4, with Test API and Test SSH buttons. SSH uses the OS clients — ssh.exe/scp.exe for key auth, PuTTY plink/pscp for password auth (host key auto-probed and pinned). No managed SSH dependency.

3 · Settings Import

Settings Import

Pushes the transform output into mailcow. Dry-run until you tick Execute.

Exchange mailcow
Accepted domains /add/domain
Mailboxes, shared mailboxes /add/mailbox
Secondary addresses, distribution groups /add/alias
Mailbox forwarding /add/filter (sieve)
Send connector smarthost + credentials /add/relayhost + per-domain /edit/domain (Routing → Sender-Dependent Transport)
Anonymous receive connector IPs /add/fwdhost (Routing → Forwarding Hosts)
/add/dkim + generated DNS-CUTOVER.md

Public IP ranges on receive connectors are flagged for review, never auto-trusted into mynetworks. Non-routable domains (.local) and system mailboxes (HealthMailbox…) are dropped automatically.

4 · Mail Migration

Mail Migration

Prepare Exchange source — the only write to Exchange. Enables the IMAP services, creates (or password-resets) the migration account, and grants it FullAccess to every user mailbox. Requires running as Administrator.

Then either:

  • mailcow Sync Jobs via API (recommended) — one job per mailbox; mailcow runs imapsync itself on a schedule, visible and retryable in the mailcow UI.
  • imapsync once over SSH — uploads a script, runs it live, deletes it.

Both authenticate to Exchange as migrator@domain\targetalias with --exchange1. This is the form Exchange 2019 actually accepts — --authuser1 does not work.


Build

powershell -ExecutionPolicy Bypass -File .\build.ps1

Copy both Mail_Migrate.exe and Mail_Migrate.exe.config to the Exchange server and run from a local disk as an Exchange-privileged user, elevated.

Requirements

  • Exchange server with EMS/remoting (the app auto-connects: RemoteExchange.ps1 → remote PSSession → snap-in)
  • .NET Framework 4.x, x64
  • mailcow API key with read-write, and its IP allow-list including your source IP
  • For the SSH steps: OpenSSH or PuTTY on PATH
  • For imapsync-over-SSH: imapsync on the mailcow host, or Docker

Does not migrate

IMAP carries mail only. Calendars, contacts, tasks and notes need a separate move (SOGo import or an EWS→CalDAV/CardDAV tool). Public folders, transport rules, litigation hold, retention policies and journaling have no mailcow equivalent — they are inventoried and listed in MIGRATION-REPORT.md, not migrated.

Exchange passwords cannot be exported. Mailboxes are created with generated passwords (written to mailbox-credentials.csv, reused as the imapsync destination auth) — reset them after cutover.

Suggested order

  1. Inventory & Export on the Exchange server
  2. mailcow Server → Test API, Test SSH
  3. Settings Import → dry-run, read the log, then Execute
  4. Mail Migration → Prepare Exchange source, dry-run, then run
  5. Publish the records in DNS-CUTOVER.md and cut over MX

MAILCOW-SETUP.md covers standing up the mailcow host itself.

Notes

  • mailmigrate.settings next to the exe stores every field including passwords, in plaintext, so nothing is retyped between runs. Keep it private; delete it when done.
  • Sources are C# 5 — the in-box csc.exe is pre-Roslyn, so no ?., string interpolation, expression-bodied members, local functions, or auto-property initializers.
  • Export-ExchangeInventory.ps1 and Prepare-ExchangeForMigration.ps1 are standalone script equivalents if you'd rather not run a binary.

License

MIT

About

One-stop Windows console for migrating Exchange Server 2019 to mailcow - inventory, transform, API/SSH settings import, and mailbox sync via imapsync.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages