Mailmerge with Microsoft OAuth authentication

Posted on January 26, 2026

mailmerge is a command line mail merge tool that supports the powerful jinja2 template engine for generating email content.

An example from the docs:

TO: {{email}}
SUBJECT: Testing mailmerge
FROM: My Self <myself@mydomain.com>
BCC: myself@mydomain.com

Hi, {{name}},

Your number is {{number}}.

This post explains how to send emails with mailmerge from a Microsoft email account, where password-based authentication is disabled. Instead, authentication uses OAuth, support for which I added to mailmerge in July 2023.

You will first need to install mailmerge by following these instructions.

Obtain authentication token from Microsoft

Now create an OAuth token using M365-IMAP.

Clone that M365-IMAP repository then cd into it.

Follow their README.md instructions, using the "Use Thunderbird’s public client ID" option as the client ID, i.e not the "Use your own Azure AD app registration" option. Then follow their instructions beneath "Obtaining auth tokens".

Once you have set this up, python3 get_token.py will create two short-lived files: imap_smtp_refresh_token and imap_smtp_access_token.

For mailmerge, you will run python3 refresh_token.py each time to create a new OAuth token as the password when prompted.

Steps for running mailmerge with OAuth

Step 1: Set up mailmerge

Run:

mailmerge --sample

then follow these instructions to edit the generated mailmerge_template.txt and mailmerge_database.csv files.

You then need to edit the mailmerge_server.conf file to tell mailmerge to use XOAUTH. You need to specify your username and your organisation's domain name for username:

[smtp_server]
host = smtp.office365.com
port = 587
security = XOAUTH
username = YOURUSERNAME@YOURDOMAIN.COM

Step 2: Create an OAuth token

Within your M365-IMAP directory run:

python3 refresh_token.py

Copy this token.

Step 3: Run mailmerge

Follow the mailmerge README to understand how to enable/disable dry runs and sending limits.

Once you are happy with the instantiated mail merge templates with --dry-run, run mailmerge to send emails to all recipients:

mailmerge --no-dry-run --no-limit

you will be asked for a password:

>>> password for YOURUSERNAME@YOURDOMAIN.COM on smtp.office365.com:

Paste the OAuth token from step 2 into the terminal window, and hit Enter. This should now send emails to recipients listed in your mailmerge_database.csv file.