Coder Social home page Coder Social logo

mu4easy's Introduction

mu4easy

GNU Emacs MELPA

A global minor mode that defines a full working setup for mu4e and mbsync, based on mu 1.8+. Easily setup accounts and aliases from these providers: Google, Apple, GMX and Proton. Additional packages are installed and configured for a better experience, including mu4e-column-faces, mu4e-alert, org-msg and helm-mu. Some customizations are available, run (customize-group 'mu4easy).

Install locally and use the load-path variable, e.g.:

(use-package mu4easy
  :load-path "~/Code/mu4easy"
  :bind ("C-c u" . mu4e)
  :config (mu4easy-mode))

Or install with Melpa. Here is an example with one email account:

(use-package mu4easy
  :ensure t
  :bind ("C-c u" . mu4e)
  :config (mu4easy-mode)
  :custom
  (mu4easy-contexts '((mu4easy-context
                       :c-name  "Google"
                       :maildir "Gmail"
                       :mail    "[email protected]"
                       :smtp    "smtp.gmail.com"
                       :sent-action delete))))

See later more details on the mu4easy-context macro.

Make sure you have mu in your in PATH.

Comments and suggestions are welcome.

mbsync

The important part is to normalize all accounts to have the same structure, containing the folders Inbox, Archive, Sent, Trash, Drafts and Spam. I would advice against syncing the Drafts folder because it can lead to issues. If you decide not to sync it, just remove the relevant lines from the .mbsyncrc file.

Let’s go over each provider and examine the gotchas.

Google

IMAPAccount Gmail
Host imap.gmail.com
User [email protected]
PassCmd "gpg -q --for-your-eyes-only --no-tty -d ~/.authinfo.gpg | awk '/machine imap.gmail.com login [email protected]/ {print $NF}'"
AuthMechs LOGIN
SSLType IMAPS
SSLVersions TLSv1.2
CertificateFile /usr/local/etc/[email protected]/cert.pem

MaildirStore Gmail-local
Path ~/Mail/Gmail/
Inbox ~/Mail/Gmail/Inbox
SubFolders Verbatim

IMAPStore Gmail-remote
Account Gmail

Channel Gmail-inbox
Far :Gmail-remote:"INBOX"
Near :Gmail-local:"INBOX"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *

Channel Gmail-trash
Far :Gmail-remote:"[Gmail]/Trash"
Near :Gmail-local:"Trash"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *

Channel Gmail-spam
Far :Gmail-remote:"[Gmail]/Spam"
Near :Gmail-local:"Spam"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *
    
Channel Gmail-all
Far :Gmail-remote:"[Gmail]/All Mail"
Near :Gmail-local:"Archive"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *

Channel Gmail-drafts
Far :Gmail-remote:"[Gmail]/Drafts"
Near :Gmail-local:"Drafts"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *

Group Gmail
Channel Gmail-inbox
Channel Gmail-trash
Channel Gmail-all
Channel Gmail-spam
Channel Gmail-drafts

First is the PassCmd. I assume all passwords (and application specific passwords) are in ~/.authinfo.gpg with the password key-value pair last (see the NF variable in awk pointing to the last column).

Next, Google has the structure [Gmail]/... so we use explicit far/near definitions. We’ll drop them in the next providers.

Finally, unlike other providers, we’re not going to sync the Sent folders because Google is saving all email in the All Mails folders and you’ll end up with duplicates locally.

Apple

IMAPAccount Apple
Host imap.mail.me.com
PORT 993
User [email protected]
PassCmd "gpg -q --for-your-eyes-only --no-tty -d ~/.authinfo.gpg | awk '/machine imap.mail.me.com/ {print $NF}'"
AuthMechs LOGIN
SSLType IMAPS
SSLVersion TLSv1.2
CertificateFile /usr/local/etc/[email protected]/cert.pem

MaildirStore Apple-local
Path ~/Mail/Apple/
Inbox ~/Mail/Apple/Inbox
SubFolders Verbatim

IMAPStore Apple-remote
Account Apple

