So if you used to have an offline mail setup for your ETH mail, you probably know that they decided to change their mail system a couple of months ago. Not only did this change break my old, pretty standard, setup, and as far as I know, they made the change overnight without giving a heads-up.
Since then, I have had to use the Outlook webmail client, which, other than being proprietary software, is not ideal1. But since I rarely sent emails, it wasn't such a big issue. However, when looking for a thesis project, sending many emails is unavoidable, so working with Outlook started to get more and more annoying.
I recently found a blog post that talked about setting up Isync and Msmtp for Office365's OAUTH2 mail, which covers most of the stuff I needed, but some Home Manager/Nix specific things were not covered.
Setting up OAUTH2
I will assume you already have a GPG key, otherwise see the official docs.
First, Copy the mutt_oauth2
script from
Mutt's repo
and placed it in a file named mutt_oauth2
.
Then in a Home Manager-managed file in the same directory, put the
following.
{
home.packages = [
(pkgs.writers.writePython3Bin "mutt_oauth2" {
flakeIgnore = [ "E501" "E265" "F401" "E226" "W504" ];
}(builtins.readFile ./mutt_oauth2.py))
];
}
Before switching to a new generation, you have to edit the mutt_oauth2
file. In the ENCRYPTION_PIPE
variable, put in the mail
address of your GPG key, which you will use to decrypt and encrypt your
OAUTH token (see later).
= ['gpg', '--encrypt', '--recipient', '<>'] ENCRYPTION_PIPE
Then in the microsoft
section of registrations
, do
'client_id': '08162f7c-0fd2-4200-a84a-f25a4db0b584',
'client_secret': 'TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82',
Don't ask me why this is needed.
Now create an OAUTH2 token with the mutt_oauth2
script
$ mutt_oauth2 -t </path/to/oauth/token> --authorize
# write "microsoft" for the first question
# "localhostauthcode" for the second
# <username>@ethz.ch for the third
I would recommend putting the token file in your pass store, if you use pass.
Isync
Isync doesn't have support for OAUTH2 by default, so we install an additional package and override the default Isync package.
{
home.packages = [
pkgs.cyrus-sasl-xoauth2]
{
programs.mbsync = enable = true;
package = (pkgs.isync.override { withCyrusSaslXoauth2 = true; });
};
}
For the accounts.email.accounts.<username>
part
(you might want to adjust some of these to your preference; consult the
Man page for details)
{
accounts.email.accounts = {
username> = rec {
<address = "xingchen@student.ethz.ch";
maildir = {
path = "</some/path>";
};
folders = {
inbox = "";
};
userName = "<username>";
realName = "<name>";
passwordCommand = "mutt_oauth2 -t </path/to/oauth/token>";
imap = {
host = "outlook.office365.com";
port = 993;
tls = {
enable = true;
};
};
mbsync = {
enable = true;
create = "both";
expunge = "both";
subFolders = "Maildir++";
remove = "imap";
patterns = [ "*" ];
extraConfig = {
account = {
User = "<username>@ethz.ch";
AuthMechs = "XOAUTH2";
};
channel = {
SyncState = "*";
}
};
};
};
};
} # Who said only Lisp has many brackets?
Msmtp
The Msmtp part is the simplest, simply add the following.
{
programs.msmtp.enable = true;
accounts.email.accounts = {
username> = rec {
<smtp = {
host = "outlook.office365.com";
port = 587;
tls = {
enable = true;
};
};
msmtp.extraConfig = {
protocol = "smtp";
tls = "on";
tls_starttls = "on";
auth = "xoauth2";
user = "<username>@ethz.ch";
passwordeval = "mutt_oauth2 -t </path/to/oauth/token>";
};
};
};
}
Now you should be able to fetch and send your ETH mails!