Skip to content

Latest commit

 

History

History
609 lines (482 loc) · 25.9 KB

gnus-guide-en.org

File metadata and controls

609 lines (482 loc) · 25.9 KB

Practical guide to use Gnus with Gmail

Author: Chen Bin (redguardtoo)

Version: 20160730

Updated: <2016-08-05 Fri>

Created: <2012-10-12 Mon>

Copyright: This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Introduction

Gnus is a nice email client.

But many newbies get lost in its features. It would be much easier if they learned the essential 5% features and ignore the remaining 95% at the beginning.

So here is my guide on the 5%.

Why (OPTIONAL)

  • Gnus is solid
  • Works on all platforms
  • Less hardware resource required
  • Mail search and filter is great
  • Bundled with Emacs, no extra installation needed
  • Usable when offline. Check the “offline” part in the section “Advanced tips”
  • powerful combined with other plugins like yasnippet

Quick start

Requirements and conventions

A little homework before we start,

  • This guide applies to Emacs24+
  • You need install GnuTLS and OpenSSH on Linux/Mac/Window(Cygwin)
  • C means Ctrl and M means Alt. For example, M-x means pressing Alt and x together.
  • M-x mycommand means pressing Alt and x, input “mycommand”, and press Enter key.
  • RET means Enter key.
  • Group means mail folder.
  • Group buffer means the list of folders.
  • Summary buffer means the list of mails.

Sample setup

Either check http://www.emacswiki.org/emacs/GnusGmail or use my setup at the end of this article.

Usage

M-x gnus and Gnus will load ~/.gnus.el. Usually we place all our setup code in ~/.gnus.el instead of ~/.emacs because libraries required by .gnus.el will be automatically loaded.

You will come to the “Group Buffer” window. The “Group Buffer” lists the mail folders. In Gnus, the folder is called “Group”. By default, the folders are invisible!

Please subscribe the groups to make it visible. For example, INBOX is named “nnimap+gmail:INBOX” in “Group Buffer” and it’s invisible at the beginning!. I admit it’s confusing.

Check section “Subscribe groups” for details.

At minimum, you need subscribe INBOX group. But after subscribing the INBOX is still invisible if INBOX contains NO unread mails. Yes, I agree with you this makes no sense for a modern email client!

You can C-u 5 M-x gnus-group-list-all-groups to solve this problem.

You can insert below code into ~/.gnus to create hotkey o for C-u 5 M-x gnus-group-list-all-groups :

(defun my-gnus-group-list-subscribed-groups ()
  "List all subscribed groups with or without un-read messages"
  (interactive)
  (gnus-group-list-all-groups 5))

