Whoever said there are no technical solutions to social problems must not have had a powerful enough mail program. Get motivated and organized with some new mail-productivity hacks for the classic Emacs environment.
endif; ?>Introduction Drowning in e-mail? In this article, you’ll pick up a few ideas for:
Introduction
Drowning in e-mail? In this article, you’ll pick up a few ideas for:
Dealing with inbox addiction by forcing yourself to do work before you can check mail.
Prioritizing mail based on your importance in the recipient list.
Scoring mail, reading interesting mail first.
Sending personalized semi-automated e-mail to your friends (so that they think you care!).
This article will probably be most useful for intermediate to advanced users who use Gnus for their mail. Gnus is an Emacs mail client. It may even be said that Gnus is the Emacs of mail clients: extremely customizable, but with a learning curve that will drive you insane. I won’t even begin to describe how to set up Gnus, for which you’ll probably need to spend a day curled up with manuals and tutorials. I should also warn you that I’m on the GNU Emacs 22 prerelease. However, I will share some of the advanced tricks that make it all worth it.
The following hacks are just a few of the ways I’ve tweaked my Gnus to fit the way I read mail. Even if you use a different mail client, you might pick up a few ideas. Have fun!
Dealing with Inbox Addiction
If you want to regain your productivity, the key thing is to limit the number of times you check your mail. There are few things as distracting as the constant notification of your e-mail client. Do not check it all the time, especially if it’s only been a minute or two since you last checked.
I have a hard time following my own advice sometimes, so I’ve added this little hack based on Don Marti’s e-mail setup described in “laptop mail part 4.” Here’s how it works. Use gnus-summary-tick-article-forward (!) to mark messages that need action and gnus-summary-mark-as-read-forward (d) when the message or action is done. The code prevents you from checking mail if the number of ticked messages in your inbox is not less than it was the last time you checked mail; that is, if you haven’t marked any of the messages as done. It’s a good reminder to pick one of those messages and respond to it. If you really can’t work on anything at the moment, you’ll be allowed to check mail again after two hours (configurable with sacha/gnus-inbox-time-threshold).
When I first implemented this code, I had so much fun keeping track of how my inbox count was going down, down, down, that I ended up clearing my inbox the same day. Since then, my inbox has been inching up, but at least I manage to cross off a few items before getting deluged with more mail. It’s a little like building a reward system into your e-mail: if you work, you get to check mail. Great way to turn your addiction on its head!
Here’s the code:
;; CONFIG: Change this to your inbox group
(defvar sacha/gnus-inbox-group “mail.misc”
“*Group to consider as inbox.”)
(defvar sacha/gnus-inbox-time-threshold (seconds-to-time (* 60 60 2))
“*Number of seconds before you can check again if you haven’t done any work.
Nil means don’t use time.”)
(defvar sacha/gnus-inbox-last-count nil “Number of ticked items in inbox.”)
(defvar sacha/gnus-inbox-last-check nil “Timestamp of last check.”)
(defun sacha/gnus-inbox-decreased-p ()
“Return non-nil if you are allowed to check mail.
You are not allowed to check mail for more messages unless the
number of ticked items has decreased since the last time checked
or `sacha/gnus-inbox-time-threshold’ seconds have passed.
Based on http://www.linuxworld.com/community/?q=node/387″
(or (not (numberp sacha/gnus-inbox-last-count)) ;; First time called
(and sacha/gnus-inbox-last-check
sacha/gnus-inbox-time-threshold
(not (time-less-p (time-since sacha/gnus-inbox-last-check)
sacha/gnus-inbox-time-threshold)))
(or (= sacha/gnus-inbox-last-count 0)
(
sacha/gnus-inbox-last-count))))
(defun sacha/gnus-inbox-count ()
“Return number of ticked items in `sacha/gnus-inbox-group’.”
(save-window-excursion
(gnus-summary-read-group-1 sacha/gnus-inbox-group nil t nil t ‘(1))
(length gnus-newsgroup-marked)))
(defadvice gnus-group-get-new-news (around sacha/gnus-inbox-check-mail activate)
“Allow only if the inbox count has decreased.”
(if (sacha/gnus-inbox-decreased-p)
ad-do-it
(setq sacha/gnus-inbox-last-count (sacha/gnus-inbox-count))
(error “Get your mail count below %d first.” (sacha/gnus-inbox-count)))
(setq sacha/gnus-inbox-last-count (sacha/gnus-inbox-count)
sacha/gnus-inbox-last-check (current-time)))
Prioritizing Recipients
You can use several tricks to prioritize mail. One way is to look at mail that you need to respond to and postpone mail that might not require a reply from you. Here’s one way of classifying mail:
Criterion Mark
You’re the only one in the To: list !
Sent to a short list of people including you (To:) *
Sent to a long list of people including you (To:) /
You’re part of a short list of Cc:s –
You’re part of a long list of Cc:s .
You don’t show up in the header at all (Bcc:, a lot of spam) (blank)
If you’re the only person the e-mail is sent to, then you probably need to reply. On the other hand, if you’re part of a long list of Cc:s, then it was probably an email sent to you for your information, and you don’t need to respond to it quickly.
Here’s the code:
;; CONFIG: Add %us to your gnus-summary-line-format.
;; CONFIG: Set gnus-ignored-from-addresses to a regexp matching your e-mail addresses
(defvar sacha/gnus-count-recipients-threshold 5
“*Number of recipients for a message considered ‘many’.”)
(defun sacha/gnus-count-recipients (header)
“Given a Gnus message header, returns priority mark.
If I am the only recipient, return “!”.
If I am one of a few recipients, but I’m listed in To:, return “*”.
If I am one of many recipients, but I’m listed in To:, return “/”.
If I am one of a few Cc’d recipients, return “-“.
If I am one of many recipients, return “.”.
Else, return ” “.”
(let* ((to (or (cdr (assoc ‘To (mail-header-extra header))) “”))
(cc (or (cdr (assoc ‘Cc (mail-header-extra header))) “”))
(threshold sacha/gnus-count-recipients-threshold))
(cond
((string-match gnus-ignored-from-addresses to)
(let ((len (length (bbdb-split to “,”))))
(cond
((= len 1) “!”)
((
(t “/”))))
((string-match gnus-ignored-from-addresses
(concat to “, ” cc))
(if (
threshold)
“-“
“.”))
(t ” “))))
(defalias ‘gnus-user-format-function-s ‘sacha/gnus-count-recipients)
You can even extend this function to consider the subtle nuances of pecking order in the To: and Cc: list, where being first in the list counts for more than being last in the list. This is left as an exercise for the reader because I’m still trying to convince people not to pile everyone in the To: list.
Scoring
I love scoring. This is the main reason why I use Gnus and one of the major reasons why I use Emacs. I’ve never found anything like it in any mail client that I’ve tried. It makes it easier for me to see interesting mail: replies to messages that I’ve ticked, messages containing certain keywords, messages from people whose e-mails I always enjoy. It can also score down messages I probably won’t be interested in, such as threads about vim.
The following code sets up simple adaptive scoring. When you read a thread you find interesting, tick a message with gnus-summary-tick-article-forward (!). When you come across a thread that you don’t want to follow, use gnus-summary-kill-same-subject-and-select (k) or a similar command to mark it killed. If you don’t have a lot of time, read or kill messages with interesting subjects and use gnus-summary-catchup (c) to mark all of them as boring. By default, boring messages are still displayed, so you can change your mind and explicitly adjust scores with gnus-summary-increase-score and gnus-summary-lower-score.
The next time you visit the summary buffer, threads with positive scores bubble to the top and threads with negative scores sink to the bottom. If you don’t have time for more than a quick scan of your mail, just look at the top of the list. You can configure Gnus to hide low-scored threads entirely, but I prefer to keep them visible just in case something catches my eye.
(setq gnus-show-threads t)
(setq gnus-thread-sort-functions ‘gnus-thread-sort-by-total-score)
(setq gnus-use-adaptive-scoring t)
(setq gnus-default-adaptive-score-alist
‘((gnus-unread-mark)
(gnus-ticked-mark (subject 5))
(gnus-dormant-mark (subject 5))
(gnus-del-mark (subject -1))
(gnus-killed-mark (subject -5))
(gnus-catchup-mark (subject -1))))
You can read more in the Gnus manual under the topic “Scoring.” There are tons of customizable options for you to tweak!
Sending Templated Mail
Here we venture into the gray area of templates and mail. Is it unethical to use Emacs to compose a large number of personalizable messages to people you know? Beats me — but it saves a lot of repetitive text entry. Even if you cut and paste, even if you insert registers, even if you use keyboard macros, composing individual messages to lots of people takes a lot of time. That’s why I wrote this little snippet that makes it easy for me to compose individual messages to all the people currently displayed in my BBDB buffer. I use BBDB as my address book, filter the displayed list by a few functions I’ve written (including one that displays only people I haven’t talked to since a certain date), use the code to compose a lot of messages, and then personalize each one before sending.
Fortunately, my friends can not only sniff out auto-generated mail but are also the sort to be amused by the Emacs hack behind it. When I used this to confirm the postal addresses of a large number of people (personalizing each message with a note), quite a few friends teased me about Emacs gaining even more artificial intelligence. I had shown them M-x doctor before, and they wondered if that was the logical next step. I also received one intentionally obfuscated reply that was almost a Turing test.
If you have friends who are likely to know and laugh at the automation, or your friends don’t care if you use tricks like that to keep in better touch, go ahead and use the following code. Please do not use this for evil.
(defun sacha/gnus-send-message-to-all (records subject &optional text)
“Compose message to everyone listed in the BBDB buffer, with notes.
SUBJECT is the subject of the message. TEXT is either a string
not starting with a parenthesis, or a sexp that evaluates to a
string. If TEXT is a sexp, the first character must be an open parenthesis.
During the evaluation of this sexp, the variable ‘record’ will
contain the current BBDB record. This allows you to write
messages with arbitrary Lisp expressions, such as the following:
(concat “Hello, ” (bbdb-record-name record) “!”)
or even something involving ‘if’, ‘cond’, ‘random’, and other
fun Lisp goodies. (Fortune cookies, anyone?)”
(interactive
(list
(records bbdb-records)
(read-string “Subject: “)
(read-string “Body: “)))
(while records
(when (bbdb-record-net (caar records))
(bbdb-send-mail (caar records) subject)
(goto-char (point-min))
(re-search-forward “–text ” nil t)
(forward-line 1)
(let ((record (caar records)))
(when text
(insert (if (= (aref text 0) ?()
(eval (read text))
text))))))
(setq records (cdr records))))
I combine a modified version of the above code with a chunk of other BBDB+Gnus code in order to keep detailed notes on people. With my setup, each composed message also automatically includes my notes about the person and our contact history. This allows me to personalize a message by greeting the person and her cat, for example. These notes are automatically removed before the message is sent, and the subject line of the current message is added to the contact history. The full code for this is enough for another article, but I hope that the above code helps you keep in touch with people better. Use BBDB to select people from your address book, then call sacha/gnus-send-message-to-all from the BBDB buffer. Again, do not use this for evil!
Those are just a few of the tricks I use for e-mail productivity. Gnus really helps me keep track of my mail, and all the little customizations I’ve accumulated over the years make it tailor-made for me. Try them out and see if you can handle your mail better! For more ideas and inspiration, check out the EmacsWiki and the Gnus manual. If you use a different mail client, read your mail client’s manual—and even the source code. Happy hacking!
Sacha Chua (sacha@sachachua.com) is a technology evangelist whose Emacs configuration is probably about to attain sentience. In a recent demonstration in Toronto, she wowed the audience with some of the crazy things you can do with Emacs. Then they realized that Emacs was talking to her and telling her what to do, which probably gave some of them the shivers. She occasionally uses vim for text editing and Lotus Notes for mail at work, but believes that $HOME is where the .emacs is.




