# 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/