Channel Apple-all
Far :Apple-remote:
Near :Apple-local:
Patterns "INBOX" "Archive" "Trash" "Spam" "Drafts"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *
    
Channel Apple-sent
Far :Apple-remote:"Sent Messages"
Near :Apple-local:"Sent"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *

Group Apple
Channel Apple-sent
Channel Apple-all

Here we use the Patterns key to quickly select the folders we’re interested in. It turns the Sent folders has many conventions; at Apple it’s called Sent Messages.

GMX

IMAPAccount GMX
Host imap.gmx.com
User [email protected]
PassCmd "gpg -q --for-your-eyes-only --no-tty -d ~/.authinfo.gpg | awk '/machine imap.gmx.com login [email protected]/ {print $NF}'"
AuthMechs LOGIN
SSLType IMAPS
SSLVersion TLSv1.2
CertificateFile /usr/local/etc/[email protected]/cert.pem

MaildirStore GMX-local
Path ~/Mail/GMX/
Inbox ~/Mail/GMX/Inbox
SubFolders Verbatim

IMAPStore GMX-remote
Account GMX

Channel GMX
Far :GMX-remote:
Near :GMX-local:
Patterns "INBOX" "Archive" "Trash" "Spam" "Drafts" "Sent"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *

Proton

IMAPAccount Proton
Host 127.0.0.1
PORT 1111
User [email protected]
PassCmd "gpg -q --for-your-eyes-only --no-tty -d ~/.authinfo.gpg | awk '/machine 127.0.0.1/ {print $NF}'"
AuthMechs LOGIN
SSLType STARTTLS
SSLVersion TLSv1.2
CertificateFile /usr/local/etc/[email protected]/cert.pem

MaildirStore Proton-local
Path ~/Mail/Proton/
Inbox ~/Mail/Proton/Inbox
SubFolders Verbatim

IMAPStore Proton-remote
Account Proton

Channel Proton
Far :Proton-remote:
Near :Proton-local:
Patterns "INBOX" "Archive" "Trash" "Spam" "Drafts" "Sent"
CopyArrivalDate yes
Create Both
Expunge Both
SyncState *

In order to us Proton, one needs to install a bridge application. It specifies the IMAP and SMTP ports to use (non-standard).

mu4e

Let’s go over the important parts of the elisp code.

(setf (alist-get 'trash mu4e-marks)
      '(:char ("d" . "")
              :prompt "dtrash"
              :dyn-target (lambda (target msg) (mu4e-get-trash-folder msg))
              ;; Here's the main difference to the regular trash mark, no +T
              ;; before -N so the message is not marked as IMAP-deleted:
              :action (lambda (docid msg target)
                        (mu4e--server-move docid (mu4e--mark-check-target target) "+S-u-N"))))

I picked this code and realized that, at least for Google, if you flag a message trashed, it just disappears. This code instead flags the message as seen, removes the flags unseen and new and finally, moves it to the Trash folder, which is synced to the server and gets deleted according to a policy you control.

