Friday, February 26, 2010

Finally getting gnus to act like an email client

I'm liking emacs. I still miss some of the vim commands, particularly numerical prefixes (I know, in emacs you can do C-u to prefix a command, but it's just not nearly as elegant) and the "repeat last edit" command ".". But on the whole, I like how integrated emacs is, how customizable it is, and actually a few of the editing commands (one of my new favorites is C-x ; to set the comment column then M-; to add a comment at the right of a group of text). Anyways, I've switched to using gnus for my email. It took a little getting used to, but yesterday I tried going back to Mail.app and found myself kind of annoyed at some of the things I just couldn't do; particularly with respect to managing my gmail account, which all of my email goes through. On the other hand, it has taken me over a week to get this to work the way I want it to. The google search results are more often than not not all that helpful, so I thought I'd document some of what I've learned here.

1. Gnus and Gmail imap. I don't remember all of the details of getting it set up, but this part of the .gnus file has the basic set-up for getting your mail from the gmail imap server:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Using gmail IMAP for receiving mail, credentials in .authinfo
(setq gnus-select-method '(nnml ""))
(add-to-list 'gnus-secondary-select-methods '(nnimap "gmail"
                                                     (nnimap-address "imap.gmail.com")
                                                     (nnimap-server-port 993)
                                                     (nnimap-stream ssl)))
;; make gnus NOT ignore [Gmail] mailboxes
(setq gnus-ignored-newsgroups "^to\\.\\|^[0-9. ]+\\( \\|$\\)\\|^[\"]\"[#'()]")
I use my Princeton email address primarily, so to send mail through Princeton smtp I use
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Using Princeton SMTP for sending mail
(setq message-sendmail-envelope-from 'header)
(setq send-mail-function 'smtpmail-send-it
      message-send-mail-function 'smtpmail-send-it)
(setq smtpmail-default-smtp-server "smtp.princeton.edu"
      smtpmail-smtp-server "smtp.princeton.edu"
      smtpmail-smtp-service 587
      smtpmail-starttls-credentials '(("smtp.princeton.edu" 587 nil nil)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This is the "proper" way to set up the "from" information for new mail
;;   Note I BCC to myself @ gmail so that it gets stored in my gmail
(setq gnus-posting-styles
      '((".*"
         (name "Daniel Swain")
         (address "dswain@princeton.edu")
         (BCC "dan.t.swain@gmail.com"))))
For both I use a ~/.authinfo file which should look something like this:
machine imap.gmail.com login dan.t.swain@gmail.com password mysupersecretpassword port 993
machine smtp.princeton.edu login dswain password
myothersupersecretpassword port 587
This bit gets gnus to stop asking me how many old emails I want to download. You could change 'some to some big number, but I keep my inbox pretty clean, so it's not a big deal.
;; don't ask how many emails to download
(setq gnus-large-newsgroup 'nil)
The final bit took me the longest to figure out. Every time I got new email, gnus would only show the new email in the buffer and hide all of my old emails until I read the new one and hit M-g again to rescan the inbox. A bit of C-h k to figure out what the function call was led me to this solution, in which I bind C-c C-c in the summary buffer to "Check for new mail", which is a call to the same function as M-g but with 'all as an argument.
;; tells gnus to get new mail and also display all old mail
(define-key gnus-summary-mode-map (kbd "C-c C-c")
  (lambda ()
    (interactive)
    (gnus-summary-rescan-group 'all)))

2. w3m and Aquamacs 2.0 preview 4b. When I upgraded to Aquamacs 2.0 preview 4b (which is based on Emacs23.1 rather than Emacs22.something), gnus seemed to stop wanting to display the contents of some emails, instead just displaying the headers. It turns out this was because those emails used HTML and w3m uses the w3m browser to show HTML emails. I had download w3m before and installed emacs-w3m under Aquamacs 1.9, but apparently something broke in the upgrade. I was able to fix it by downloading the CVS version of emacs-w3m (I didn't have to reinstall w3m, which I had installed using darwinports) and configuring it using --with-emacs=/Applications/Aquamacs.app/Contents/MacOS/Aquamacs. I did a "make" but not "make install", instead I copied the whole emacs-w3m folder to my emacs packages directory (~/.emacs-pkgs, but the name isn't important) and loading it in my .emacs.el with
;; Use w3m for web browsing
(setq load-path (cons "~/.emacs-pkgs/emacs-w3m/" load-path))
(require 'w3m-load)

3. I used htmlize to generate the code snippets in this post.

5 comments:

Zaak said...

Dan, I am trying to set this up, as I want to start using org mode, and I can point to emails, etc. from org mode if I read them in emacs. I'm a little bit unclear: What needs to be added to your .emacs file, and what needs to be added to the .gnus file? Thanks for this helpful post, I agree with you about most of the other tutorials being somewhat challenging.

Dan said...

Hey Zaak, I'm glad this is helpful. I tend to write about things to sort them out in my own head, but always hope it helps someone else, too.

Everything from the "1." part should be in .gnus, except the part that goes in .authinfo (the lines starting "machine"). I only have the lines to load w3m in my .emacs.

Zaak said...

It looks like things are working now, except I'm having tls issues with outgoing mail. Somehow I think I need to install starttls in my userspace at work, or funnel things through sendmail. Also on the todo list: Learn how to use gnus.

btw have you checked out orgmode?

edwingt said...

Hello I can send mails with this configuration, and apparently gnus read my gmail because it say *Group* nnimap:gmail but I'm not able to see my messages. I thinks is something with " (setq gnus-ignored-newsgroups "^to\\.\\|^[0-9. ]+\\( \\|$\\)\\|^[\"]\"[#'()]")" any ideas.

Dan said...

Hi edwingt. I'm glad this was useful to you! I've read that in other languages the gmail mailboxes have a different naming convention that slips through this regex. There is probably a much better solution, but for now it appears that the best bet is to use

(setq gnus-ignored-newsgroups "")

so that you are not ignoring *any* newsgroups.

If you're just using gnus to read mail, this is probably OK. Otherwise you may need to do some more research to find a regex that will work.