Neither Imap nor Yourmap: Yeet Legacy Authentication!

Every so often, the prevailing forces in the IT industry collectively decide that a protocol must be deprecated. The Internet Messaging Access Protocol (IMAP) appears to be one of the latest victims of this phenomenon. This has caused some inconveniences, but I'm okay with the reasoning behind this: an increased emphasis on security and requiring of multi-factor authentication.

Of the tech giants I've seen addressing this, it seems Microsoft hates IMAP more than Google. I use a library that reads my Gmail messages through IMAP, and Google's way of handling the inherent flaws in the protocol is to set up different credentials to access Gmail via IMAP. From a security standpoint, this seems like a half-measure, but it's better than nothing. Microsoft is strongly recommending that Exchange administrators disable IMAP and POP3 (seriously, why is anyone still using POP3?) and making sure two-factor authentication is on for all of tenant accounts, whether they're shared/system accounts or named users.

Monica and I are increasingly focusing on improving our Microsoft Secure Score on our 365 Tenant, and my little email processing app that handles inbound emails to our help desk ticketing system is at odds with disabling the IMAP protocol and enabling MFA on the But after a blip of my program not working during the summer, it stopped working for good a few weeks ago. Just kept failing to authenticate over and over, despite IMAP being turned on for the help account.

The options for our environment as I saw them were as follows, in order of least to most difficult:

  1. Deprecate emails to the helpdesk
  2. Try to make legacy authentication work somehow
  3. Figure out the new way of doing things and enable MFA

I had already previously tried to use a python Exchange library to access our inbox but I could never get it to work. Like, at all. Upon researching some more, I found python-o365. Python O365 hooks seamlessly to Microsoft Graph, their REST API.

Initially I was sort of perturbed at the idea of refactoring a thing I had knocked out quickly. It had been working just fine for over a year. There's some research and setup work that definitely needs to be done up front involving setting permissions on the app in the MS Azure portal, but luckily this is all outlined nicely in the O365 documentation. I thought I was doing something wrong as I struggled to get it to connect to the account I wanted to process before realizing my mistake. This part worked fine:

The API gave me a link to establish a connection to an account, but the problem kept having was that I was still signed in as the Tenant Administrator, meaning it was not establishing the account I wanted to connect to on this step:

In other words, it seems stupidly simple in retrospect, but the mailbox to which you are trying to connect needs to match the one getting passed in as the mailbox object. The admin account is not a cheat code to accessing all the things. Once I realized my error and got signed in properly, I was off and running with the code refactor. Big props to the O365 API developer, the interface is clean, and overall, a pleasure to work with. With a new lease on security life, I took the opportunity to clean up some of the security aspects of this project, utilizing the the CryptFileKeyring backend of the python-keyring package to securely store sensitive credentials:

I abstracted anything sensitive away in keyring, and anything custom or needing to be set to match our environment was done in a TOML config file and stashed in user space. This process allows us to get away from all legacy authentication, and the biggest win here is in the security realm. Now that we're utilizing Bitwarden's TOTP code functionality on our shared enterprise accounts, we can now confidently enable Multi-Factor Authentication on service and shared accounts in our environment!