(define-key gnus-group-mode-map
  ;; list all the subscribed groups even they contain zero un-read messages
  (kbd "o") 'my-gnus-group-list-subscribed-groups)

In the “Group Buffer”, you can enter a folder by pressing RET. But I strongly suggest C-u RET because you intend to see all the mails instead of unread mails.

In the folder, you are viewing “Summary Buffer” which is, as I said before, the list of your mails.

Now it’s simple. Press RET to see the mail. Press q to quit “Summary Buffer”.

In short, “Group Buffer” lists mail folders. “Summary Buffer” lists mails in one folder.

That’s all you need to know. You could go to section “My Gnus configuration (for Gmail)” to use Gnus now without reading remaining sections.

Essential 5%

Don’t memorize all key bindings. Only pick up what you actually use instead.

At the end of this article, I’ve provided my Hydra setup so you actually don’t need remembering key binding any more.

Please see section “Use Hydra to avoid remembering key bindings” for more details.

Search mails

Search mails on Server

Press G G or M-x gnus-group-make-nnir-group to search mails at server side in “Group Buffer”.

You can press # to mark the groups. Search will be limited to marked groups. M-# to un-mark.

If no group marked, the group under cursor is searched.

Place the cursor before the first group, all groups will be searched.

To search certain fields in the mail, press C-u G G or C-u M-x gnus-group-make-nnir-group instead. This is a very useful technique.

You can apply more advanced search syntax by:

  • Press C-u G G or C-u M-x gnus-group-make-nnir-group
  • Input query statements, press Enter
  • Type “imap”, press Enter

Search mails locally

Press / / to limit the mails by subject at “Summary Buffer”. “Limiting” means filtering mails locally.

Press / a to limit the mails by author at “Summary Buffer”.

/ w to cancel the current filter.

You can apply the limits sequentially and cancel them in reverse order by pressing / w.

“Limiting” is cool. See http://www.gnu.org/software/emacs/manual/html_mono/gnus.html#Limiting for more Limiting tricks.

You can also see http://sachachua.com/blog/2008/05/emacs-gnus-searching-mail/ for technical details.

Subscribe groups

Press A A or M-x gnus-group-list-active in “Group Buffer” to fetch groups at all connected server. It take a while. I suggest pressing “L” to use local cache instead after A A once.

After A A or L, press u to subscribe/unsubscribe specific group.

In order to see all the mails in “INBOX” folder/group, you need MANUALLY subscribe the group “INBOX”!

Pressing o is much better. It is the hotkey I created for C-u 5 M-x gnus-group-list-all-groups, as mentioned in previous sections.

Press g or M-x gnus-group-get-new-news to refresh groups list.

You can also subscribe programmatically in ~/.gnus.el once per emacs session:

(defvar gnus-subscribe-groups-done nil
  "Only subscribe groups once.  Or else Gnus will NOT restart.")
(unless gnus-subscribe-groups-done
  (gnus-subscribe-hierarchically "nnimap+hotmail:Inbox")
  (setq gnus-subscribe-groups-done t))

Reply email

Press R or M-x gnus-summary-reply-with-original to reply with quoted text. Press r or M-x gnus-summary-reply to reply without quoted text.

Press S W (capitalized S then capitalized W) or =M-x gnus-summary-wide-reply-with-original=to reply all with quoted text. It’s called “wide reply” in Emacs.

Press S w or M-x gnus-summary-wide-reply to reply all without quoted text.

Compose new email

Press m or M-x gnus-new-mail in “Summary Buffer”.

You could also C-x m or M-x compose-mail anywhere in Emacs without bugging Gnus.

Re-send as new mail

Press S D e or M-x gnus-summary-resend-message-edit. Useful if you re-send mail in Draft folder.

Attach a file

Press C-c C-a or M-x mml-attach-file.

The attached file is actually plain text embedded in mail body. You can copy and modify the text.

Save attachment

Move focus over the attachment and press o or M-x gnus-mime-save-part. See ”Using Mime” in Emacs manual for details.

Open attachment

Move focus over the attachment and press Enter or M-x gnus-article-press-button.

The variable =mailcap-mime-data defines what program is used to open the attachment.

You can tweak the variable at Window or OSX directly.

At Linux, I press M-x mailcap-parse-mailcaps to load data from ~/.mailcap into mailcap-mime-data instead of tweaking mailcap-mime-data.

My ~/.mailcap:

# url
text/html; w3m -I %{charset} -T text/html; copiousoutput;

# image viewer
image/*; feh -F -d -S filename '%s';

# pdf
application/pdf; zathura '%s';
image/pdf; zathura '%s'

# video
video/* ; mplayer '%s'
audio/* ; mplayer '%s'

# Office files.
application/msword; soffice '%s'
application/rtf; soffice '%s'
text/richtext; soffice '%s'
application/vnd.ms-excel; soffice '%s'
application/vnd.ms-powerpoint; soffice '%s'

Send email

Press C-c C-c or M-x message-send-and-exit.

Refresh “Summary Buffer” (check new mails)

Press / N or M-x gnus-summary-insert-new-articles.

Make all mails visible (IMPORTANT)

Press C-u RET on the selected group in “Group Buffer”, or C-u M-g in “Summary Buffer”.

That’s the most important part of this article! By default, Gnus only displays unread mails.

Check http://stackoverflow.com/questions/4982831/i-dont-want-to-expire-mail-in-gnus for details.

Forward mail

Press C-c C-f or M-x gnus-summary-mail-forward in “Summary Buffer”.

You can mark multiple mails to forward (hotkey is “#”) and forward them in one mail. Holger Schauer provided the tip.

After the forwarded email is created, you may copy the body of that email without sending it. The copied content could be inserted into new mail.

Mark mails as read

Press c either in “Summary Buffer” or “Group Buffer”. This is my most frequently used command which it’s superior to Google’s own UI!

Tree view of mail folders

Group Topics is used to re-organize the mail folder into tree view.

For example, you can place mail folders from Gmail into “gmail” topic, mails from Outlook.com into “hotmail” topic, place “gmail” and “hotmail” under root topic “Gnus”.

The setup is only one line,

(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)

After setup, you can read its official manual to learn its commands to organize mail folders manually.

It’s tiresome to do this folder organizing thing again and again on different computers.

So you’d better save all the trouble and use my way instead.

All you need to do is to insert below code into ~/.gnus.el and you are done,

(eval-after-load 'gnus-topic
  '(progn
     (setq gnus-message-archive-group '((format-time-string "sent.%Y")))
     (setq gnus-topic-topology '(("Gnus" visible)
                                 (("misc" visible))
                                 (("hotmail" visible nil nil))
                                 (("gmail" visible nil nil))))

     ;; Please not the key of topic is specified in my sample setup
     (setq gnus-topic-alist '(("hotmail" ; the key of topic
                               "nnimap+hotmail:Inbox"
                               "nnimap+hotmail:Drafts"
                               "nnimap+hotmail:Sent")
                              ("gmail" ; the key of topic
                               "INBOX"
                               "[Gmail]/Sent Mail"
                               "Drafts")
                              ("misc" ; the key of topic
                               "nnfolder+archive:sent.2015-12"
                               "nnfolder+archive:sent.2016"
                               "nndraft:drafts")
                              ("Gnus")))))

Instead remembering topic commands, editing above snippet is more straightforward. The only requirement is a little bit of Emacs Lisp knowledge.

The flag gnus-message-archive-group defines local archive folder of sent mails. By default new folder is created monthly. My setup creates the folder yearly.

Advanced tips

Windows?

It’s 100% usable if you install Cygwin at first.

Gnus from Cygwin version of Emacs works out of the box.

Native Emacs for Windows need a little setup:

  • Right-click “My Computer” and go to “Properties -> Advanced -> Environmental Variables”
  • Setup user variables which does not require Administrator right
  • Set the variable “HOME” to the parent directory of your “.emacs.d” directory
  • Set the variable “PATH” to the “C:\cygwin64\bin”. I suppose Cygwin is installed at driver C.
  • Install GnuTLS and OpenSSH through Cygwin package manager

Outlook?

Exchange/Outlook users could read my post http://blog.binchen.org/posts/how-to-get-email-from-exchange-server-without-outlook.html.

You need one portable Java program Davmail. That’s enough in 99% companies. But if your Administrator is evil, you need use EWSEditor for once.

Auto-complete mail address

Install BBDB through melpa. It is a email address database written in Emacs Lisp.

You can always use M-x bbdb-complete-name and M-x bbdb-complete-mail provided by BBDB.

But there are another two better plugins based on BBDB (so you still need install BBDB at first):

You only need one of them.

Synchronize from Gmail contacts

Please,

Other plugins are strict on versions of BBDB. Mine doesn’t have such issue.

Customize “From” field

Easiest solution is to switch the FROM field dynamically by M-x toggle-mail-from-field:

(defun toggle-mail-from-field ()
  (interactive)
  (cond
   ((string= "[email protected]" user-mail-address)
    (setq user-mail-address "[email protected]"))
   (t
    (setq user-mail-address "[email protected]")))
  (message "Mail FROM: %s" user-mail-address))

A more complex solution is setup FROM field by the computer you are using:

;; (getenv "HOSTNAME") won't work because $HOSTNAME is not an env variable
;; (system-name) won't work because my /etc/hosts has some weird setup in office
(setq my-hostname (with-temp-buffer
        (shell-command "hostname" t)
        (goto-char (point-max))
        (delete-char -1)
        (buffer-string)))

(defun at-office ()
  (interactive)
  (and (string= my-hostname "my-sydney-workpc")
       (not (or (string= my-hostname "homepc")
                (string= my-hostname "eee")))))

(setq user-full-name "My Name"
      user-mail-address (if (at-office) "[email protected]" "[email protected]"))

Please note,

  • Command line program hostname is better than Emacs function (system-name)
  • I works on several computers which do not belong to me, so I cannot change /etc/hosts which (system-name) try to access
  • Please verify your email address at Gmail if you use Google’s SMTP server

Classify email

Popfile.

You may think Google Inbox equals to Popfile. Trust me, it’s not. You only need Popfile!

Popfile is open sourced. The data is stored locally with my full control. For example, the algorithm trained by Gmail can be used to classify mails from Microsoft Exchange Mail Server.

Check http://blog.binchen.org/posts/use-popfile-at-linux.html for details.

The command I use to start popfile,

cd ~/bin/popfile/ && perl popfile.pl

Write HTML mail

Use org-mime.

Usage is simple. Write mail in org format and M-x org-mime-htmlize.

Please use my patched org-mime which supports Emacs 24.

Read HTML mail

Install w3m and emacs-w3m.

Then insert below code into ~/.emacs,

(setq mm-text-html-renderer 'w3m)

If we don’t specify the w3m as html render, Emacs will use its built in browser shr to render HTML.

I prefer w3m to shr because w3m is more powerful and available on all platforms.

Read mail offline

Go to the “Summary Buffer”.

You need mark the mails by pressing ! or M-x gnus-summary-tick-article-forward.

The marked mails enter the disk cache. They can be read offline.

M-x gnus-summary-put-mark-as-read to remove the cached mail.

You also need insert below code into ~/.emacs,

(setq gnus-use-cache t)

Above code uses the cache to the full extent by “wasting” tens of megabytes of disk space.

The disk cache is located at “~/News/cache/”. You can back it up with GitHub private repository.

Multiple accounts

You only need copy the code containing “gnus-secondary-select-methods” from my setup.

Here is a sample setup,

(add-to-list 'gnus-secondary-select-methods
             '(nnimap "gmail-second"
                      (nnimap-address "imap.gmail.com")
                      (nnimap-server-port 993)
                      (nnimap-stream ssl)
                      (nnir-search-engine imap)
                      ; @see http://www.gnu.org/software/emacs/manual/html_node/gnus/Expiring-Mail.html
                      ;; press 'E' to expire email
                      (nnmail-expiry-target "nnimap+gmail:[Gmail]/Trash")
                      (nnmail-expiry-wait 90)))

gnus-secondary-select-methods is the list of your email accounts.

The information of multiple accounts is stored at ~/.authinfo.gpg.

Why Gnus displays more mails than Gmail

Gnus counts by individual mail. Gmail count by mail thread.

Subscribe “[Gmail]/Sent Mail” folder

So you can see your sent mails in Gnus.

Reconnect mail server

Press M-x gnus-group-enter-server-mode to go into server list.

Move the cursor to the offline server and M-x gnus-server-open-server.

Use Hydra to avoid remembering key bindings

  • Install Hydra through http://melpa.org/
  • Insert below code into ~/.emacs. Then press C-c C-y when composing mail. Press y in other modes
(eval-after-load 'gnus-group
  '(progn
     (defhydra hydra-gnus-group (:color blue)
       "Do?"
       ("a" gnus-group-list-active "REMOTE groups A A")
       ("l" gnus-group-list-all-groups "LOCAL groups L")
       ("c" gnus-topic-catchup-articles "Read all c")
       ("G" gnus-group-make-nnir-group "Search server G G")
       ("g" gnus-group-get-new-news "Refresh g")
       ("s" gnus-group-enter-server-mode "Servers")
       ("m" gnus-group-new-mail "Compose m OR C-x m")
       ("#" gnus-topic-mark-topic "mark #")
       ("q" nil "cancel"))
     ;; y is not used by default
     (define-key gnus-group-mode-map "y" 'hydra-gnus-group/body)))

;; gnus-summary-mode
(eval-after-load 'gnus-sum
  '(progn
     (defhydra hydra-gnus-summary (:color blue)
       "Do?"
       ("n" gnus-summary-insert-new-articles "Refresh / N")
       ("f" gnus-summary-mail-forward "Forward C-c C-f")
       ("!" gnus-summary-tick-article-forward "Mail -> disk !")
       ("p" gnus-summary-put-mark-as-read "Mail <- disk")
       ("c" gnus-summary-catchup-and-exit "Read all c")
       ("e" gnus-summary-resend-message-edit "Resend S D e")
       ("R" gnus-summary-reply-with-original "Reply with original R")
       ("r" gnus-summary-reply "Reply r")
       ("W" gnus-summary-wide-reply-with-original "Reply all with original S W")
       ("w" gnus-summary-wide-reply "Reply all S w")
       ("#" gnus-topic-mark-topic "mark #")
       ("q" nil "cancel"))
     ;; y is not used by default
     (define-key gnus-summary-mode-map "y" 'hydra-gnus-summary/body)))

;; gnus-article-mode
(eval-after-load 'gnus-art
  '(progn
     (defhydra hydra-gnus-article (:color blue)
       "Do?"
       ("f" gnus-summary-mail-forward "Forward")
       ("R" gnus-article-reply-with-original "Reply with original R")
       ("r" gnus-article-reply "Reply r")
       ("W" gnus-article-wide-reply-with-original "Reply all with original S W")
       ("o" gnus-mime-save-part "Save attachment at point o")
       ("w" gnus-article-wide-reply "Reply all S w")
       ("q" nil "cancel"))
     ;; y is not used by default
     (define-key gnus-article-mode-map "y" 'hydra-gnus-article/body)))

(eval-after-load 'message
  '(progn
     (defhydra hydra-message (:color blue)
       "Do?"
       ("ca" mml-attach-file "Attach C-c C-a")
       ("cc" message-send-and-exit "Send C-c C-c")
       ("q" nil "cancel"))
     (global-set-key (kbd "C-c C-y") 'hydra-message/body)))

My setup

This setup requires Emacs 24.3 at minimum.

My ~/.gnus.el,

(require 'nnir)

;; @see http://www.emacswiki.org/emacs/GnusGmail#toc1
(setq gnus-select-method '(nntp "news.gmane.org")) ;; if you read news groups

;; ask encryption password once
(setq epa-file-cache-passphrase-for-symmetric-encryption t)

;; @see http://gnus.org/manual/gnus_397.html
(add-to-list 'gnus-secondary-select-methods
             '(nnimap "gmail"
                      (nnimap-address "imap.gmail.com")
                      (nnimap-server-port 993)
                      (nnimap-stream ssl)
                      (nnir-search-engine imap)
                      ; @see http://www.gnu.org/software/emacs/manual/html_node/gnus/Expiring-Mail.html
                      ;; press 'E' to expire email
                      (nnmail-expiry-target "nnimap+gmail:[Gmail]/Trash")
                      (nnmail-expiry-wait 90)))

;; OPTIONAL, the setup for Microsoft Hotmail
(add-to-list 'gnus-secondary-select-methods
             '(nnimap "hotmail"
                      (nnimap-address "imap-mail.outlook.com")
                      (nnimap-server-port 993)
                      (nnimap-stream ssl)
                      (nnir-search-engine imap)
                      (nnmail-expiry-wait 90)))

(setq gnus-thread-sort-functions
      '((not gnus-thread-sort-by-date)
        (not gnus-thread-sort-by-number)))

; NO 'passive
(setq gnus-use-cache t)

;; BBDB: Address list
(add-to-list 'load-path "/where/you/place/bbdb/")
(require 'bbdb)
(bbdb-initialize 'message 'gnus 'sendmail)
(add-hook 'gnus-startup-hook 'bbdb-insinuate-gnus)
(setq bbdb/mail-auto-create-p t
      bbdb/news-auto-create-p t)

;; auto-complete emacs address using bbdb UI
(add-hook 'message-mode-hook
          '(lambda ()
             (flyspell-mode t)
             (local-set-key "<TAB>" 'bbdb-complete-name)))

;; Fetch only part of the article if we can.
;; I saw this in someone's .gnus
(setq gnus-read-active-file 'some)

;; open attachment
(eval-after-load 'mailcap
  '(progn
     (cond
      ;; on OSX, maybe change mailcap-mime-data?
      ((eq system-type 'darwin))
      ;; on Windows, maybe change mailcap-mime-data?
      ((eq system-type 'windows-nt))
      (t
       ;; Linux, read ~/.mailcap
       (mailcap-parse-mailcaps)))))

;; Tree view for groups.
(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)

;; Threads!  I hate reading un-threaded email -- especially mailing
;; lists.  This helps a ton!
(setq gnus-summary-thread-gathering-function 'gnus-gather-threads-by-subject)

;; Also, I prefer to see only the top level message.  If a message has
;; several replies or is part of a thread, only show the first message.
;; `gnus-thread-ignore-subject' will ignore the subject and
;; look at 'In-Reply-To:' and 'References:' headers.
(setq gnus-thread-hide-subtree t)
(setq gnus-thread-ignore-subject t)

;; Personal Information
(setq user-full-name "My Name"
      user-mail-address "[email protected]")

;; Read HTML mail
;; You need install the command line web browser 'w3m' and Emacs plugin 'w3m'
(setq mm-text-html-renderer 'w3m)

;; Setup to send email through SMTP
(setq message-send-mail-function 'smtpmail-send-it
      smtpmail-default-smtp-server "smtp.gmail.com"
      smtpmail-smtp-service 587
      smtpmail-local-domain "homepc")
;; http://www.gnu.org/software/emacs/manual/html_node/gnus/_005b9_002e2_005d.html
(setq gnus-use-correct-string-widths nil)

(eval-after-load 'gnus-topic
  '(progn
     (setq gnus-message-archive-group '((format-time-string "sent.%Y")))
     (setq gnus-server-alist '(("archive" nnfolder "archive" (nnfolder-directory "~/Mail/archive")
                                (nnfolder-active-file "~/Mail/archive/active")
                                (nnfolder-get-new-mail nil)
                                (nnfolder-inhibit-expiry t))))

     (setq gnus-topic-topology '(("Gnus" visible)
                                 (("misc" visible))
                                 (("hotmail" visible nil nil))
                                 (("gmail" visible nil nil))))

     (setq gnus-topic-alist '(("hotmail" ; the key of topic
                               "nnimap+hotmail:Inbox"
                               "nnimap+hotmail:Drafts"
                               "nnimap+hotmail:Sent"
                               "nnimap+hotmail:Junk"
                               "nnimap+hotmail:Deleted")
                              ("gmail" ; the key of topic
                               "INBOX"
                               "[Gmail]/Sent Mail"
                               "[Gmail]/Trash"
                               "Sent Messages"
                               "Drafts")
                              ("misc" ; the key of topic
                               "nnfolder+archive:sent.2015-12"
                               "nnfolder+archive:sent.2016"
                               "nnfolder+archive:sent.2017"
                               "nndraft:drafts")
                              ("Gnus")))))

Your login and password is stored at “~/.authinfo.gpg” which is read by Gnus. Please press C-h v auth-sources for more information.

Multiple mail accounts share one “.authinfo.gpg”,

machine imap.gmail.com login [email protected] password my-secret-password port 993
machine smtp.gmail.com login [email protected] password my-secret-password port 587
machine imap-mail.outlook.com login [email protected] password my-secret-password port 993

Please note “.authinfo.gpg” is encrypted by default. Emacs will do the encryption/description automatically if file extension is “.gpg”. See http://emacswiki.org/emacs/EasyPG for details.