Skip to content

Instantly share code, notes, and snippets.

@A6GibKm
Last active April 21, 2024 12:13
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save A6GibKm/238b754a4a90051f60906b9efa3e8000 to your computer and use it in GitHub Desktop.
Save A6GibKm/238b754a4a90051f60906b9efa3e8000 to your computer and use it in GitHub Desktop.
Read your emails with mu4e

Connecting emacs and Protonmail Bridge

This guide will cover the basics on how to integrate emacs with protonmail-bridge using

Configuring mbsync

Create a configuration file ~/.mbsyncrc for mbsync

IMAPAccount protonmail
Host 127.0.0.1
Port 1143
PassCmd "gpg -q --for-your-eyes-only --no-tty -d ~/.authinfo.gpg | awk 'FNR == 1 {print $8}'"
SSLType STARTTLS
SSLVersions TLSv1.2
CertificateFile ~/.config/protonmail/bridge/cert.pem

IMAPStore remote
Account protonmail

#You can change .mail to something else
MaildirStore local
Path ~/.mail/
Inbox ~/.mail/INBOX/

Channel inbox
Master :remote:
Slave :local:
Patterns * 
Create Both
Expunge Both
SyncState *

Group protonmail
Channel inbox

(Alternative to mbsync) Using offlineimap

Alternatively install offlineimap with the following config at ~/.offlineimaprc

# ~/.offlineimaprc

[general]
accounts = protonmail
pythonfile = ~/.config/offlineimap/keyring.py
metadata = ~/.cache/offlineimap

[Account protonmail]
remoterepository = protonmail-remote
localrepository = protonmail-local

[Repository protonmail-local]
type = Maildir
localfolders = ~/.mail
sync_deletes = no

[Repository protonmail-remote]
expunge = yes
type = IMAP
remotehost = 127.0.0.1
remoteport= 1143
remoteuser = USERNAME@protonmail.com
remotepasseval = get_password("USERNAME@protonmail.com")
# Alternatively, use
# remotepass = <YOUR BRIDGE-SPECIFIC PASSWORD>
nametrans = lambda foldername: re.sub ('^Folders.', '', foldername)
folderfilter = lambda foldername: foldername not in ['All Mail']
ssl = no # ssl is broken.
starttls = yes
ssl_version = tls1_2
sslcacertfile = ~/.config/protonmail/bridge/cert.pem

Where one possible script is

#!/usr/bin/env python3
# ~/.config/offlineimap/keyring.py

import re
import os


def get_password(login):
    machine = "127.0.0.1"
    port = "1143"
    s = "machine %s port %s login %s password ([^ ]*)\n" % (
        machine,
        port,
        login,
    )
    p = re.compile(s)
    authinfo = os.popen(
        "gpg -q --no-tty -d ~/.authinfo.gpg"
    ).read()
    return p.search(authinfo).group(1)

Note: offlineimap depends on deprecated Python 2.7.

Logging credentials

Next we need to create a file to log our credentials for sending mail with smtpmail. Create a file ~/.authinfo with the following contents

machine 127.0.0.1 port 1143 login USERNAME@protonmail.com password BRIDGE_PASSWORD
machine 127.0.0.1 port 1025 login USERNAME@protonmail.com password BRIDGE_PASSWORD

You should encrypt it, one option is to use epa in emacs M-x epa-encrypt-file. Another is to set a symmetric encryption that will require some password $ gpg --symmetric .authinfo. Finally delete .authinfo.

Now to get/sync you mail, run on a terminal $ mbsync protonmail.

Configuring mu4e

This is a minimal configuration that you should include in your init.el configuration file.

(require 'mu4e)

(setq mu4e-maildir "~/.mail"
mu4e-attachment-dir "~/Downloads")

(setq user-mail-address "USERNAME_HERE@protonmail.com"
user-full-name  "YOUR_NAME")

;; Get mail
(setq mu4e-get-mail-command "mbsync protonmail"
mu4e-change-filenames-when-moving t   ; needed for mbsync
mu4e-update-interval 120)             ; update every 2 minutes

;; Send mail
(setq message-send-mail-function 'smtpmail-send-it
smtpmail-auth-credentials "~/.authinfo.gpg"
smtpmail-smtp-server "127.0.0.1"
smtpmail-stream-type 'starttls
smtpmail-smtp-service 1025)

(add-to-list 'gnutls-trustfiles (expand-file-name "~/.config/protonmail/bridge/cert.pem"))

To index your emails from the terminal run mu index --maildir=~/.mail

Now just launch M-x mu4e from emacs to read your mail.

@marvhus
Copy link

marvhus commented Feb 9, 2024

I'm not entirely sure how to do a pull request on a Gist, but I fixed a typo, and you can see the fix in my fork.

I essentially changed gpg --symetric .authinfo to gpg --symmetric .authinfo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment