Experiences with Gnorb, Gnus etc.

Table of Contents

1 Notes on gnorb (and related gnus issues)

These notes are in the order I thought of them. If it seems a bit scattered, well …

1.1 Read the info file

1.1.1 How to get it right

Read through the gnorb info file a few times. Pay special attention to the sample workflow. You should be able to reproduce this workflow. If you can’t, you have things to do with your setup.

1.1.2 Use the keybindings

The sample keybindings in the info file are very useful. That said, you’ll be using C-c t most of the time.

1.2 Loading order

You should load and fully configure org-mode, gnus, and bbdb (I do them in that order) before you load and configure gnorb. This includes fully configuring the gnus registry. (The Gnorb author is working on eliminating this order dependency, but it really isn’t a bad idea to think through the way you load things.)

But note a couple of things.

1.2.1 Start gnus at the very end

Do not actually start gnus with (gnus) until gnorb is completely set up. I found that the gnus group buffer doesn’t have the right stuff in it if you call (gnus) before gnorb is set up. Again, the author is working on this and may have already resolved it, but I don’t consider this a serious issue. Just do things in the right sequence; which is pretty logical in any event.

1.2.2 Set up secondary-select-method

You should set up your nngnorb secondary-select-method within your gnus setup. There is no problem doing this before gnorb is loaded.

1.3 org-capture templates

Be sure that each and every one of your org-capture templates contains the %a string, which brings in a link back to (in this case) the relevant email. If you don’t do this then later on gnorb won’t know that there is an email to which a reply can be sent. This sounds obvious but is quite easy to miss.

Well … I found the above isn’t quite accurate. See below about capturing emails. But your org-capture templates really ought to contain the %a string no matter.

1.4 Capturing emails

There are some things to be aware of about capturing emails.

1.4.1 How to capture email

Turns out I was doing this wrong. I was capturing emails with the gnorb C-c t sequence and that created problems with template selection, capture location and so on. Don’t do it that way! Just capture with the usual org-capture sequence (C-c and then select template). When it’s time to reply to the email you can use gnorb’s C-c t to track the email chain. Works great and no problems.

1.4.2 Selecting headlines

The following only applies to special cases. If you do as I suggested above and capture emails with org-capture methods, all the stuff below won’t matter, which is good. So do it the right way in the first place.

But if you insist on using C-c t to capture, read on.

If everything else is correctly setup and executed, gnorb eventually prompts for an org headline to which the email will be attached. But all is not as it seems.

First, you can’t just enter a new headline. You have to choose from a completion buffer of existing headlines. This buffer is generated by org-mode and can be a little difficult to search through. I haven’t fully determined what makes up the buffer but it seems to be derived from all open org files. If you want a headline in an org file that isn’t current in a buffer you’re out of luck. If you want a new headline, sorry.

But it’s a little worse than that. If you add a headline after the completion buffer has first been generated, you won’t see it because it seems that the buffer isn’t properly regenerated (I would be delighted to be proven wrong on this). Supposedly you can close the buffer and then re-open the file, but this hasn’t worked for me either.

So you need to plan ahead to some extent. I need to look into this further to be sure I’ve got everything right here. I’m hoping there is a better way. You really ought to be able to start a new headline, even in a new file, as an attachment point.

1.4.3 Messages captured as org-mode TODOs

The gnorb manual tells you that if you do an org-mode TODO capture (for me that’s C-c c t) or the like, gnorb will track the email, and that’s correct. But you have to be careful.

Org will put the email link on the same line as the TODO header. You had better leave the link there, and not move it down to make things look neater or to avoid a very long TODO line. Why? because if you move it down, org will move it down further when you do an action, moving it below the first :PROPERTIES: line. This matters because when you go to use gnorb to reply, with C-c t, gnorb will quickly pop up an email composition buffer that doesn’t have the recipient filled in. This is not what you want.

But if you leave things alone, gnorb will find the email link, and then rather slowly (if you’re using gmail) set up a buffer, open the mail, and start a properly filled in reply buffer.

1.5 Gnus registry

Strictly speaking this is not a gnorb issue but if you’re like me, you won’t have used the gnus registry prior to setting up gnorb. So there are some points to watch.

1.5.1 Size

