Last week, I discussed the need for email client upgrades to cope with the imminent termination of support for basic authentication for seven protocols used to connect to Exchange Online. In some cases, vendors are stepping up to the mark and making sure that clients switch easily over to modern authentication, with Apple’s project to upgrade mail app profiles being a notable example. Apparently, that’s going to happen when devices apply the iOS 15.6 upgrade.
It’s a while since I used an IMAP4 client with Exchange Online, so to test the OAuth 2.0 connection, I downloaded Thunderbird 102.0.2.
Thunderbird’s Azure AD App
The implementation to achieve OAuth 2.0 support is interesting. Like any app that depends on Graph permissions, Thunderbird needs to create a registered Azure AD. In turn, the service principal for the app can receive consent for the permissions needed to access Exchange Online with POP3 and IMAP4, and to send messages using SMTP. Michel de Rooij has a good write-up on how the OAuth flow works for Thunderbird. Essentially, you to open a browser and run a command to add the app identifier created by Thunderbird to your tenant. The command I used was:
Pass your tenant identifier (use the Get-MgOrganization cmdlet to get the identifier or look for it in the Azure AD admin center).
Pass the client identifier (app identifier) for the Thunderbird app. This is always 08162f7c-0fd2-4200-a84a-f25a4db0b584.
Prompt for consent.
When you create a registered app in Azure AD, you decide if the app is available in just your tenant or any organizational directory (any Microsoft 365 tenant). The app knows what permissions it needs to function, so when you run the command, you do two things:
Create an entry for the app in the tenant’s Azure AD.
Consent to the permissions needed by the app to run. As you can see from Figure 1, these are read and write access to mailboxes using IMAP4 and POP3. and send messages using SMTP AUTH. It’s best if an admin gives consent for an organization as this avoids the need for individual users to grant consent for the app to access their mailbox (if allowed by Azure AD settings).
Figure 1: Granting IMAP4 and POP3 permissions to the Thunderbird app
When these permissions are in place, users can follow the instructions to configure their client to use OAuth for authorization (Figure 2). The important thing is to use SSL/TLS with OAuth2 to fetch messages from Exchange Online and StartTLS and OAuth2 to send messages via SMTP.
Figure 2: IMAP4 settings for Thunderbird to connect to Exchange Online with OAuth 2.0
Guidance online (like these hints) offers some good suggestions like subscribing to folders in your Exchange Online mailbox to make them available to Thunderbird. It’s worth reading and passing to end users if they don’t already know this stuff.
SMTP AUTH Needed to Send Email
Everything works swimmingly. That is, if the mailbox is allowed to use SMTP AUTH to send messages. Usually, the IMAP4 connection works without a hitch and no problems are detected until the time comes to send messages, at which the server refuses to accept the message. Invariably, this is because the mailbox isn’t allowed to use SMTP AUTH. To fix the problem, run the Set-CasMailbox cmdlet to remove the block:
Once the block is lifted, mail should flow freely and you should have a happy IMAP4 user (Figure 3).
Figure 3: The Thunderbird IMAP4 client connected to Exchange Online
Connecting IMAP4 Clients to Exchange Online Might Need Upgrades
The Thunderbird implementation is smooth and should be easy for anyone to use. The difficulties I see are:
People who have old Thunderbird clients with configurations that use basic authentication. These folk won’t be able to connect to Exchange Online after Microsoft switches basic authentication off and will need to change their settings and potentially update their client. Before anything works, the tenant administrator must create the registered app and consent to the necessary permissions.
People who have other IMAP4 and POP3 clients where the app creator hasn’t produced an upgraded version to support OAuth 2.0. These people are out of luck and will need to adopt a different client.
With 78 days to go before October 1, it’s time to ensure that the IMAP4 clients to Exchange Online connection remains intact after basic authentication disappears. And while you’re at it, make sure that all your ActiveSync clients can too.
So much change, all the time. It’s a challenge to stay abreast of all the updates Microsoft makes across Office 365. Subscribe to the Office 365 for IT Pros eBook to receive monthly insights into what happens, why it happens, and what new features and capabilities mean for your tenant.
10 Replies to “Connecting IMAP4 Clients to Exchange Online with OAuth 2.0”
It’s also possible to switch over to using Owl for Exchange which is a paid-for addin but provides access to other features like the Address Book and Calendars (https://www.beonex.com/owl/)
Hi Tony,
Any clue on the way to get the job done with a shared MailBox ?
The fact is that the authentication dialog thrown via à browser window asks a valid email address, while the authentication string for a shared mailbox is something like “myaccount@my.co\my-shared.mailbox@my.co” … which is obviously not a valid e-mail address :/
I’ve struggled a bit these days, since OAuth2 is our only left option to use an MS365 account on ThunderBird/Linux :/
Have a nice day 🙂
Honestly, I’d use OWA to access a shared mailbox on whatever platform you use. I doubt that many client vendors have figured out how to resolve the permissions needed to access shared folders from regular IMAP4 clients.
Try as follows:
Email address:
When prompted to log in via web, click ‘Sign in as a different account’, then enter the login details for the mailbox which has delegated permissions.
Works for us in another OAuth product (Jira)
Sorry, that comment got a bit corrupted by WordPress:
Email address: shared.mailbox@example.com
When prompted to log in via web, click ‘Sign in as a different account’, then enter the login details for the mailbox which has delegated permissions (e.g firstname.lastname@example.com).
So I see the export option is now available to export Wikis from standard Teams channels. But what are we supposed to do for wikis in private or shared channels??
{"id":null,"mode":"button","open_style":"in_modal","currency_code":"EUR","currency_symbol":"\u20ac","currency_type":"decimal","blank_flag_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":100,"top_media_type":"featured_image","featured_image_url":"https:\/\/office365itpros.com\/wp-content\/uploads\/2022\/11\/cover-141x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Virtual Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"Office 365 for IT Pros","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"Office 365 for IT Pros","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for supporting the work of Office 365 for IT Pros!","payment_confirmation_title":"Office 365 for IT Pros","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}
It’s also possible to switch over to using Owl for Exchange which is a paid-for addin but provides access to other features like the Address Book and Calendars (https://www.beonex.com/owl/)
Hi Tony,
Any clue on the way to get the job done with a shared MailBox ?
The fact is that the authentication dialog thrown via à browser window asks a valid email address, while the authentication string for a shared mailbox is something like “myaccount@my.co\my-shared.mailbox@my.co” … which is obviously not a valid e-mail address :/
I’ve struggled a bit these days, since OAuth2 is our only left option to use an MS365 account on ThunderBird/Linux :/
Have a nice day 🙂
Honestly, I’d use OWA to access a shared mailbox on whatever platform you use. I doubt that many client vendors have figured out how to resolve the permissions needed to access shared folders from regular IMAP4 clients.
Try as follows:
Email address:
When prompted to log in via web, click ‘Sign in as a different account’, then enter the login details for the mailbox which has delegated permissions.
Works for us in another OAuth product (Jira)
Sorry, that comment got a bit corrupted by WordPress:
Email address: shared.mailbox@example.com
When prompted to log in via web, click ‘Sign in as a different account’, then enter the login details for the mailbox which has delegated permissions (e.g firstname.lastname@example.com).
Sorry, email address: shared.mailbox@mafint.org
So I see the export option is now available to export Wikis from standard Teams channels. But what are we supposed to do for wikis in private or shared channels??
Copy the content out of the wikis and paste into a Word document in the document library. That’s what I did.
Thanks Tony – (clearly I commented on the wrong post). I was hoping Microsoft had an alternative for those channels.