# Mutt with OAuth2
contributed by < [`linD026`](https://github.com/linD026) >
###### tags: `kernel-tools`
---
:::success
**Source code**
* [gitlab/muttmua - mutt_oauth2.py](https://gitlab.com/muttmua/mutt/-/blob/master/contrib/mutt_oauth2.py)
* [gitlab/muttmua - mutt_oauth2.py.README](https://gitlab.com/muttmua/mutt/-/blob/master/contrib/mutt_oauth2.py.README)
**Tutorial**
* [Red Hat - mutt email oauth2](https://www.redhat.com/sysadmin/mutt-email-oauth2)
:::
## Google registration
> Reference : [mutt/contrib/mutt_oauth2.py.README](https://gitlab.com/muttmua/mutt/-/blob/master/contrib/mutt_oauth2.py.README#L163)
Go to console.developers.google.com, and create a new project. The name doesn't
matter and could be "mutt registration project".
- Go to **Library**, choose **Gmail API**, and enable it
- Hit left arrow icon to get back to console.developers.google.com
- Choose **OAuth Consent Screen**
- Choose Internal for an organizational G Suite
- Choose External if that's your only choice
- For Application Name, put for example "Mutt"
- Under scopes, choose Add scope, scroll all the way down, enable the "https://mail.google.com/" scope
- Fill out additional fields (application logo, etc) if you feel like it (will make the consent screen look nicer)
- Back at console.developers.google.com, choose Credentials
- At top, choose **Create Credentials / OAuth2 client iD**
- Application type is "**Desktop app**"
Edit the `client_id` (and `client_secret` if there is one) into the
`mutt_oauth2.py` script.
:::warning
**NOTE**
It needs to add the account to the `Test user` ( at "**OAuth consent screen::Test users**"").
Otherwise, we cannot get the code in [next step](##mutt_oauth2.py).
:::
---
## Gnu Privacy Guard (gpg)
```
$ gpg --gen-key
```
First, we set Name and Email. We can simply set Name as "**My mutt_oauth2 token store**" and let the email empty. It will generate:
```
igpg: /home/user/.gnupg/trustdb.gpg: trustdb created
gpg: key 2856933BAECE4525 marked as ultimately trusted
gpg: directory '/home/user/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/user/.gnupg/openpgp-revocs.d/BE294513C874525DE247E452428759334678E5C25.rev'
public and secret key created and signed.
pub rsa3072 2022-06-20 [SC] [expires: 2024-06-19]
BE29B13457465DE234E44122856933BAEC8E4525
uid My mutt_oauth2 token store
sub rsa3072 2022-06-20 [E] [expires: 2024-06-19]
```
---
## [mutt_oauth2.py](https://gitlab.com/muttmua/mutt/-/blob/master/contrib/mutt_oauth2.py)
> mutt_oauth2.py needs Python >= 3.7 to work.
After that, edit `mutt_oauth2.py`:
- From **gpg**
- `YOUR_GPG_IDENTITY`
- From **google**
- `client_id`
- `client_secret`
```
ENCRYPTION_PIPE = ['gpg', '--encrypt', '--recipient', 'My mutt_oauth2 token store']
DECRYPTION_PIPE = ['gpg', '--decrypt']
registrations = {
'google': {
'authorize_endpoint': 'https://accounts.google.com/o/oauth2/auth',
'devicecode_endpoint': 'https://oauth2.googleapis.com/device/code',
'token_endpoint': 'https://accounts.google.com/o/oauth2/token',
'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob',
'imap_endpoint': 'imap.gmail.com',
'pop_endpoint': 'pop.gmail.com',
'smtp_endpoint': 'smtp.gmail.com',
'sasl_method': 'OAUTHBEARER',
'scope': 'https://mail.google.com/',
'client_id': '10072841202637-j2bvitf3k3j12do40ja2dsjg9nigdasdec2.apps.googleusercontent.com',
'client_secret': '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oj',
},
```
Then, `export GPG_TTY=$(tty)`.
Now, we can excute the script:
```
$ ./mutt_oauth2.py user@gmail.com.tokens --verbose --authorize
```
Here is the first command, it will generate the tokens file.
Select `google`, `authcode`, and paste the code from the website.
When finished the command, it will have the access and refresh tokens.
:::success
**access token** will be expired.
So it needs the **refresh token** to get the access token.
:::
```
$ ./mutt_oauth2.py user@gmail.com.tokens --verbose --test
$ ./mutt_oauth2.py user@gmail.com.tokens --verbose --debug --test
```
For the debugging.
```
$ ./mutt_oauth2.py user@gmail.com.tokens
```
It will return the access token.
---
## Add to mutt config
```
set imap_authenticators="oauthbearer:xoauth2"
set imap_oauth_refresh_command="/path/to/script/mutt_oauth2.py /path/to/token/${imap_user}.tokens"
set smtp_authenticators=${imap_authenticators}
set smtp_oauth_refresh_command=${imap_oauth_refresh_command}
```
Then done. We can use Mutt to access gmail.
:::warning
**NOTE**
To fix the mutt cannot execute every reboot.
```
Authenticating (OAUTHBEARER)...You must run script with "--authorize" at least
```
You needs to specific the path:
```bash
./path/to/script/mutt_oauth2.py /path/to/token/${imap_user}.tokens
```
:::
---
## Some detail about Mutt
### tips
> For how to read emails in Mutt, see `help` ( press `?`).
> Like `<` and `>` can scroll up and down one line, `/` for searching the word, `q` for quit.
* Show the email you sent in Mutt.
* Enter `c` and `?`, then choose the `Gmail`, `All Mail` or other IMAP that have your email.
* Otherwise, you can just cc yourself when you are sending the email.
* When you want to reply all the address, plesse use `g` for group reply (reply all).
* Save the email to the local file. Hit `v` to open the attachments and `s` to save.
### My configuration
```
set imap_user = 'user@gmail.com'
set imap_pass = ''
set spoolfile = imaps://imap.gmail.com/INBOX
set folder = imaps://imap.gmail.com/
# Do NOT save sent messages on the server.
# If your client is sending mail through Gmail's SMTP server,
# your sent messages will be automatically copied to
# the [Gmail]/Sent Mail folder.
set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
# disable mutt's storing of all sent mail
set copy = no
set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
# ================ oauth2 ====================
set imap_authenticators="oauthbearer:xoauth2"
set imap_oauth_refresh_command="~/.mutt/mutt_oauth2.py ~/.mutt/${imap_user}.tokens"
set smtp_authenticators=${imap_authenticators}
set smtp_oauth_refresh_command=${imap_oauth_refresh_command}
# ================ No authenticators available - BUG ===============
# With Homebrew in MacOS
set smtp_authenticators = 'gssapi:login'
# ================ SMTP ====================
set smtp_url = "smtp://user@smtp.gmail.com:587/"
set smtp_pass = ${imap_pass}
set ssl_force_tls = yes # Require encrypted connection
# ================ Composition ====================
set editor = "vim"
set edit_headers = yes # See the headers when editing
set charset = UTF-8 # value of $LANG; also fallback for send_charset
# Sender, email address, and sign-off line must match
unset use_domain # because joe@localhost is just embarrassing
set realname = "MY-NAME"
set from = "user@gmail.com"
set use_from = yes
set crypt_replysign = yes
set crypt_verify_sig = yes
# ============== Mail ================
set sort=threads
set timeout=10
# ============== Color ===============
color normal white default
color attachment brightyellow default
color hdrdefault cyan default
color indicator black cyan
color markers brightred default
color quoted green default
color signature cyan default
color status brightgreen blue
color tilde blue default
color tree red default
color index red default ~P
color index red default ~D
color index magenta default ~T
color header brightgreen default ^From:
color header brightcyan default ^To:
color header brightcyan default ^Reply-To:
color header brightcyan default ^Cc:
color header brightblue default ^Subject:
color body brightred default [\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+
# identifies email addresses
color body brightblue default (https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+
# identifies URLs
```
## More easy way to do it
Set application password to `imap_pass`.
You can set the password in https://myaccount.google.com/security .
Then, here you go. :)
:::warning
**NOTE**
With Homebrew, you need to add following setting to avoid ` No authenticators available` problem.
```
set smtp_authenticators = 'gssapi:login'
```
> From https://github.com/Homebrew/legacy-homebrew/issues/33419
:::
---
## Fix your mutt
https://lwn.net/Articles/924822/