Make the registry maximum entries large enough. Now, this will give you a rather large registry file after a while, but in the end that’s okay.

1.5.2 Exclusions

The registry aggressively grabs everything unless told not to do so. Initially, I was indexing trash and spam messages along with everything else. So carefully set up group exclusions and be sure they’re working.

1.5.3 Trimming the registry

The registry can get pretty big (hey, I set my limit at 500000 entries or something). But every so often I get tired of it and trim it down. Way down. Below is code to do that. It will trim the registry down to just about the bare essentials, also known as “precious” entries. Gnorb marks its entries as “precious,” by the way.

Now, I’m telling you not to run this code because it aggressively deletes data. If you really have to run it, at least back up the registry first, and/or really know what you’re doing.

I AM NOT RESPONSIBLE FOR LOSS OF DATA if you decide to use this. YOU HAVE BEEN WARNED! Don’t do it!

(defun gnus-registry-shrink ()
"A local function to shrink the gnus registry
to pretty much just precious entries.
With hard-wired parameters, requires editing to
be useful in other environments"
  (interactive)
  (defvar gnus-registry-max-entries-save)
  (setq gnus-registry-max-entries-save gnus-registry-max-entries)
;; This will pretty much just keep 'precious' entries.
  (setq gnus-registry-max-entries 5)
  (gnus-registry-save)
  (gnus-registry-load)
  (setq gnus-registry-max-entries gnus-registry-max-entries-save)
  (gnus-registry-save)
  (gnus-registry-load)
  )

1.6 Using Gmail

I use gnus along with gmail and I don’t use local storage. My backend is imap and I ensure that imap is loaded early in my setup. If you don’t use gmail with gnus (how to do so is well documented online) this doesn’t apply to you. I’ll repeat here: if you use gnorb with gmail (and likely any imap scheme) you will need to hone the virtue of patience, because many gnorb operations take a while. Or maybe you could drink coffee and relax for a bit. Not a bad thought.

1.6.1 Define sent mail folder

Gmail isn’t the smoothest companion to gnorb. For one thing you need to define the sent mail location, as documented in the gnorb info file. That’s not a big deal.

1.6.2 Fetching associated emails

But when you do something like C-c e to list all emails associated with an org headline, it may take a while. Fortunately, since gnorb uses the registry, the relevant emails will be found sooner or later.

I don’t have a solution for this at present. I just grin and bear it. We are far too used to instant gratification with computers and the internet. It does not harm us to wait 15 seconds for something.

1.6.3 Gmail email that moves

My practice is to have a clear inbox, so I archive mail items pretty quickly (see my article on Stupid Gmail Hacks). But what if I’ve made an org-mode link to an email? The email is no longer in the inbox and won’t be found through the link.

So I put together a little code that fixes org-mode links to Gmail email. This is a bit drastic, but it works. All links, no matter where they are from, are modified so that they point to All Mail. Gmail leaves everything in All Mail except Spam and Trash. So links will always work.

(Disclaimer: With the use of the registry, is this hack redundant? I don’t think so, but someone who knows more might straighten me out on this if I’m wrong. However, I still think it best to have links that actually point to something.)

Anyhow, here’s the hack. (It’s also found in the Stupid Gmail Hacks article.)

;; This function and defadvice attempts to solve the problem of Gmail
;; email being moved from folder to folder. We change org-mode email
;; links involving gmail to always point to the All Mail folder, where
;; everything resides except stuff that has been purged.

(defun changegroupinemaillink (&rest args)
  (if org-stored-links
    (let* ( (oldlink (car (car org-stored-links)))
            (newlink (replace-regexp-in-string "gmail:.*#" "gmail:[Gmail]/All Mail#" oldlink)))
        (setcar (car org-stored-links) newlink))))

(advice-add 'org-store-link :after #'changegroupinemaillink)

1.7 BBDB integration

There were a couple of problems, but they’ve been resolved. BBDB integration works wonderfully. I use it to log emails from a correspondent who is providing input on a certain project.

1.8 My startup code

Don’t copy blindly. Some stuff just pertains to me. It’s fairly clear which is which but you have to read through it to know :)

1.8.1 gnorb


;; Now attempt gnorb. Must be below gnus, bbdb, org.

;; Basic setup

(require 'gnorb)

(gnorb-tracking-initialize)

;; This cannot be nil or there is an error.
;; If you are not 'bobnewell' change this.
(setq message-alternative-emails "bobnewell")

;; Fix for gmail. imap must be loaded.
(require 'imap)

;; Let gnorb find sent mail folder. Change to suit.
(setq gnorb-gnus-sent-groups '("nnimap+gmail:[Gmail]/Sent Mail"))

;; Additional (custom?) setup.

;; For uniformity of posting styles.
(setq gnorb-posting-styles gnus-posting-styles)
;; Force capture all attachments.
(setq gnorb-gnus-capture-always-attach t)
;; Change the default from a very stingy 5.
(setq gnorb-bbdb-collect-N-messages 1000)

;; Keybindings

(eval-after-load "gnorb-bbdb"
       '(progn
          (define-key bbdb-mode-map (kbd "O") 'gnorb-bbdb-tag-agenda)
          (define-key bbdb-mode-map (kbd "S") 'gnorb-bbdb-mail-search)
          (define-key bbdb-mode-map [remap bbdb-mail] 'gnorb-bbdb-mail)
          (define-key bbdb-mode-map (kbd "l") 'gnorb-bbdb-open-link)
          (global-set-key (kbd "C-c C") 'gnorb-bbdb-cite-contact)))

     (eval-after-load "gnorb-org"
       '(progn
          (org-defkey org-mode-map (kbd "C-c C") 'gnorb-org-contact-link)
          (org-defkey org-mode-map (kbd "C-c t") 'gnorb-org-handle-mail)
          (org-defkey org-mode-map (kbd "C-c e") 'gnorb-org-view)
          (org-defkey org-mode-map (kbd "C-c E") 'gnorb-org-email-subtree)
          (org-defkey org-mode-map (kbd "C-c V") 'gnorb-org-popup-bbdb)
          (setq gnorb-org-agenda-popup-bbdb t)
          (eval-after-load "org-agenda"
            '(progn (org-defkey org-agenda-mode-map (kbd "C-c t") 'gnorb-org-handle-mail)
                    (org-defkey org-agenda-mode-map (kbd "C-c v") 'gnorb-org-popup-bbdb)
                    (org-defkey org-agenda-mode-map (kbd "V") 'gnorb-org-view)))))

     (eval-after-load "gnorb-gnus"
       '(progn
          (define-key gnus-summary-mime-map "a" 'gnorb-gnus-article-org-attach)
          (define-key gnus-summary-mode-map (kbd "C-c t") 'gnorb-gnus-incoming-do-todo)
          (push '("attach to org heading" . gnorb-gnus-mime-org-attach)
                gnus-mime-action-alist)
          ;; The only way to add mime button command keys is by redefining
          ;; gnus-mime-button-map, possibly not ideal. Ideal would be a
          ;; setter function in gnus itself.
          (push '(gnorb-gnus-mime-org-attach "a" "Attach to Org heading")
                gnus-mime-button-commands)
          (setq gnus-mime-button-map
                (let ((map (make-sparse-keymap)))
                  (define-key map gnus-mouse-2 'gnus-article-push-button)
                  (define-key map gnus-down-mouse-3 'gnus-mime-button-menu)
                  (dolist (c gnus-mime-button-commands)
                    (define-key map (cadr c) (car c)))
                  map))))

     (eval-after-load "message"
       '(progn
          (define-key message-mode-map (kbd "C-c t") 'gnorb-gnus-outgoing-do-todo)))

1.8.2 gnus

I’m just showing the stuff relevant to gnorb. Obviously my gnus startup is much longer.

This is for gnorb:

(add-to-list ’gnus-secondary-select-methods ’(nngnorb “GobblerGnorb”))

And this is my registry setup:


(setq gnus-registry-max-entries 500000)
(gnus-registry-initialize)
;; Change these to suit your environment.
(setq gnus-registry-ignored-groups '(("nntp" t)
                                     ("Trash$" t)
                                     ("drafts$" t)
				     ("Starred$" t)
                                     ("Spam$" t)))

Author: Bob Newell

Email: bobnewell@bobnewell.net

Created: 2018-03-07 Wed 14:02

Validate