Migrating the Mail Service From macOS Server

Migrating from macOS Mail Server is going to be one of the stranger migrations you might do. Why? Unless you’re moving to basically a custom build of the same tools used in macOS Server (which you’d do by forklifting /Library/Server/Mail/ into a postfix environment and putting the various components Apple changed at compile-time back together), the process for moving to a modern system is going to rely on IMAP and look a little like this:
  • Get a list of accounts
  • Provide the password for each account
  • Setup an initial sync of mailbox contents
  • Look for errors
  • On the day that you cut MX records, do another sync
  • On the day that you cut MX records, migrate local accounts
  • Do a final sync
  • Archive the spam account
  • Take the server offline
You can do this with less effort (e.g. users need to backup their mailboxes, do the sync once, etc), but in my experience the above process has produced the best result for the consumers of mail services and for customers of various types of consultancies. The technical portion of this is pretty straight forward if you follow these steps. The part I like the least is the fact that whosoever has access to those passwords has access to mailboxes, and your actions during that time are very much open to interpretation.

Let’s start by looking at the domains running on the mail server. We’ll do this with serveradmin, by looking at the settings of the mail:postfix:domains:_array_index:

sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin settings mail:postfix:domains:_array_index:

The return will list all of the domains running on the server:

mail:postfix:domains:_array_index:0:name = "krypted.com"

mail:postfix:domains:_array_index:1:name = "kryptedadmin.com"

The primary domain, or the one in _array_index:0 should map to the mydomain variable in /Library/Server/Mail/Config/postfix/main.cf. All of the users will be stored in /Library/Server/Mail/Config/postfix/virtual_users. To see them, simply cat that file:

cat /Library/Server/Mail/Config/postfix/virtual_users

Which would return a line similar to this one for each email account:

charles.edge@krypted.com charles.edge

To just see a list of email address, you could run:

sudo cat /Library/Server/Mail/Config/postfix/virtual_users | grep -E -o "\b[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9.-]+\b"

Now that you have a list of email address, you can easily put them into a file that will sync mailboxes. There are a number of tools you could use to migrate actual mail. These include:
Now, let’s look at using imapsync to actually sync a mailbox. In the most basic form, you could just do:

imapsync --host1 oldmail.krypted.com --user1 charles.edge --password1 mypassword --host2 newmail.krypted.com --user2 charles.edge --password2 mynewpassword

For a small set of users you could easily just paste this command into a .sh file, and run it then run it again the night of the sync, and then run a cleanup a couple of days later in case there were any stragglers. This isn’t going to work for everyone. A lot of people will use custom settings in mail apps. If necessary, you can also configure ports for both servers with –port1 and –port2. You can also configure SSL, synchrinization options, regular expression conversions on objects during the migration, include and exclude items with mail folders, move passwords into a file, etc. Before doing the sync, I’d recommend syncing a test mailbox and reading the entire manpage at https://github.com/imapsync/imapsync.

Changing MX and getting mail to actually flow to the new servers is just a matter of making sure there’s an A Record for the new mail server and putting the MX to that. I recommend setting the TTL of your dns records for mail servers as low as your DNS server or registrar will allow until the migration process is complete. The reason for this is that you want to keep the time frame that mail could flow to both servers at a minimum. The final sync is because DNS changes aren’t instant. Some DNS servers get a lot of traffic and so don’t respect the TTL for a given record. Therefore, that final sync pulls everything that might have accidentally been flowing into your old server into your new server. 

Next, you’ll need to change the host name of the mail server in mail clients and hopefully have users reset their passwords so you don’t have access to their mail any longer. For this, I recommend pushing a profile (e.g. using an MDM or command line equivalent). 

I have seen a number of environments (and helped in some cases) get really crafty. They might present a user with a forced “change password” dialog and then have that stored in a file that admins can’t access. It’s in clear text and there’s always risk. But this allows for non repudiation. It also means that when you send a profile to a device you can have the new account show up and work without the user having to enter a password. Every time users have to touch something, there’s the chance it will get mistyped (I typo things all the time) and there’s a chance that they’ll be confused and call you, so the larger the user base you’re migrating, the more logic you’ll hopefully be able to apply to this process to help keep your phone from ringing. I’ve also seen environments where admins had users type in the password, monitor the sync, and then proceed using client-side scripts. This has always been fraught with peril, but offers an added sense of privacy. 

Don’t forget to grab the mailbox. Seems like this is the main reason I’ve had to revive dead servers. Something got put there and someone needs it… Migrating that mailbox the same as you would any other is a good idea, just-in-case. If you don’t know your quarantine address, run the following to find it:

sudo serveradmin settings mail:postfix:spam_quarantine

Once you’re sure that no mail is flowing to the old server (72 hours is usually a good time frame), you can pull the old server offline. I recommend keeping the server or a clone of the server forever. I’ve needed to revive them here and there due to a variety of reasons that have nothing to do with data integrity of what was migrated. You never know. And if you’re a consultant, there’s no easier way to get fired than to go mucking about with access to mail without a lot of communication in advance. 

Overall, this process can be pretty seamless to your users. But it requires more labor on your side. To keep costs and effort down for you, you could type up a document that steps people through things, but I prefer people at work liking me, so wouldn’t do that personally. Good luck and please comment here if you have further tools or workflows that you prefer!