(cl-defmacro mu4easy-context (&key c-name maildir mail smtp
                                   (smtp-mail mail)
                                   (smtp-port 587)
                                   (smtp-type 'starttls)
                                   (sent-action 'sent)
                                   (name "Daniel Fleischer")
                                   (sig "Daniel Fleischer"))
  (let
      ((inbox      (concat "/" maildir "/Inbox"))  
       (sent       (concat "/" maildir "/Sent"))
       (trash      (concat "/" maildir "/Trash"))
       (refile     (concat "/" maildir "/Archive"))
       (draft      (concat "/" maildir "/Drafts")))
    
    `(make-mu4e-context
      :name ,c-name
      :match-func (lambda (msg)
                    (when msg
                      (string-match-p (concat "^/" ,maildir "/")
                                      (mu4e-message-field msg :maildir))))
      :vars '((user-mail-address . ,mail)
              (user-full-name . ,name)
              (mu4e-sent-folder . ,sent)
              (mu4e-drafts-folder . ,draft)
              (mu4e-trash-folder . ,trash)
              (mu4e-refile-folder . ,refile)
              (mu4e-compose-signature . (concat ,sig))
              (mu4e-sent-messages-behavior . ,sent-action)
              (smtpmail-smtp-user . ,smtp-mail)
              (smtpmail-starttls-credentials . ((,smtp ,smtp-port nil nil)))
              (smtpmail-auth-credentials . '((,smtp ,smtp-port ,smtp-mail nil)))
              (smtpmail-default-smtp-server . ,smtp)
              (smtpmail-smtp-server . ,smtp)
              (smtpmail-stream-type . ,smtp-type)
              (smtpmail-smtp-service . ,smtp-port)
              (org-msg-signature . ,sig)
              (mu4e-maildir-shortcuts . 
                                      ((,inbox   . ?i)
                                       (,sent    . ?s)
                                       (,trash   . ?t)
                                       (,refile  . ?a)
                                       (,draft   . ?d)))))))

That’s the macro to create contexts or identities. It’s assuming you have a consistent maildirs structure, like specified in the mbsync config, i.e. all account names are on a single level and then below them you have Inbox, Archive, Trash, Sent, Spam and Drafts for each one. To match the context I’m just looking at the maildir the message is in. Some defaults in the function are the SMTP encryption and what to do with sent messages (either delete them in the case of Google or save them in the Sent folder; more on that in the contexts examples).

Next there are some variables settings; these are set to taste, feel free to experiment with them. Next are the bookmarks, which are very convenient both for jumping and for reading the read/unread counts.

Tip: the bookmarks query can be either a function or a string. If it’s a function, there is no read/unread count. I’m using a string generated from a function; if you first eval the string and then set the variable, you do get counts.

For org-msg package users, notice that the package itself handles the signature, so you want to define org-msg-signature like I did in the macro. It accepts org formatting, e.g. *Daniel Fleischer*\n/Skynet Inc/ and then converts it into formatted HTML. Also, when using org-msg, reply style is top-posting so you need it to handle the signature correctly (above the replied text).

Another improvement is creating a customized link description; i.e. calling org-store-link to save a link to an email, it uses mu4easy-mail-link-description which will give a nice description of the form to/from: subject (ISO timestamp) - works with org-capture as well.

Added is a custom updating function that asks you which account to update, or by default updates all. It is bound to the usual “U”.

Finally, setting up the accounts, either using customization or using code:

(setq mu4easy-contexts
      
      '((mu4easy-context
         :c-name  "Google"
         :maildir "Gmail"
         :mail    "[email protected]"
         :smtp    "smtp.gmail.com"
         :sent-action delete)
        
        (mu4easy-context
         :c-name  "1-GMX"
         :maildir "GMX"
         :mail    "[email protected]"
         :smtp    "mail.gmx.com")
        
        (mu4easy-context
         :c-name    "2-GMX-alias"
         :maildir   "GMX"
         :mail      "[email protected]"
         :smtp      "mail.gmx.com"
         :smtp-mail "[email protected]")
        
        (mu4easy-context
         :c-name  "Apple"
         :maildir "Apple"
         :mail    "[email protected]"
         :smtp    "smtp.mail.me.com")
        
        (mu4easy-context
         :c-name  "3-Apple-alias"
         :maildir "Apple"
         :mail    "[email protected]"
         :smtp    "smtp.mail.me.com"
         :smtp-mail "[email protected]")
        
        (mu4easy-context
         :c-name    "Proton"
         :maildir   "Proton"
         :mail      "[email protected]"
         :smtp      "127.0.0.1"
         :smtp-type ssl
         :smtp-port 999)
        
        (mu4easy-context
         :c-name    "4-Proton-alias"
         :maildir   "Proton"
         :mail      "[email protected]"
         :smtp      "127.0.0.1"
         :smtp-mail "[email protected]"
         :smtp-type ssl
         :smtp-port 999)))

Important points:

  1. Jumping to contexts is based on their first (unique) letter, that’s why I’m using numbers in the c-name key.
  2. Google saves the sent messages in the All Mail (Archive) folder so it is recommended to set the corresponding mu4e setting to delete sent messages (locally). It’s only for Google; for the other account, sent messages are saved in the Sent folder.
  3. The 2-GMX account is an alias - not another GMX account (see the last comment). It has a different mail, but the SMTP authentication needs the real email address. The outgoing email still looks like it is coming from the alias.
  4. Proton account needs SSL encryption for SMTP, it connects to localhost and uses non-standard ports for IMAP and SMTP (check the Proton bridge app for details).
  5. If you have multiple accounts with the same providers, they should have different maildirs, e.g. ~/Mail/Gmail1/, ~/Mail/Gmail2/. Here I showed aliases, not multiple accounts.

Disclaimer

This setup is based upon a couple of weeks worth of tweaking, trial and error. It’s not perfect; some email were lost (those not saved into sent), lessons were learned. I didn’t try it with Microsoft-based emails. Make sure to test everything you do - to see that emails are going in and out, saved in Archive and Sent, compare the results with the web-based interface until you get comfortable using it 100% of the time. Or not.

mu4easy's People

Contributors

danielf-amobee avatar danielfleischer avatar vellvisher avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mu4easy's Issues

how do you quickly jump to your gmail sent items?

With this config where you don't sync the Sent folder for your gmail account (because it's already all available in the All Mail/Archive), how do you quickly jump to your sent emails for this account? Is there any way to set up the keyboard shortcut J-s to jump to the /Archive channel with a filter with something like from:?

Cheers! I'm not using the package directly but have manually configured everything according to your setup! (I wanted to understand what was going on, so I didn't want to rely on macro's for now).

Great job!

I still remember a few years ago I try to use emacs + mbsync to get emails from Google accounts. I took me a lot of time and it did not work well. Eventually I thought that dealing with emails in emacs is not a good idea, for this and other reasons.

Anyway, I'm still glad to see that this package can make things easier! I would be happy if I had this tool at that time.

mu4easy not being fully instantiated with 'use-package'

I've been using this package for a while, somehow I'm unable to setup this package so that it's run automatically when mu4e starts.

The behavior is such that the contexts seem to partially work (seems inconsistent, I couldn't pinpoint what's wrong with contexts), when composing message it only launches the default compose, without the org-msg or other configurations that I have.

My workaround is to toggle mu4easy-mode manually after mu4e launched.

I'm on doomemacs distro, emacs 29.1.

A good way to set bookmarks for Gmail maildir depending on context?

Hello,

Much thanks for sharing your configuration here, its really helped me set up mu4e.

I am using your context generating macro, which for most cases works fine, except for Gmail 'Archive' directories, which are stored in 'gmail/All Mail' maildir.

Thus, in a gmail account context, when pressing 'ja' maildir bookmark opens to non-existent 'gmail/Archive'.

I have tried something like this:

(defvar my/mu4e-context (mu4e-context-current))

(cl-defmacro.....
(if (string-match-p "1gmail\\|2gmail\\|3gmail" my/mu4e-context)
(let
      ((inbox      (concat "/" maildir "/Inbox"))
       (sent       (concat "/" maildir "/Sent"))
       (trash      (concat "/" maildir "/Trash"))
       (refile     (concat "/" maildir "/All Mail"))
       (draft      (concat "/" maildir "/Drafts"))))
 (let
      ((inbox      (concat "/" maildir "/Inbox"))
       (sent       (concat "/" maildir "/Sent"))
       (trash      (concat "/" maildir "/Trash"))
       (refile     (concat "/" maildir "/Archive"))
       (draft      (concat "/" maildir "/Drafts")))))

...rest of macro
)

However my programming skills are very poor and I am unable to get it to work.
Is there an way to go about this that you recommend?

"Wrong number of arguments: (3 . 3), 2" error

After creating the mu4easy-contexts in .emacs, I get the error "Wrong number of arguments: (3 . 3), 2" relating to the mu4easy-contexts-function. I've created two context-entries for accounts that I successfully synchronized with mbsync, though the error had already appeared when I had three contexts specified, the third being for a gmail account I couldn't synchronize. I've created all the folders specified in the readme, as some were not initialized because no mails were in them. I installed mu4easy through melpa.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.