[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6. Select Methods

A foreign group is a group not read by the usual (or default) means. It could be, for instance, a group from a different NNTP server, it could be a virtual group, or it could be your own personal mail group.

A foreign group (or any group, really) is specified by a name and a select method. To take the latter first, a select method is a list where the first element says what back end to use (e.g. nntp, nnspool, nnml) and the second element is the server name. There may be additional elements in the select method, where the value may have special meaning for the back end in question.

One could say that a select method defines a virtual server---so we do just that (see section 6.1 Server Buffer).

The name of the group is the name the back end will recognize the group as.

For instance, the group `soc.motss' on the NNTP server `some.where.edu' will have the name `soc.motss' and select method (nntp "some.where.edu"). Gnus will call this group `nntp+some.where.edu:soc.motss', even though the nntp back end just knows this group as `soc.motss'.

The different methods all have their peculiarities, of course.

6.1 Server Buffer  Making and editing virtual servers.
6.2 Getting News  Reading USENET news with Gnus.
6.3 Getting Mail  Reading your personal mail with Gnus.
6.4 Browsing the Web  Getting messages from a plethora of Web sources.
6.5 IMAP  Using Gnus as a IMAP client.
6.6 Other Sources  Reading directories, files, SOUP packets.
6.7 Combined Groups  Combining groups into one group.
6.8 Gnus Unplugged  Reading news and mail offline.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1 Server Buffer

Traditionally, a server is a machine or a piece of software that one connects to, and then requests information from. Gnus does not connect directly to any real servers, but does all transactions through one back end or other. But that's just putting one layer more between the actual media and Gnus, so we might just as well say that each back end represents a virtual server.

For instance, the nntp back end may be used to connect to several different actual NNTP servers, or, perhaps, to many different ports on the same actual NNTP server. You tell Gnus which back end to use, and what parameters to set by specifying a select method.

These select method specifications can sometimes become quite complicated--say, for instance, that you want to read from the NNTP server `news.funet.fi' on port number 13, which hangs if queried for NOV headers and has a buggy select. Ahem. Anyway, if you had to specify that for each group that used this server, that would be too much work, so Gnus offers a way of naming select methods, which is what you do in the server buffer.

To enter the server buffer, use the ^ (gnus-group-enter-server-mode) command in the group buffer.

6.1.1 Server Buffer Format  You can customize the look of this buffer.
6.1.2 Server Commands  Commands to manipulate servers.
6.1.3 Example Methods  Examples server specifications.
6.1.4 Creating a Virtual Server  An example session.
6.1.5 Server Variables  Which variables to set.
6.1.6 Servers and Methods  You can use server names as select methods.
6.1.7 Unavailable Servers  Some servers you try to contact may be down.

gnus-server-mode-hook is run when creating the server buffer.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.1 Server Buffer Format

You can change the look of the server buffer lines by changing the gnus-server-line-format variable. This is a format-like variable, with some simple extensions:

How the news is fetched--the back end name.

The name of this server.

Where the news is to be fetched from--the address.

The opened/closed/denied status of the server.

Whether this server is agentized.

The mode line can also be customized by using the gnus-server-mode-line-format variable (see section 8.4.2 Mode Line Formatting). The following specs are understood:

Server name.

Server method.

Also see section 8.4 Formatting Variables.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.2 Server Commands

The key v is reserved for users. You can bind it key to some function or better use it as a prefix key.

Add a new server (gnus-server-add-server).

Edit a server (gnus-server-edit-server).

Browse the current server (gnus-server-read-server).

Return to the group buffer (gnus-server-exit).

Kill the current server (gnus-server-kill-server).

Yank the previously killed server (gnus-server-yank-server).

Copy the current server (gnus-server-copy-server).

List all servers (gnus-server-list-servers).

Request that the server scan its sources for new articles (gnus-server-scan-server). This is mainly sensible with mail servers.

Request that the server regenerate all its data structures (gnus-server-regenerate-server). This can be useful if you have a mail back end that has gotten out of sync.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.3 Example Methods

Most select methods are pretty simple and self-explanatory:

(nntp "news.funet.fi")

Reading directly from the spool is even simpler:

(nnspool "")

As you can see, the first element in a select method is the name of the back end, and the second is the address, or name, if you will.

After these two elements, there may be an arbitrary number of (variable form) pairs.

To go back to the first example--imagine that you want to read from port 15 on that machine. This is what the select method should look like then:

(nntp "news.funet.fi" (nntp-port-number 15))

You should read the documentation to each back end to find out what variables are relevant, but here's an nnmh example:

nnmh is a mail back end that reads a spool-like structure. Say you have two structures that you wish to access: One is your private mail spool, and the other is a public one. Here's the possible spec for your private mail:

(nnmh "private" (nnmh-directory "~/private/mail/"))

(This server is then called `private', but you may have guessed that.)

Here's the method for a public spool:

(nnmh "public"
      (nnmh-directory "/usr/information/spool/")
      (nnmh-get-new-mail nil))

If you are behind a firewall and only have access to the NNTP server from the firewall machine, you can instruct Gnus to rlogin on the firewall machine and telnet from there to the NNTP server. Doing this can be rather fiddly, but your virtual server definition should probably look something like this:

(nntp "firewall"
      (nntp-open-connection-function nntp-open-via-rlogin-and-telnet)
      (nntp-via-address "the.firewall.machine")
      (nntp-address "the.real.nntp.host")
      (nntp-end-of-line "\n"))

If you want to use the wonderful ssh program to provide a compressed connection over the modem line, you could add the following configuration to the example above:

      (nntp-via-rlogin-command "ssh")

See also nntp-via-rlogin-command-switches.

If you're behind a firewall, but have direct access to the outside world through a wrapper command like "runsocks", you could open a socksified telnet connection to the news server as follows:

(nntp "outside"
      (nntp-pre-command "runsocks")
      (nntp-open-connection-function nntp-open-via-telnet)
      (nntp-address "the.news.server")
      (nntp-end-of-line "\n"))

This means that you have to have set up ssh-agent correctly to provide automatic authorization, of course. And to get a compressed connection, you have to have the `Compression' option in the ssh `config' file.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.4 Creating a Virtual Server

If you're saving lots of articles in the cache by using persistent articles, you may want to create a virtual server to read the cache.

First you need to add a new server. The a command does that. It would probably be best to use nnml to read the cache. You could also use nnspool or nnmh, though.

Type a nnml RET cache RET.

You should now have a brand new nnml virtual server called `cache'. You now need to edit it to have the right definitions. Type e to edit the server. You'll be entered into a buffer that will contain the following:

(nnml "cache")

Change that to:

(nnml "cache"
         (nnml-directory "~/News/cache/")
         (nnml-active-file "~/News/cache/active"))

Type C-c C-c to return to the server buffer. If you now press RET over this virtual server, you should be entered into a browse buffer, and you should be able to enter any of the groups displayed.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.5 Server Variables

One sticky point when defining variables (both on back ends and in Emacs in general) is that some variables are typically initialized from other variables when the definition of the variables is being loaded. If you change the "base" variable after the variables have been loaded, you won't change the "derived" variables.

This typically affects directory and file variables. For instance, nnml-directory is `~/Mail/' by default, and all nnml directory variables are initialized from that variable, so nnml-active-file will be `~/Mail/active'. If you define a new virtual nnml server, it will not suffice to set just nnml-directory---you have to explicitly set all the file variables to be what you want them to be. For a complete list of variables for each back end, see each back end's section later in this manual, but here's an example nnml definition:

(nnml "public"
      (nnml-directory "~/my-mail/")
      (nnml-active-file "~/my-mail/active")
      (nnml-newsgroups-file "~/my-mail/newsgroups"))

Server variables are often called server parameters.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.6 Servers and Methods

Wherever you would normally use a select method (e.g. gnus-secondary-select-method, in the group select method, when browsing a foreign server) you can use a virtual server name instead. This could potentially save lots of typing. And it's nice all over.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.7 Unavailable Servers

If a server seems to be unreachable, Gnus will mark that server as denied. That means that any subsequent attempt to make contact with that server will just be ignored. "It can't be opened," Gnus will tell you, without making the least effort to see whether that is actually the case or not.

That might seem quite naughty, but it does make sense most of the time. Let's say you have 10 groups subscribed to on server `nephelococcygia.com'. This server is located somewhere quite far away from you and the machine is quite slow, so it takes 1 minute just to find out that it refuses connection to you today. If Gnus were to attempt to do that 10 times, you'd be quite annoyed, so Gnus won't attempt to do that. Once it has gotten a single "connection refused", it will regard that server as "down".

So, what happens if the machine was only feeling unwell temporarily? How do you test to see whether the machine has come up again?

You jump to the server buffer (see section 6.1 Server Buffer) and poke it with the following commands:

Try to establish connection to the server on the current line (gnus-server-open-server).

Close the connection (if any) to the server (gnus-server-close-server).

Mark the current server as unreachable (gnus-server-deny-server).

Open the connections to all servers in the buffer (gnus-server-open-all-servers).

Close the connections to all servers in the buffer (gnus-server-close-all-servers).

Remove all marks to whether Gnus was denied connection from any servers (gnus-server-remove-denials).

Set server status to offline (gnus-server-offline-server).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2 Getting News

A newsreader is normally used for reading news. Gnus currently provides only two methods of getting news--it can read from an NNTP server, or it can read from a local spool.

6.2.1 NNTP  Reading news from an NNTP server.
6.2.2 News Spool  Reading news from the local spool.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2.1 NNTP

Subscribing to a foreign group from an NNTP server is rather easy. You just specify nntp as method and the address of the NNTP server as the, uhm, address.

If the NNTP server is located at a non-standard port, setting the third element of the select method to this port number should allow you to connect to the right port. You'll have to edit the group info for that (see section 2.9 Foreign Groups).

The name of the foreign group can be the same as a native group. In fact, you can subscribe to the same group from as many different servers you feel like. There will be no name collisions.

The following variables can be used to create a virtual nntp server:

is run after a connection has been made. It can be used to send commands to the NNTP server after it has been contacted. By default it sends the command MODE READER to the server with the nntp-send-mode-reader function. This function should always be present in this hook.

This function will be used to send `AUTHINFO' to the NNTP server. The default function is nntp-send-authinfo, which looks through your `~/.authinfo' (or whatever you've set the nntp-authinfo-file variable to) for applicable entries. If none are found, it will prompt you for a login name and a password. The format of the `~/.authinfo' file is (almost) the same as the ftp `~/.netrc' file, which is defined in the ftp manual page, but here are the salient facts:

  1. The file contains one or more line, each of which define one server.

  2. Each line may contain an arbitrary number of token/value pairs.

    The valid tokens include `machine', `login', `password', `default'. In addition Gnus introduces two new tokens, not present in the original `.netrc'/ftp syntax, namely `port' and `force'. (This is the only way the `.authinfo' file format deviates from the `.netrc' file format.) `port' is used to indicate what port on the server the credentials apply to and `force' is explained below.

Here's an example file:

machine news.uio.no login larsi password geheimnis
machine nntp.ifi.uio.no login larsi force yes

The token/value pairs may appear in any order; `machine' doesn't have to be first, for instance.

In this example, both login name and password have been supplied for the former server, while the latter has only the login name listed, and the user will be prompted for the password. The latter also has the `force' tag, which means that the authinfo will be sent to the nntp server upon connection; the default (i.e., when there is not `force' tag) is to not send authinfo to the nntp server until the nntp server asks for it.

You can also add `default' lines that will apply to all servers that don't have matching `machine' lines.

default force yes

This will force sending `AUTHINFO' commands to all servers not previously mentioned.

Remember to not leave the `~/.authinfo' file world-readable.

This is a list of regexps to match on server types and actions to be taken when matches are made. For instance, if you want Gnus to beep every time you connect to innd, you could say something like:

(setq nntp-server-action-alist
      '(("innd" (ding))))

You probably don't want to do that, though.

The default value is

'(("nntpd 1\\.5\\.11t"
   (remove-hook 'nntp-server-opened-hook

This ensures that Gnus doesn't send the MODE READER command to nntpd 1.5.11t, since that command chokes that server, I've been told.

If the NNTP server doesn't support NOV headers, this back end will collect headers by sending a series of head commands. To speed things up, the back end sends lots of these commands without waiting for reply, and then reads all the replies. This is controlled by the nntp-maximum-request variable, and is 400 by default. If your network is buggy, you should set this to 1.

If you have lots of foreign nntp groups that you connect to regularly, you're sure to have problems with NNTP servers not responding properly, or being too loaded to reply within reasonable time. This is can lead to awkward problems, which can be helped somewhat by setting nntp-connection-timeout. This is an integer that says how many seconds the nntp back end should wait for a connection before giving up. If it is nil, which is the default, no timeouts are done.

If the NNTP server does not support NOV, you could set this variable to t, but nntp usually checks automatically whether NOV can be used.

List of strings used as commands to fetch NOV lines from a server. The default value of this variable is ("XOVER" "XOVERVIEW").

nntp normally sends just one big request for NOV lines to the server. The server responds with one huge list of lines. However, if you have read articles 2-5000 in the group, and only want to read article 1 and 5001, that means that nntp will fetch 4999 NOV lines that you will not need. This variable says how big a gap between two consecutive articles is allowed to be before the XOVER request is split into several request. Note that if your network is fast, setting this variable to a really small number means that fetching will probably be slower. If this variable is nil, nntp will never split requests. The default is 5.

A hook run before attempting to connect to an NNTP server.

If non-nil, nntp will log all commands it sends to the NNTP server (along with a timestamp) in the `*nntp-log*' buffer. This is useful if you are debugging a Gnus/NNTP connection that doesn't seem to work.

It is possible to customize how the connection to the nntp server will be opened. If you specify an nntp-open-connection-function parameter, Gnus will use that function to establish the connection. Six pre-made functions are supplied. These functions can be grouped in two categories: direct connection functions (four pre-made), and indirect ones (two pre-made).

A hook run just before posting an article. If there is no Message-ID header in the article and the news server provides the recommended ID, it will be added to the article before running this hook. It is useful to make Cancel-Lock headers even if you inhibit Gnus to add a Message-ID header, you could say:

(add-hook 'nntp-prepare-post-hook 'canlock-insert-header)

Note that not all servers support the recommended ID. This works for INN versions 2.3.0 and later, for instance. Direct Functions  Connecting directly to the server. Indirect Functions  Connecting indirectly to the server. Common Variables  Understood by several connection functions.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Direct Functions

These functions are called direct because they open a direct connection between your machine and the NNTP server. The behavior of these functions is also affected by commonly understood variables (see section Common Variables).

This is the default, and simply connects to some port or other on the remote system.

Opens a connection to a server over a secure channel. To use this you must have GNUTLS installed. You then define a server as follows:

;; "nntps" is port 563 and is predefined in our `/etc/services'
;; however, `gnutls-cli -p' doesn't like named ports.
(nntp "snews.bar.com"
      (nntp-open-connection-function nntp-open-tls-stream)
      (nntp-port-number )
      (nntp-address "snews.bar.com"))

Opens a connection to a server over a secure channel. To use this you must have OpenSSL or SSLeay installed. You then define a server as follows:

;; "snews" is port 563 and is predefined in our `/etc/services'
;; however, `openssl s_client -port' doesn't like named ports.
(nntp "snews.bar.com"
      (nntp-open-connection-function nntp-open-ssl-stream)
      (nntp-port-number 563)
      (nntp-address "snews.bar.com"))

Opens a connection to an NNTP server by simply `telnet''ing it. You might wonder why this function exists, since we have the default nntp-open-network-stream which would do the job. (One of) the reason(s) is that if you are behind a firewall but have direct connections to the outside world thanks to a command wrapper like runsocks, you can use it like this:

(nntp "socksified"
      (nntp-pre-command "runsocks")
      (nntp-open-connection-function nntp-open-telnet-stream)
      (nntp-address "the.news.server"))

With the default method, you would need to wrap your whole Emacs session, which is not a good idea.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Indirect Functions

These functions are called indirect because they connect to an intermediate host before actually connecting to the NNTP server. All of these functions and related variables are also said to belong to the "via" family of connection: they're all prefixed with "via" to make things cleaner. The behavior of these functions is also affected by commonly understood variables (see section Common Variables).

Does an `rlogin' on a remote system, and then does a `telnet' to the real NNTP server from there. This is useful for instance if you need to connect to a firewall machine first.

nntp-open-via-rlogin-and-telnet-specific variables:

Command used to log in on the intermediate host. The default is `rsh', but `ssh' is a popular alternative.

List of strings to be used as the switches to nntp-via-rlogin-command. The default is nil. If you use `ssh' for nntp-via-rlogin-command, you may set this to `("-C")' in order to compress all data connections, otherwise set this to `("-t" "-e" "none")' or `("-C" "-t" "-e" "none")' if the telnet command requires a pseudo-tty allocation on an intermediate host.

Does essentially the same, but uses `telnet' instead of `rlogin' to connect to the intermediate host.

nntp-open-via-telnet-and-telnet-specific variables:

Command used to telnet the intermediate host. The default is `telnet'.

List of strings to be used as the switches to the nntp-via-telnet-command command. The default is `("-8")'.

Password to use when logging in on the intermediate host.

If non-nil, the intermediate telnet session (client and server both) will support the ENVIRON option and not prompt for login name. This works for Solaris telnet, for instance.

Regexp matching the shell prompt on the intermediate host. The default is `bash\\|\$ *\r?$\\|> *\r?'.

Here are some additional variables that are understood by all the above functions:

User name to use when connecting to the intermediate host.

Address of the intermediate host to connect to.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Common Variables

The following variables affect the behavior of all, or several of the pre-made connection functions. When not specified, all functions are affected (the values of the following variables will be used as the default if each virtual nntp server doesn't specify those server variables individually).

A command wrapper to use when connecting through a non native connection function (all except nntp-open-network-stream, nntp-open-tls-stream, and nntp-open-ssl-stream). This is where you would put a `SOCKS' wrapper for instance.

The address of the NNTP server.

Port number to connect to the NNTP server. The default is `nntp'. If you use NNTP over TLS/SSL, you may want to use integer ports rather than named ports (i.e, use `563' instead of `snews' or `nntps'), because external TLS/SSL tools may not work with named ports.

String to use as end-of-line marker when talking to the NNTP server. This is `\r\n' by default, but should be `\n' when using a non native connection function.

Command to use when connecting to the NNTP server through `telnet'. This is not for an intermediate host. This is just for the real NNTP server. The default is `telnet'.

A list of switches to pass to nntp-telnet-command. The default is `("-8")'.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2.2 News Spool

Subscribing to a foreign group from the local spool is extremely easy, and might be useful, for instance, to speed up reading groups that contain very big articles---`alt.binaries.pictures.furniture', for instance.

Anyway, you just specify nnspool as the method and "" (or anything else) as the address.

If you have access to a local spool, you should probably use that as the native select method (see section 1.1 Finding the News). It is normally faster than using an nntp select method, but might not be. It depends. You just have to try to find out what's best at your site.

Program used to post an article.

Parameters given to the inews program when posting an article.

Where nnspool looks for the articles. This is normally `/usr/spool/news/'.

Where nnspool will look for NOV files. This is normally

Where the news lib dir is (`/usr/lib/news/' by default).

The name of the active file.

The name of the group descriptions file.

The name of the news history file.

The name of the active date file.

If non-nil, nnspool won't try to use any NOV files that it finds.

If non-nil, which is the default, use sed to get the relevant portion from the overview file. If nil, nnspool will load the entire file into a buffer and process it there.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3 Getting Mail

Reading mail with a newsreader--isn't that just plain WeIrD? But of course.

6.3.1 Mail in a Newsreader  Important introductory notes.
6.3.2 Getting Started Reading Mail  A simple cookbook example.
6.3.3 Splitting Mail  How to create mail groups.
6.3.4 Mail Sources  How to tell Gnus where to get mail from.
6.3.5 Mail Back End Variables  Variables for customizing mail handling.
6.3.6 Fancy Mail Splitting  Gnus can do hairy splitting of incoming mail.
6.3.7 Group Mail Splitting  Use group customize to drive mail splitting.
6.3.8 Incorporating Old Mail  What about the old mail you have?
6.3.9 Expiring Mail  Getting rid of unwanted mail.
6.3.10 Washing Mail  Removing cruft from the mail you get.
6.3.11 Duplicates  Dealing with duplicated mail.
6.3.12 Not Reading Mail  Using mail back ends for reading other files.
6.3.13 Choosing a Mail Back End  Gnus can read a variety of mail formats.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.1 Mail in a Newsreader

If you are used to traditional mail readers, but have decided to switch to reading mail with Gnus, you may find yourself experiencing something of a culture shock.

Gnus does not behave like traditional mail readers. If you want to make it behave that way, you can, but it's an uphill battle.

Gnus, by default, handles all its groups using the same approach. This approach is very newsreaderly--you enter a group, see the new/unread messages, and when you read the messages, they get marked as read, and you don't see them any more. (Unless you explicitly ask for them.)

In particular, you do not do anything explicitly to delete messages.

Does this mean that all the messages that have been marked as read are deleted? How awful!

But, no, it means that old messages are expired according to some scheme or other. For news messages, the expire process is controlled by the news administrator; for mail, the expire process is controlled by you. The expire process for mail is covered in depth in 6.3.9 Expiring Mail.

What many Gnus users find, after using it a while for both news and mail, is that the transport mechanism has very little to do with how they want to treat a message.

Many people subscribe to several mailing lists. These are transported via SMTP, and are therefore mail. But we might go for weeks without answering, or even reading these messages very carefully. We may not need to save them because if we should need to read one again, they are archived somewhere else.

Some people have local news groups which have only a handful of readers. These are transported via NNTP, and are therefore news. But we may need to read and answer a large fraction of the messages very carefully in order to do our work. And there may not be an archive, so we may need to save the interesting messages the same way we would personal mail.

The important distinction turns out to be not the transport mechanism, but other factors such as how interested we are in the subject matter, or how easy it is to retrieve the message if we need to read it again.

Gnus provides many options for sorting mail into "groups" which behave like newsgroups, and for treating each group (whether mail or news) differently.

Some users never get comfortable using the Gnus (ahem) paradigm and wish that Gnus should grow up and be a male, er, mail reader. It is possible to whip Gnus into a more mailreaderly being, but, as said before, it's not easy. People who prefer proper mail readers should try VM instead, which is an excellent, and proper, mail reader.

I don't mean to scare anybody off, but I want to make it clear that you may be required to learn a new way of thinking about messages. After you've been subjected to The Gnus Way, you will come to love it. I can guarantee it. (At least the guy who sold me the Emacs Subliminal Brain-Washing Functions that I've put into Gnus did guarantee it. You Will Be Assimilated. You Love Gnus. You Love The Gnus Mail Way. You Do.)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.2 Getting Started Reading Mail

It's quite easy to use Gnus to read your new mail. You just plonk the mail back end of your choice into gnus-secondary-select-methods, and things will happen automatically.

For instance, if you want to use nnml (which is a "one file per mail" back end), you could put the following in your `~/.gnus.el' file:

(setq gnus-secondary-select-methods '((nnml "")))

Now, the next time you start Gnus, this back end will be queried for new articles, and it will move all the messages in your spool file to its directory, which is `~/Mail/' by default. The new group that will be created (`mail.misc') will be subscribed, and you can read it like any other group.

You will probably want to split the mail into several groups, though:

(setq nnmail-split-methods
      '(("junk" "^From:.*Lars Ingebrigtsen")
        ("crazy" "^Subject:.*die\\|^Organization:.*flabby")
        ("other" "")))

This will result in three new nnml mail groups being created: `nnml:junk', `nnml:crazy', and `nnml:other'. All the mail that doesn't fit into the first two groups will be placed in the last group.

This should be sufficient for reading mail with Gnus. You might want to give the other sections in this part of the manual a perusal, though. Especially see section 6.3.13 Choosing a Mail Back End and see section 6.3.9 Expiring Mail.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.3 Splitting Mail

The nnmail-split-methods variable says how the incoming mail is to be split into groups.

(setq nnmail-split-methods
  '(("mail.junk" "^From:.*Lars Ingebrigtsen")
    ("mail.crazy" "^Subject:.*die\\|^Organization:.*flabby")
    ("mail.other" "")))

This variable is a list of lists, where the first element of each of these lists is the name of the mail group (they do not have to be called something beginning with `mail', by the way), and the second element is a regular expression used on the header of each mail to determine if it belongs in this mail group. The first string may contain `\\1' forms, like the ones used by replace-match to insert sub-expressions from the matched text. For instance:

("list.\\1" "From:.* \\(.*\\)-list@majordomo.com")

In that case, nnmail-split-lowercase-expanded controls whether the inserted text should be made lowercase. See section 6.3.6 Fancy Mail Splitting.

The second element can also be a function. In that case, it will be called narrowed to the headers with the first element of the rule as the argument. It should return a non-nil value if it thinks that the mail belongs in that group.

The last of these groups should always be a general one, and the regular expression should always be `""' so that it matches any mails that haven't been matched by any of the other regexps. (These rules are processed from the beginning of the alist toward the end. The first rule to make a match will "win", unless you have crossposting enabled. In that case, all matching rules will "win".) If no rule matched, the mail will end up in the `bogus' group. When new groups are created by splitting mail, you may want to run gnus-group-find-new-groups to see the new groups. This also applies to the `bogus' group.

If you like to tinker with this yourself, you can set this variable to a function of your choice. This function will be called without any arguments in a buffer narrowed to the headers of an incoming mail message. The function should return a list of group names that it thinks should carry this mail message.

Note that the mail back ends are free to maul the poor, innocent, incoming headers all they want to. They all add Lines headers; some add X-Gnus-Group headers; most rename the Unix mbox From<SPACE> line to something else.

The mail back ends all support cross-posting. If several regexps match, the mail will be "cross-posted" to all those groups. nnmail-crosspost says whether to use this mechanism or not. Note that no articles are crossposted to the general (`""') group.

nnmh and nnml makes crossposts by creating hard links to the crossposted articles. However, not all file systems support hard links. If that's the case for you, set nnmail-crosspost-link-function to copy-file. (This variable is add-name-to-file by default.)

If you wish to see where the previous mail split put the messages, you can use the M-x nnmail-split-history command. If you wish to see where re-spooling messages would put the messages, you can use gnus-summary-respool-trace and related commands (see section 3.25 Mail Group Commands).

Header lines longer than the value of nnmail-split-header-length-limit are excluded from the split function.

By default the splitting codes MIME decodes headers so you can match on non-ASCII strings. The nnmail-mail-splitting-charset variable specifies the default charset for decoding. The behavior can be turned off completely by binding nnmail-mail-splitting-decodes to nil, which is useful if you want to match articles based on the raw header data.

By default, splitting is performed on all incoming messages. If you specify a directory entry for the variable mail-sources (see section Mail Source Specifiers), however, then splitting does not happen by default. You can set the variable nnmail-resplit-incoming to a non-nil value to make splitting happen even in this case. (This variable has no effect on other kinds of entries.)

Gnus gives you all the opportunity you could possibly want for shooting yourself in the foot. Let's say you create a group that will contain all the mail you get from your boss. And then you accidentally unsubscribe from the group. Gnus will still put all the mail from your boss in the unsubscribed group, and so, when your boss mails you "Have that report ready by Monday or you're fired!", you'll never see it and, come Tuesday, you'll still believe that you're gainfully employed while you really should be out collecting empty bottles to save up for next month's rent money.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.4 Mail Sources

Mail can be gotten from many different sources--the mail spool, from a POP mail server, from a procmail directory, or from a maildir, for instance. Mail Source Specifiers  How to specify what a mail source is. Mail Source Customization  Some variables that influence things. Fetching Mail  Using the mail source specifiers.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Mail Source Specifiers

You tell Gnus how to fetch mail by setting mail-sources (see section Fetching Mail) to a mail source specifier.

Here's an example:

(pop :server "pop3.mailserver.com" :user "myname")

As can be observed, a mail source specifier is a list where the first element is a mail source type, followed by an arbitrary number of keywords. Keywords that are not explicitly specified are given default values.

The following mail source types are available:

Get mail from a single file; typically from the mail spool.


The file name. Defaults to the value of the MAIL environment variable or the value of rmail-spool-directory (usually something like `/usr/mail/spool/user-name').

Script run before/after fetching mail.

An example file mail source:

(file :path "/usr/spool/mail/user-name")

Or using the default file name:


If the mail spool file is not located on the local machine, it's best to use POP or IMAP or the like to fetch the mail. You can not use ange-ftp file names here--it has no way to lock the mail spool while moving the mail.

If it's impossible to set up a proper server, you can use ssh instead.

(setq mail-sources
      '((file :prescript "ssh host bin/getmail >%t")))

The `getmail' script would look something like the following:

#  getmail - move mail from spool to stdout
#  flu@iki.fi

rm -f $TMP; $MOVEMAIL $MAIL $TMP >/dev/null && cat $TMP

Alter this script to fit find the `movemail' you want to use.

Get mail from several files in a directory. This is typically used when you have procmail split the incoming mail into several files. That is, there is a one-to-one correspondence between files in that directory and groups, so that mail from the file `foo.bar.spool' will be put in the group foo.bar. (You can change the suffix to be used instead of .spool.) Setting nnmail-scan-directory-mail-source-once to non-nil forces Gnus to scan the mail source only once. This is particularly useful if you want to scan mail groups at a specified level.

There is also the variable nnmail-resplit-incoming, if you set that to a non-nil value, then the normal splitting process is applied to all the files from the directory, 6.3.3 Splitting Mail.


The name of the directory where the files are. There is no default value.

Only files ending with this suffix are used. The default is `.spool'.

Only files that have this predicate return non-nil are returned. The default is identity. This is used as an additional filter--only files that have the right suffix and satisfy this predicate are considered.

Script run before/after fetching mail.

An example directory mail source:

(directory :path "/home/user-name/procmail-dir/"
           :suffix ".prcml")

Get mail from a POP server.


The name of the POP server. The default is taken from the MAILHOST environment variable.

The port number of the POP server. This can be a number (eg, `:port 1234') or a string (eg, `:port "pop3"'). If it is a string, it should be a service name as listed in `/etc/services' on Unix systems. The default is `"pop3"'. On some systems you might need to specify it as `"pop-3"' instead.

The user name to give to the POP server. The default is the login name.

The password to give to the POP server. If not specified, the user is prompted.

The program to use to fetch mail from the POP server. This should be a format-like string. Here's an example:

fetchmail %u@%s -P %p %t

The valid format specifier characters are:

The name of the file the mail is to be moved to. This must always be included in this string.

The name of the server.

The port number of the server.

The user name to use.

The password to use.

The values used for these specs are taken from the values you give the corresponding keywords.

A script to be run before fetching the mail. The syntax is the same as the :program keyword. This can also be a function to be run.

A script to be run after fetching the mail. The syntax is the same as the :program keyword. This can also be a function to be run.

The function to use to fetch mail from the POP server. The function is called with one parameter--the name of the file where the mail should be moved to.

This can be either the symbol password or the symbol apop and says what authentication scheme to use. The default is password.

If the :program and :function keywords aren't specified, pop3-movemail will be used. If the pop3-leave-mail-on-server is non-nil the mail is to be left on the POP server after fetching when using pop3-movemail. Note that POP servers maintain no state information between sessions, so what the client believes is there and what is actually there may not match up. If they do not, then the whole thing can fall apart and leave you with a corrupt mailbox.

Here are some examples. Fetch from the default POP server, using the default user name, and default fetcher:


Fetch from a named server with a named user and password:

(pop :server "my.pop.server"
     :user "user-name" :password "secret")

Use `movemail' to move the mail:

(pop :program "movemail po:%u %t %p")

Get mail from a maildir. This is a type of mailbox that is supported by at least qmail and postfix, where each file in a special directory contains exactly one mail.


The name of the directory where the mails are stored. The default is taken from the MAILDIR environment variable or `~/Maildir/'.
The subdirectories of the Maildir. The default is `("new" "cur")'.

You can also get mails from remote hosts (because maildirs don't suffer from locking problems).

Two example maildir mail sources:

(maildir :path "/home/user-name/Maildir/"
         :subdirs ("cur" "new"))

(maildir :path "/user@remotehost.org:~/Maildir/"
         :subdirs ("new"))

Get mail from a IMAP server. If you don't want to use IMAP as intended, as a network mail reading protocol (ie with nnimap), for some reason or other, Gnus let you treat it similar to a POP server and fetches articles from a given IMAP mailbox. See section 6.5 IMAP, for more information.

Note that for the Kerberos, GSSAPI, TLS/SSL and STARTTLS support you may need external programs and libraries, See section 6.5 IMAP.


The name of the IMAP server. The default is taken from the MAILHOST environment variable.

The port number of the IMAP server. The default is `143', or `993' for TLS/SSL connections.

The user name to give to the IMAP server. The default is the login name.

The password to give to the IMAP server. If not specified, the user is prompted.

What stream to use for connecting to the server, this is one of the symbols in imap-stream-alist. Right now, this means `gssapi', `kerberos4', `starttls', `tls', `ssl', `shell' or the default `network'.

Which authenticator to use for authenticating to the server, this is one of the symbols in imap-authenticator-alist. Right now, this means `gssapi', `kerberos4', `digest-md5', `cram-md5', `anonymous' or the default `login'.

When using the `shell' :stream, the contents of this variable is mapped into the imap-shell-program variable. This should be a format-like string (or list of strings). Here's an example:

ssh %s imapd

The valid format specifier characters are:

The name of the server.

User name from imap-default-user.

The port number of the server.

The values used for these specs are taken from the values you give the corresponding keywords.

The name of the mailbox to get mail from. The default is `INBOX' which normally is the mailbox which receive incoming mail.

The predicate used to find articles to fetch. The default, `UNSEEN UNDELETED', is probably the best choice for most people, but if you sometimes peek in your mailbox with a IMAP client and mark some articles as read (or; SEEN) you might want to set this to `1:*'. Then all articles in the mailbox is fetched, no matter what. For a complete list of predicates, see RFC 2060 section 6.4.4.

How to flag fetched articles on the server, the default `\Deleted' will mark them as deleted, an alternative would be `\Seen' which would simply mark them as read. These are the two most likely choices, but more flags are defined in RFC 2060 section 2.3.2.

If non-nil, don't remove all articles marked as deleted in the mailbox after finishing the fetch.

An example IMAP mail source:

(imap :server "mail.mycorp.com"
      :stream kerberos4
      :fetchflag "\\Seen")

Get mail from a webmail server, such as http://www.hotmail.com/, http://webmail.netscape.com/, http://www.netaddress.com/, http://mail.yahoo.com/.

NOTE: Webmail largely depends on cookies. A "one-line-cookie" patch is required for url "4.0pre.46".

WARNING: Mails may be lost. NO WARRANTY.


The type of the webmail server. The default is hotmail. The alternatives are netscape, netaddress, my-deja.

The user name to give to the webmail server. The default is the login name.

The password to give to the webmail server. If not specified, the user is prompted.

If non-nil, only fetch unread articles and don't move them to trash folder after finishing the fetch.

An example webmail source:

(webmail :subtype 'hotmail
         :user "user-name"
         :password "secret")

Common Keywords
Common keywords can be used in any type of mail source.


If non-nil, fetch the mail even when Gnus is unplugged. If you use directory source to get mail, you can specify it as in this example:

(setq mail-sources
      '((directory :path "/home/pavel/.Spool/"
                   :suffix ""
                   :plugged t)))

Gnus will then fetch your mail even when you are unplugged. This is useful when you use local mail and news.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Function Interface

Some of the above keywords specify a Lisp function to be executed. For each keyword :foo, the Lisp variable foo is bound to the value of the keyword while the function is executing. For example, consider the following mail-source setting:

(setq mail-sources '((pop :user "jrl"
                          :server "pophost" :function fetchfunc)))

While the function fetchfunc is executing, the symbol user is bound to "jrl", and the symbol server is bound to "pophost". The symbols port, password, program, prescript, postscript, function, and authentication are also bound (to their default values).

See above for a list of keywords for each type of mail source.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Mail Source Customization

The following is a list of variables that influence how the mail is fetched. You would normally not need to set or change any of these variables.

File where mail will be stored while processing it. The default is

If non-nil, delete incoming files after handling them. If t, delete the files immediately, if nil, never delete any files. If a positive number, delete files older than number of days (This will only happen, when receiving new mail). You may also set mail-source-delete-incoming to nil and call mail-source-delete-old-incoming from a hook or interactively.

If non-nil, ask for for confirmation before deleting old incoming files. This variable only applies when mail-source-delete-incoming is a positive number.

If non-nil, ignore errors when reading mail from a mail source.

Directory where incoming mail source files (if any) will be stored. The default is `~/Mail/'. At present, the only thing this is used for is to say where the incoming files will be stored if the variable mail-source-delete-incoming is nil or a number.

Prefix for file name for storing incoming mail. The default is `Incoming', in which case files will end up with names like `Incoming30630D_' or `Incoming298602ZD'. This is really only relevant if mail-source-delete-incoming is nil or a number.

All new mail files will get this file mode. The default is 384.

If non-nil, name of program for fetching new mail. If nil, movemail in exec-directory.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Fetching Mail

The way to actually tell Gnus where to get new mail from is to set mail-sources to a list of mail source specifiers (see section Mail Source Specifiers).

If this variable (and the obsolescent nnmail-spool-file) is nil, the mail back ends will never attempt to fetch mail by themselves.

If you want to fetch mail both from your local spool as well as a POP mail server, you'd say something like:

(setq mail-sources
        (pop :server "pop3.mail.server"
             :password "secret")))

Or, if you don't want to use any of the keyword defaults:

(setq mail-sources
      '((file :path "/var/spool/mail/user-name")
        (pop :server "pop3.mail.server"
             :user "user-name"
             :port "pop3"
             :password "secret")))

When you use a mail back end, Gnus will slurp all your mail from your inbox and plonk it down in your home directory. Gnus doesn't move any mail if you're not using a mail back end--you have to do a lot of magic invocations first. At the time when you have finished drawing the pentagram, lightened the candles, and sacrificed the goat, you really shouldn't be too surprised when Gnus moves your mail.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.5 Mail Back End Variables

These variables are (for the most part) pertinent to all the various mail back ends.

The mail back ends all call this hook after reading new mail. You can use this hook to notify any mail watch programs, if you want to.

Hook run in the buffer where the mail headers of each message is kept just before the splitting based on these headers is done. The hook is free to modify the buffer contents in any way it sees fit--the buffer is discarded after the splitting has been done, and no changes performed in the buffer will show up in any files. gnus-article-decode-encoded-words is one likely function to add to this hook.

These are two useful hooks executed when treating new incoming mail---nnmail-pre-get-new-mail-hook (is called just before starting to handle the new mail) and nnmail-post-get-new-mail-hook (is called when the mail handling is done). Here's and example of using these two hooks to change the default file modes the new mail files get:

(add-hook 'nnmail-pre-get-new-mail-hook
          (lambda () (set-default-file-modes 511)))

(add-hook 'nnmail-post-get-new-mail-hook
          (lambda () (set-default-file-modes 551)))

If non-nil, the mail back ends will use long file and directory names. Groups like `mail.misc' will end up in directories (assuming use of nnml back end) or files (assuming use of nnfolder back end) like `mail.misc'. If it is nil, the same group will end up in `mail/misc'.

Function called to delete files. It is delete-file by default.

If non-nil, put the Message-IDs of articles imported into the back end (via Gcc, for instance) into the mail duplication discovery cache. The default is nil.

This can be a regular expression or a list of regular expressions. Group names that match any of the regular expressions will never be recorded in the Message-ID cache.

This can be useful, for example, when using Fancy Splitting (see section 6.3.6 Fancy Mail Splitting) together with the function nnmail-split-fancy-with-parent.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.6 Fancy Mail Splitting

If the rather simple, standard method for specifying how to split mail doesn't allow you to do what you want, you can set nnmail-split-methods to nnmail-split-fancy. Then you can play with the nnmail-split-fancy variable.

Let's look at an example value of this variable first:

;; Messages from the mailer daemon are not crossposted to any of
;; the ordinary groups.  Warnings are put in a separate group
;; from real errors.
(| ("from" mail (| ("subject" "warn.*" "mail.warning")
   ;; Non-error messages are crossposted to all relevant
   ;; groups, but we don't crosspost between the group for the
   ;; (ding) list and the group for other (ding) related mail.
   (& (| (any "ding@ifi\\.uio\\.no" "ding.list")
         ("subject" "ding" "ding.misc"))
      ;; Other mailing lists...
      (any "procmail@informatik\\.rwth-aachen\\.de" "procmail.list")
      (any "SmartList@informatik\\.rwth-aachen\\.de" "SmartList.list")
      ;; Both lists below have the same suffix, so prevent
      ;; cross-posting to mkpkg.list of messages posted only to
      ;; the bugs- list, but allow cross-posting when the
      ;; message was really cross-posted.
      (any "bugs-mypackage@somewhere" "mypkg.bugs")
      (any "mypackage@somewhere" - "bugs-mypackage" "mypkg.list")
      ;; People...
      (any "larsi@ifi\\.uio\\.no" "people.Lars_Magne_Ingebrigtsen"))
   ;; Unmatched mail goes to the catch all group.

This variable has the format of a split. A split is a (possibly) recursive structure where each split may contain other splits. Here are the possible split syntaxes:

If the split is a string, that will be taken as a group name. Normal regexp match expansion will be done. See below for examples.

(field value [- restrict [...] ] split [invert-partial])
The split can be a list containing at least three elements. If the first element field (a regexp matching a header) contains value (also a regexp) then store the message as specified by split.

If restrict (yet another regexp) matches some string after field and before the end of the matched value, the split is ignored. If none of the restrict clauses match, split is processed.

The last element invert-partial is optional. If it is non-nil, the match-partial-words behavior controlled by the variable nnmail-split-fancy-match-partial-words (see below) is be inverted. (New in Gnus 5.10.7)

(| split ...)
If the split is a list, and the first element is | (vertical bar), then process each split until one of them matches. A split is said to match if it will cause the mail message to be stored in one or more groups.

(& split ...)
If the split is a list, and the first element is &, then process all splits in the list.

If the split is the symbol junk, then don't save (i.e., delete) this message. Use with extreme caution.

(: function arg1 arg2 ...)
If the split is a list, and the first element is `:', then the second element will be called as a function with args given as arguments. The function should return a split.

For instance, the following function could be used to split based on the body of the messages:

(defun split-on-body ()
      (goto-char (point-min))
      (when (re-search-forward "Some.*string" nil t)

The buffer is narrowed to the message in question when function is run. That's why (widen) needs to be called after save-excursion and save-restriction in the example above. Also note that with the nnimap backend, message bodies will not be downloaded by default. You need to set nnimap-split-download-body to t to do that (see section 6.5.1 Splitting in IMAP).

(! func split)
If the split is a list, and the first element is !, then split will be processed, and func will be called as a function with the result of split as argument. func should return a split.

If the split is nil, it is ignored.

In these splits, field must match a complete field name.

Normally, value in these splits must match a complete word according to the fundamental mode syntax table. In other words, all value's will be implicitly surrounded by \<...\> markers, which are word delimiters. Therefore, if you use the following split, for example,

(any "joe" "joemail")

messages sent from `joedavis@foo.org' will normally not be filed in `joemail'. If you want to alter this behavior, you can use any of the following three ways:

  1. You can set the nnmail-split-fancy-match-partial-words variable to non-nil in order to ignore word boundaries and instead the match becomes more like a grep. This variable controls whether partial words are matched during fancy splitting. The default value is nil.

    Note that it influences all value's in your split rules.

  2. value beginning with .* ignores word boundaries in front of a word. Similarly, if value ends with .*, word boundaries in the rear of a word will be ignored. For example, the value "@example\\.com" does not match `foo@example.com' but ".*@example\\.com" does.

  3. You can set the invert-partial flag in your split rules of the `(field value ...)' types, aforementioned in this section. If the flag is set, word boundaries on both sides of a word are ignored even if nnmail-split-fancy-match-partial-words is nil. Contrarily, if the flag is set, word boundaries are not ignored even if nnmail-split-fancy-match-partial-words is non-nil. (New in Gnus 5.10.7)

field and value can also be Lisp symbols, in that case they are expanded as specified by the variable nnmail-split-abbrev-alist. This is an alist of cons cells, where the CAR of a cell contains the key, and the CDR contains the associated value. Predefined entries in nnmail-split-abbrev-alist include:

Matches the `From', `Sender' and `Resent-From' fields.
Matches the `To', `Cc', `Apparently-To', `Resent-To' and `Resent-Cc' fields.
Is the union of the from and to entries.

nnmail-split-fancy-syntax-table is the syntax table in effect when all this splitting is performed.

If you want to have Gnus create groups dynamically based on some information in the headers (i.e., do replace-match-like substitutions in the group names), you can say things like:

(any "debian-\\b\\(\\w+\\)@lists.debian.org" "mail.debian.\\1")

In this example, messages sent to `debian-foo@lists.debian.org' will be filed in `mail.debian.foo'.

If the string contains the element `\&', then the previously matched string will be substituted. Similarly, the elements `\\1' up to `\\9' will be substituted with the text matched by the groupings 1 through 9.

Where nnmail-split-lowercase-expanded controls whether the lowercase of the matched string should be used for the substitution. Setting it as non-nil is useful to avoid the creation of multiple groups when users send to an address using different case (i.e. mailing-list@domain vs Mailing-List@Domain). The default value is t.

nnmail-split-fancy-with-parent is a function which allows you to split followups into the same groups their parents are in. Sometimes you can't make splitting rules for all your mail. For example, your boss might send you personal mail regarding different projects you are working on, and as you can't tell your boss to put a distinguishing string into the subject line, you have to resort to manually moving the messages into the right group. With this function, you only have to do it once per thread.

To use this feature, you have to set nnmail-treat-duplicates and nnmail-cache-accepted-message-ids to a non-nil value. And then you can include nnmail-split-fancy-with-parent using the colon feature, like so:

(setq nnmail-treat-duplicates 'warn     ; or delete
      nnmail-cache-accepted-message-ids t
      '(| (: nnmail-split-fancy-with-parent)
          ;; other splits go here

This feature works as follows: when nnmail-treat-duplicates is non-nil, Gnus records the message id of every message it sees in the file specified by the variable nnmail-message-id-cache-file, together with the group it is in (the group is omitted for non-mail messages). When mail splitting is invoked, the function nnmail-split-fancy-with-parent then looks at the References (and In-Reply-To) header of each message to split and searches the file specified by nnmail-message-id-cache-file for the message ids. When it has found a parent, it returns the corresponding group name unless the group name matches the regexp nnmail-split-fancy-with-parent-ignore-groups. It is recommended that you set nnmail-message-id-cache-length to a somewhat higher number than the default so that the message ids are still in the cache. (A value of 5000 appears to create a file some 300 kBytes in size.) When nnmail-cache-accepted-message-ids is non-nil, Gnus also records the message ids of moved articles, so that the followup messages goes into the new group.

Also see the variable nnmail-cache-ignore-groups if you don't want certain groups to be recorded in the cache. For example, if all outgoing messages are written to an "outgoing" group, you could set nnmail-cache-ignore-groups to match that group name. Otherwise, answers to all your messages would end up in the "outgoing" group.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.7 Group Mail Splitting

If you subscribe to dozens of mailing lists but you don't want to maintain mail splitting rules manually, group mail splitting is for you. You just have to set to-list and/or to-address in group parameters or group customization and set nnmail-split-methods to gnus-group-split. This splitting function will scan all groups for those parameters and split mail accordingly, i.e., messages posted from or to the addresses specified in the parameters to-list or to-address of a mail group will be stored in that group.

Sometimes, mailing lists have multiple addresses, and you may want mail splitting to recognize them all: just set the extra-aliases group parameter to the list of additional addresses and it's done. If you'd rather use a regular expression, set split-regexp.

All these parameters in a group will be used to create an nnmail-split-fancy split, in which the field is `any', the value is a single regular expression that matches to-list, to-address, all of extra-aliases and all matches of split-regexp, and the split is the name of the group. restricts are also supported: just set the split-exclude parameter to a list of regular expressions.

If you can't get the right split to be generated using all these parameters, or you just need something fancier, you can set the parameter split-spec to an nnmail-split-fancy split. In this case, all other aforementioned parameters will be ignored by gnus-group-split. In particular, split-spec may be set to nil, in which case the group will be ignored by gnus-group-split.

gnus-group-split will do cross-posting on all groups that match, by defining a single & fancy split containing one split for each group. If a message doesn't match any split, it will be stored in the group named in gnus-group-split-default-catch-all-group, unless some group has split-spec set to catch-all, in which case that group is used as the catch-all group. Even though this variable is often used just to name a group, it may also be set to an arbitrarily complex fancy split (after all, a group name is a fancy split), and this may be useful to split mail that doesn't go to any mailing list to personal mail folders. Note that this fancy split is added as the last element of a | split list that also contains a & split with the rules extracted from group parameters.

It's time for an example. Assume the following group parameters have been defined:

((to-address . "bar@femail.com")
 (split-regexp . ".*@femail\\.com"))
((to-list . "foo@nowhere.gov")
 (extra-aliases "foo@localhost" "foo-redist@home")
 (split-exclude "bugs-foo" "rambling-foo")
 (admin-address . "foo-request@nowhere.gov"))
((split-spec . catch-all))

Setting nnmail-split-methods to gnus-group-split will behave as if nnmail-split-fancy had been selected and variable nnmail-split-fancy had been set as follows:

(| (& (any "\\(bar@femail\\.com\\|.*@femail\\.com\\)" "mail.bar")
      (any "\\(foo@nowhere\\.gov\\|foo@localhost\\|foo-redist@home\\)"
           - "bugs-foo" - "rambling-foo" "mail.foo"))

If you'd rather not use group splitting for all your mail groups, you may use it for only some of them, by using nnmail-split-fancy splits like this:

(: gnus-group-split-fancy groups no-crosspost catch-all)

groups may be a regular expression or a list of group names whose parameters will be scanned to generate the output split. no-crosspost can be used to disable cross-posting; in this case, a single | split will be output. catch-all is the fall back fancy split, used like gnus-group-split-default-catch-all-group. If catch-all is nil, or if split-regexp matches the empty string in any selected group, no catch-all split will be issued. Otherwise, if some group has split-spec set to catch-all, this group will override the value of the catch-all argument.

Unfortunately, scanning all groups and their parameters can be quite slow, especially considering that it has to be done for every message. But don't despair! The function gnus-group-split-setup can be used to enable gnus-group-split in a much more efficient way. It sets nnmail-split-methods to nnmail-split-fancy and sets nnmail-split-fancy to the split produced by gnus-group-split-fancy. Thus, the group parameters are only scanned once, no matter how many messages are split.

However, if you change group parameters, you'd have to update nnmail-split-fancy manually. You can do it by running gnus-group-split-update. If you'd rather have it updated automatically, just tell gnus-group-split-setup to do it for you. For example, add to your `~/.gnus.el':

(gnus-group-split-setup auto-update catch-all)

If auto-update is non-nil, gnus-group-split-update will be added to nnmail-pre-get-new-mail-hook, so you won't ever have to worry about updating nnmail-split-fancy again. If you don't omit catch-all (it's optional, equivalent to nil), gnus-group-split-default-catch-all-group will be set to its value.

Because you may want to change nnmail-split-fancy after it is set by gnus-group-split-update, this function will run gnus-group-split-updated-hook just before finishing.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.8 Incorporating Old Mail

Most people have lots of old mail stored in various file formats. If you have set up Gnus to read mail using one of the spiffy Gnus mail back ends, you'll probably wish to have that old mail incorporated into your mail groups.

Doing so can be quite easy.

To take an example: You're reading mail using nnml (see section Mail Spool), and have set nnmail-split-methods to a satisfactory value (see section 6.3.3 Splitting Mail). You have an old Unix mbox file filled with important, but old, mail. You want to move it into your nnml groups.

Here's how:

  1. Go to the group buffer.

  2. Type G f and give the file name to the mbox file when prompted to create an nndoc group from the mbox file (see section 2.9 Foreign Groups).

  3. Type SPACE to enter the newly created group.

  4. Type M P b to process-mark all articles in this group's buffer (see section 3.7.6 Setting Process Marks).

  5. Type B r to respool all the process-marked articles, and answer `nnml' when prompted (see section 3.25 Mail Group Commands).

All the mail messages in the mbox file will now also be spread out over all your nnml groups. Try entering them and check whether things have gone without a glitch. If things look ok, you may consider deleting the mbox file, but I wouldn't do that unless I was absolutely sure that all the mail has ended up where it should be.

Respooling is also a handy thing to do if you're switching from one mail back end to another. Just respool all the mail in the old mail groups using the new mail back end.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.9 Expiring Mail

Traditional mail readers have a tendency to remove mail articles when you mark them as read, in some way. Gnus takes a fundamentally different approach to mail reading.

Gnus basically considers mail just to be news that has been received in a rather peculiar manner. It does not think that it has the power to actually change the mail, or delete any mail messages. If you enter a mail group, and mark articles as "read", or kill them in some other fashion, the mail articles will still exist on the system. I repeat: Gnus will not delete your old, read mail. Unless you ask it to, of course.

To make Gnus get rid of your unwanted mail, you have to mark the articles as expirable. (With the default key bindings, this means that you have to type E.) This does not mean that the articles will disappear right away, however. In general, a mail article will be deleted from your system if, 1) it is marked as expirable, AND 2) it is more than one week old. If you do not mark an article as expirable, it will remain on your system until hell freezes over. This bears repeating one more time, with some spurious capitalizations: IF you do NOT mark articles as EXPIRABLE, Gnus will NEVER delete those ARTICLES.

You do not have to mark articles as expirable by hand. Gnus provides two features, called "auto-expire" and "total-expire", that can help you with this. In a nutshell, "auto-expire" means that Gnus hits E for you when you select an article. And "total-expire" means that Gnus considers all articles as expirable that are read. So, in addition to the articles marked `E', also the articles marked `r', `R', `O', `K', `Y' and so on are considered expirable.

When should either auto-expire or total-expire be used? Most people who are subscribed to mailing lists split each list into its own group and then turn on auto-expire or total-expire for those groups. (See section 6.3.3 Splitting Mail, for more information on splitting each list into its own group.)

Which one is better, auto-expire or total-expire? It's not easy to answer. Generally speaking, auto-expire is probably faster. Another advantage of auto-expire is that you get more marks to work with: for the articles that are supposed to stick around, you can still choose between tick and dormant and read marks. But with total-expire, you only have dormant and ticked to choose from. The advantage of total-expire is that it works well with adaptive scoring (see section 7.6 Adaptive Scoring). Auto-expire works with normal scoring but not with adaptive scoring.

Groups that match the regular expression gnus-auto-expirable-newsgroups will have all articles that you read marked as expirable automatically. All articles marked as expirable have an `E' in the first column in the summary buffer.

By default, if you have auto expiry switched on, Gnus will mark all the articles you read as expirable, no matter if they were read or unread before. To avoid having articles marked as read marked as expirable automatically, you can put something like the following in your `~/.gnus.el' file:

(remove-hook 'gnus-mark-article-hook
(add-hook 'gnus-mark-article-hook 'gnus-summary-mark-unread-as-read)

Note that making a group auto-expirable doesn't mean that all read articles are expired--only the articles marked as expirable will be expired. Also note that using the d command won't make articles expirable--only semi-automatic marking of articles as read will mark the articles as expirable in auto-expirable groups.

Let's say you subscribe to a couple of mailing lists, and you want the articles you have read to disappear after a while:

(setq gnus-auto-expirable-newsgroups

Another way to have auto-expiry happen is to have the element auto-expire in the group parameters of the group.

If you use adaptive scoring (see section 7.6 Adaptive Scoring) and auto-expiring, you'll have problems. Auto-expiring and adaptive scoring don't really mix very well.

The nnmail-expiry-wait variable supplies the default time an expirable article has to live. Gnus starts counting days from when the message arrived, not from when it was sent. The default is seven days.

Gnus also supplies a function that lets you fine-tune how long articles are to live, based on what group they are in. Let's say you want to have one month expiry period in the `mail.private' group, a one day expiry period in the `mail.junk' group, and a six day expiry period everywhere else:

(setq nnmail-expiry-wait-function
      (lambda (group)
       (cond ((string= group "mail.private")
             ((string= group "mail.junk")
             ((string= group "important")

The group names this function is fed are "unadorned" group names--no `nnml:' prefixes and the like.

The nnmail-expiry-wait variable and nnmail-expiry-wait-function function can either be a number (not necessarily an integer) or one of the symbols immediate or never.

You can also use the expiry-wait group parameter to selectively change the expiry period (see section 2.10 Group Parameters).

The normal action taken when expiring articles is to delete them. However, in some circumstances it might make more sense to move them to other groups instead of deleting them. The variable nnmail-expiry-target (and the expiry-target group parameter) controls this. The variable supplies a default value for all groups, which can be overridden for specific groups by the group parameter. default value is delete, but this can also be a string (which should be the name of the group the message should be moved to), or a function (which will be called in a buffer narrowed to the message in question, and with the name of the group being moved from as its parameter) which should return a target--either a group name or delete.

Here's an example for specifying a group name:

(setq nnmail-expiry-target "nnml:expired")

Gnus provides a function nnmail-fancy-expiry-target which will expire mail to groups according to the variable nnmail-fancy-expiry-targets. Here's an example:

 (setq nnmail-expiry-target 'nnmail-fancy-expiry-target
       '((to-from "boss" "nnfolder:Work")
         ("subject" "IMPORTANT" "nnfolder:IMPORTANT.%Y.%b")
         ("from" ".*" "nnfolder:Archive-%Y")))

With this setup, any mail that has IMPORTANT in its Subject header and was sent in the year YYYY and month MMM, will get expired to the group nnfolder:IMPORTANT.YYYY.MMM. If its From or To header contains the string boss, it will get expired to nnfolder:Work. All other mail will get expired to nnfolder:Archive-YYYY.

If nnmail-keep-last-article is non-nil, Gnus will never expire the final article in a mail newsgroup. This is to make life easier for procmail users.

By the way: That line up there, about Gnus never expiring non-expirable articles, is a lie. If you put total-expire in the group parameters, articles will not be marked as expirable, but all read articles will be put through the expiry process. Use with extreme caution. Even more dangerous is the gnus-total-expirable-newsgroups variable. All groups that match this regexp will have all read articles put through the expiry process, which means that all old mail articles in the groups in question will be deleted after a while. Use with extreme caution, and don't come crying to me when you discover that the regexp you used matched the wrong group and all your important mail has disappeared. Be a man! Or a woman! Whatever you feel more comfortable with! So there!

Most people make most of their mail groups total-expirable, though.

If gnus-inhibit-user-auto-expire is non-nil, user marking commands will not mark an article as expirable, even if the group has auto-expire turned on.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.10 Washing Mail

Mailers and list servers are notorious for doing all sorts of really, really stupid things with mail. "Hey, RFC 822 doesn't explicitly prohibit us from adding the string wE aRe ElItE!!!!!1!! to the end of all lines passing through our server, so let's do that!!!!1!" Yes, but RFC 822 wasn't designed to be read by morons. Things that were considered to be self-evident were not discussed. So. Here we are.

Case in point: The German version of Microsoft Exchange adds `AW: ' to the subjects of replies instead of `Re: '. I could pretend to be shocked and dismayed by this, but I haven't got the energy. It is to laugh.

Gnus provides a plethora of functions for washing articles while displaying them, but it might be nicer to do the filtering before storing the mail to disk. For that purpose, we have three hooks and various functions that can be put in these hooks.

This hook is called before doing anything with the mail and is meant for grand, sweeping gestures. It is called in a buffer that contains all the new, incoming mail. Functions to be used include:

Remove trailing carriage returns from each line. This is default on Emacs running on MS machines.

This hook is called narrowed to each header. It can be used when cleaning up the headers. Functions that can be used include:

Clear leading white space that "helpful" listservs have added to the headers to make them look nice. Aaah.

(Note that this function works on both the header on the body of all messages, so it is a potentially dangerous function to use (if a body of a message contains something that looks like a header line). So rather than fix the bug, it is of course the right solution to make it into a feature by documenting it.)

Some list servers add an identifier--for example, `(idm)'---to the beginning of all Subject headers. I'm sure that's nice for people who use stone age mail readers. This function will remove strings that match the nnmail-list-identifiers regexp, which can also be a list of regexp. nnmail-list-identifiers may not contain \\(..\\).

For instance, if you want to remove the `(idm)' and the `nagnagnag' identifiers:

(setq nnmail-list-identifiers
      '("(idm)" "nagnagnag"))

This can also be done non-destructively with gnus-list-identifiers, See section 3.17.3 Article Hiding.

Translate all `TAB' characters into `SPACE' characters.

Eudora produces broken References headers, but OK In-Reply-To headers. This function will get rid of the References headers.

This hook is called narrowed to each message. Functions to be used include:

Decode Quoted Readable encoding.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.11 Duplicates

If you are a member of a couple of mailing lists, you will sometimes receive two copies of the same mail. This can be quite annoying, so nnmail checks for and treats any duplicates it might find. To do this, it keeps a cache of old Message-IDs--- nnmail-message-id-cache-file, which is `~/.nnmail-cache' by default. The approximate maximum number of Message-IDs stored there is controlled by the nnmail-message-id-cache-length variable, which is 1000 by default. (So 1000 Message-IDs will be stored.) If all this sounds scary to you, you can set nnmail-treat-duplicates to warn (which is what it is by default), and nnmail won't delete duplicate mails. Instead it will insert a warning into the head of the mail saying that it thinks that this is a duplicate of a different message.

This variable can also be a function. If that's the case, the function will be called from a buffer narrowed to the message in question with the Message-ID as a parameter. The function must return either nil, warn, or delete.

You can turn this feature off completely by setting the variable to nil.

If you want all the duplicate mails to be put into a special duplicates group, you could do that using the normal mail split methods:

(setq nnmail-split-fancy
      '(| ;; Messages duplicates go to a separate group.
        ("gnus-warning" "duplicat\\(e\\|ion\\) of message" "duplicate")
        ;; Message from daemons, postmaster, and the like to another.
        (any mail "mail.misc")
        ;; Other rules.
        [...] ))
Or something like:
(setq nnmail-split-methods
      '(("duplicates" "^Gnus-Warning:.*duplicate")
        ;; Other rules.

Here's a neat feature: If you know that the recipient reads her mail with Gnus, and that she has nnmail-treat-duplicates set to delete, you can send her as many insults as you like, just by using a Message-ID of a mail that you know that she's already received. Think of all the fun! She'll never see any of it! Whee!

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.12 Not Reading Mail

If you start using any of the mail back ends, they have the annoying habit of assuming that you want to read mail with them. This might not be unreasonable, but it might not be what you want.

If you set mail-sources and nnmail-spool-file to nil, none of the back ends will ever attempt to read incoming mail, which should help.

This might be too much, if, for instance, you are reading mail quite happily with nnml and just want to peek at some old Rmail file you have stashed away with nnbabyl. All back ends have variables called back-end-get-new-mail. If you want to disable the nnbabyl mail reading, you edit the virtual server for the group to have a setting where nnbabyl-get-new-mail to nil.

All the mail back ends will call nn*-prepare-save-mail-hook narrowed to the article to be saved before saving it when reading incoming mail.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3.13 Choosing a Mail Back End

Gnus will read the mail spool when you activate a mail group. The mail file is first copied to your home directory. What happens after that depends on what format you want to store your mail in.

There are six different mail back ends in the standard Gnus, and more back ends are available separately. The mail back end most people use (because it is possibly the fastest) is nnml (see section Mail Spool). Unix Mail Box  Using the (quite) standard Un*x mbox. Rmail Babyl  Emacs programs use the Rmail Babyl format. Mail Spool  Store your mail in a private spool? MH Spool  An mhspool-like back end. Maildir  Another one-file-per-message format. Mail Folders  Having one file for each group. Comparing Mail Back Ends  An in-depth looks at pros and cons.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Unix Mail Box

The nnmbox back end will use the standard Un*x mbox file to store mail. nnmbox will add extra headers to each mail article to say which group it belongs in.

Virtual server settings:

The name of the mail box in the user's home directory. Default is `~/mbox'.

The name of the active file for the mail box. Default is `~/.mbox-active'.

If non-nil, nnmbox will read incoming mail and split it into groups. Default is t.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Rmail Babyl

The nnbabyl back end will use a Babyl mail box (aka. Rmail mbox) to store mail. nnbabyl will add extra headers to each mail article to say which group it belongs in.

Virtual server settings:

The name of the Rmail mbox file. The default is `~/RMAIL'

The name of the active file for the rmail box. The default is `~/.rmail-active'

If non-nil, nnbabyl will read incoming mail. Default is t

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Mail Spool

The nnml spool mail format isn't compatible with any other known format. It should be used with some caution.

If you use this back end, Gnus will split all incoming mail into files, one file for each mail, and put the articles into the corresponding directories under the directory specified by the nnml-directory variable. The default value is `~/Mail/'.

You do not have to create any directories beforehand; Gnus will take care of all that.

If you have a strict limit as to how many files you are allowed to store in your account, you should not use this back end. As each mail gets its own file, you might very well occupy thousands of inodes within a few weeks. If this is no problem for you, and it isn't a problem for you having your friendly systems administrator walking around, madly, shouting "Who is eating all my inodes?! Who? Who!?!", then you should know that this is probably the fastest format to use. You do not have to trudge through a big mbox file just to read your new mail.

nnml is probably the slowest back end when it comes to article splitting. It has to create lots of files, and it also generates NOV databases for the incoming mails. This makes it possibly the fastest back end when it comes to reading mail.

When the marks file is used (which it is by default), nnml servers have the property that you may backup them using tar or similar, and later be able to restore them into Gnus (by adding the proper nnml server) and have all your marks be preserved. Marks for a group is usually stored in the .marks file (but see nnml-marks-file-name) within each nnml group's directory. Individual nnml groups are also possible to backup, use G m to restore the group (after restoring the backup into the nnml directory).

If for some reason you believe your `.marks' files are screwed up, you can just delete them all. Gnus will then correctly regenerate them next time it starts.

Virtual server settings:

All nnml directories will be placed under this directory. The default is the value of message-directory (whose default value is `~/Mail').

The active file for the nnml server. The default is `~/Mail/active'.

The nnml group descriptions file. See section Newsgroups File Format. The default is `~/Mail/newsgroups'.

If non-nil, nnml will read incoming mail. The default is t.

If non-nil, this back end will ignore any NOV files. The default is nil.

The name of the NOV files. The default is `.overview'.

Hook run narrowed to an article before saving.

If non-nil, this back end will ignore any MARKS files. The default is nil.

The name of the marks files. The default is `.marks'.

If non-nil, nnml will allow using compressed message files.

If your nnml groups and NOV files get totally out of whack, you can do a complete update by typing M-x nnml-generate-nov-databases. This command will trawl through the entire nnml hierarchy, looking at each and every article, so it might take a while to complete. A better interface to this functionality can be found in the server buffer (see section 6.1.2 Server Commands).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] MH Spool

nnmh is just like nnml, except that is doesn't generate NOV databases and it doesn't keep an active file or marks file. This makes nnmh a much slower back end than nnml, but it also makes it easier to write procmail scripts for.

Virtual server settings:

All nnmh directories will be located under this directory. The default is the value of message-directory (whose default is `~/Mail')

If non-nil, nnmh will read incoming mail. The default is t.

If non-nil, nnmh will go to ridiculous lengths to make sure that the articles in the folder are actually what Gnus thinks they are. It will check date stamps and stat everything in sight, so setting this to t will mean a serious slow-down. If you never use anything but Gnus to read the nnmh articles, you do not have to set this variable to t. The default is nil.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Maildir

nnmaildir stores mail in the maildir format, with each maildir corresponding to a group in Gnus. This format is documented here: http://cr.yp.to/proto/maildir.html and here: http://www.qmail.org/man/man5/maildir.html. nnmaildir also stores extra information in the `.nnmaildir/' directory within a maildir.

Maildir format was designed to allow concurrent deliveries and reading, without needing locks. With other back ends, you would have your mail delivered to a spool of some kind, and then you would configure Gnus to split mail from that spool into your groups. You can still do that with nnmaildir, but the more common configuration is to have your mail delivered directly to the maildirs that appear as group in Gnus.

nnmaildir is designed to be perfectly reliable: C-g will never corrupt its data in memory, and SIGKILL will never corrupt its data in the filesystem.

nnmaildir stores article marks and NOV data in each maildir. So you can copy a whole maildir from one Gnus setup to another, and you will keep your marks.

Virtual server settings:

For each of your nnmaildir servers (it's very unlikely that you'd need more than one), you need to create a directory and populate it with maildirs or symlinks to maildirs (and nothing else; do not choose a directory already used for other purposes). Each maildir will be represented in Gnus as a newsgroup on that server; the filename of the symlink will be the name of the group. Any filenames in the directory starting with `.' are ignored. The directory is scanned when you first start Gnus, and each time you type g in the group buffer; if any maildirs have been removed or added, nnmaildir notices at these times.

The value of the directory parameter should be a Lisp form which is processed by eval and expand-file-name to get the path of the directory for this server. The form is evaled only when the server is opened; the resulting string is used until the server is closed. (If you don't know about forms and eval, don't worry--a simple string will work.) This parameter is not optional; you must specify it. I don't recommend using "~/Mail" or a subdirectory of it; several other parts of Gnus use that directory by default for various things, and may get confused if nnmaildir uses it too. "~/.nnmaildir" is a typical value.

This should be a Lisp form which is processed by eval and expand-file-name. The form is evaled only when the server is opened; the resulting string is used until the server is closed.

When you create a group on an nnmaildir server, the maildir is created with target-prefix prepended to its name, and a symlink pointing to that maildir is created, named with the plain group name. So if directory is "~/.nnmaildir" and target-prefix is "../maildirs/", then when you create the group foo, nnmaildir will create `~/.nnmaildir/../maildirs/foo' as a maildir, and will create `~/.nnmaildir/foo' as a symlink pointing to `../maildirs/foo'.

You can set target-prefix to a string without any slashes to create both maildirs and symlinks in the same directory; in this case, any maildirs found in directory whose names start with target-prefix will not be listed as groups (but the symlinks pointing to them will be).

As a special case, if target-prefix is "" (the default), then when you create a group, the maildir will be created in directory without a corresponding symlink. Beware that you cannot use gnus-group-delete-group on such groups without the force argument.

This should be a function with the same interface as directory-files (such as directory-files itself). It is used to scan the server's directory for maildirs. This parameter is optional; the default is nnheader-directory-files-safe if nnheader-directory-files-is-safe is nil, and directory-files otherwise. (nnheader-directory-files-is-safe is checked only once when the server is opened; if you want to check it each time the directory is scanned, you'll have to provide your own function that does that.)

If non-nil, then after scanning for new mail in the group maildirs themselves as usual, this server will also incorporate mail the conventional Gnus way, from mail-sources according to nnmail-split-methods or nnmail-split-fancy. The default value is nil.

Do not use the same maildir both in mail-sources and as an nnmaildir group. The results might happen to be useful, but that would be by chance, not by design, and the results might be different in the future. If your split rules create new groups, remember to supply a create-directory server parameter.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Group parameters

nnmaildir uses several group parameters. It's safe to ignore all this; the default behavior for nnmaildir is the same as the default behavior for other mail back ends: articles are deleted after one week, etc. Except for the expiry parameters, all this functionality is unique to nnmaildir, so you can ignore it if you're just trying to duplicate the behavior you already have with another back end.

If the value of any of these parameters is a vector, the first element is evaluated as a Lisp form and the result is used, rather than the original value. If the value is not a vector, the value itself is evaluated as a Lisp form. (This is why these parameters use names different from those of other, similar parameters supported by other back ends: they have different, though similar, meanings.) (For numbers, strings, nil, and t, you can ignore the eval business again; for other values, remember to use an extra quote and wrap the value in a vector when appropriate.)

An integer specifying the minimum age, in seconds, of an article before it will be expired, or the symbol never to specify that articles should never be expired. If this parameter is not set, nnmaildir falls back to the usual nnmail-expiry-wait(-function) variables (the expiry-wait group parameter overrides nnmail-expiry-wait and makes nnmail-expiry-wait-function ineffective). If you wanted a value of 3 days, you could use something like [(* 3 24 60 60)]; nnmaildir will evaluate the form and use the result. An article's age is measured starting from the article file's modification time. Normally, this is the same as the article's delivery time, but editing an article makes it younger. Moving an article (other than via expiry) may also make an article younger.

If this is set to a string such as a full Gnus group name, like
and if it is not the name of the same group that the parameter belongs to, then articles will be moved to the specified group during expiry before being deleted. If this is set to an nnmaildir group, the article will be just as old in the destination group as it was in the source group. So be careful with expire-age in the destination group. If this is set to the name of the same group that the parameter belongs to, then the article is not expired at all. If you use the vector form, the first element is evaluated once for each article. So that form can refer to nnmaildir-article-file-name, etc., to decide where to put the article. Even if this parameter is not set, nnmaildir does not fall back to the expiry-target group parameter or the nnmail-expiry-target variable.

If this is set to t, nnmaildir will treat the articles in this maildir as read-only. This means: articles are not renamed from `new/' into `cur/'; articles are only found in `new/', not `cur/'; articles are never deleted; articles cannot be edited. `new/' is expected to be a symlink to the `new/' directory of another maildir--e.g., a system-wide mailbox containing a mailing list of common interest. Everything in the maildir outside `new/' is not treated as read-only, so for a shared mailbox, you do still need to set up your own maildir (or have write permission to the shared mailbox); your maildir just won't contain extra copies of the articles.

A function with the same interface as directory-files. It is used to scan the directories in the maildir corresponding to this group to find articles. The default is the function specified by the server's directory-files parameter.

If non-nil, nnmaildir will always count the lines of an article, rather than use the Lines: header field. If nil, the header field will be used if present.

A list of mark symbols, such as ['(read expire)]. Whenever Gnus asks nnmaildir for article marks, nnmaildir will say that all articles have these marks, regardless of whether the marks stored in the filesystem say so. This is a proof-of-concept feature that will probably be removed eventually; it ought to be done in Gnus proper, or abandoned if it's not worthwhile.

A list of mark symbols, such as ['(tick expire)]. Whenever Gnus asks nnmaildir for article marks, nnmaildir will say that no articles have these marks, regardless of whether the marks stored in the filesystem say so. never-marks overrides always-marks. This is a proof-of-concept feature that will probably be removed eventually; it ought to be done in Gnus proper, or abandoned if it's not worthwhile.

An integer specifying the size of the NOV memory cache. To speed things up, nnmaildir keeps NOV data in memory for a limited number of articles in each group. (This is probably not worthwhile, and will probably be removed in the future.) This parameter's value is noticed only the first time a group is seen after the server is opened--i.e., when you first start Gnus, typically. The NOV cache is never resized until the server is closed and reopened. The default is an estimate of the number of articles that would be displayed in the summary buffer: a count of articles that are either marked with tick or not marked with read, plus a little extra.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Article identification

Articles are stored in the `cur/' subdirectory of each maildir. Each article file is named like uniq:info, where uniq contains no colons. nnmaildir ignores, but preserves, the :info part. (Other maildir readers typically use this part of the filename to store marks.) The uniq part uniquely identifies the article, and is used in various places in the `.nnmaildir/' subdirectory of the maildir to store information about the corresponding article. The full pathname of an article is available in the variable nnmaildir-article-file-name after you request the article in the summary buffer.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] NOV data

An article identified by uniq has its NOV data (used to generate lines in the summary buffer) stored in .nnmaildir/nov/uniq. There is no nnmaildir-generate-nov-databases function. (There isn't much need for it--an article's NOV data is updated automatically when the article or nnmail-extra-headers has changed.) You can force nnmaildir to regenerate the NOV data for a single article simply by deleting the corresponding NOV file, but beware: this will also cause nnmaildir to assign a new article number for this article, which may cause trouble with seen marks, the Agent, and the cache.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Article marks

An article identified by uniq is considered to have the mark flag when the file `.nnmaildir/marks/flag/uniq' exists. When Gnus asks nnmaildir for a group's marks, nnmaildir looks for such files and reports the set of marks it finds. When Gnus asks nnmaildir to store a new set of marks, nnmaildir creates and deletes the corresponding files as needed. (Actually, rather than create a new file for each mark, it just creates hard links to `.nnmaildir/markfile', to save inodes.)

You can invent new marks by creating a new directory in `.nnmaildir/marks/'. You can tar up a maildir and remove it from your server, untar it later, and keep your marks. You can add and remove marks yourself by creating and deleting mark files. If you do this while Gnus is running and your nnmaildir server is open, it's best to exit all summary buffers for nnmaildir groups and type s in the group buffer first, and to type g or M-g in the group buffer afterwards. Otherwise, Gnus might not pick up the changes, and might undo them.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Mail Folders

nnfolder is a back end for storing each mail group in a separate file. Each file is in the standard Un*x mbox format. nnfolder will add extra headers to keep track of article numbers and arrival dates.

When the marks file is used (which it is by default), nnfolder servers have the property that you may backup them using tar or similar, and later be able to restore them into Gnus (by adding the proper nnfolder server) and have all your marks be preserved. Marks for a group are usually stored in a file named as the mbox file with .mrk concatenated to it (but see nnfolder-marks-file-suffix) within the nnfolder directory. Individual nnfolder groups are also possible to backup, use G m to restore the group (after restoring the backup into the nnfolder directory).

Virtual server settings:

All the nnfolder mail boxes will be stored under this directory. The default is the value of message-directory (whose default is `~/Mail')

The name of the active file. The default is `~/Mail/active'.

The name of the group descriptions file. See section Newsgroups File Format. The default is `~/Mail/newsgroups'

If non-nil, nnfolder will read incoming mail. The default is t

Hook run before saving the folders. Note that Emacs does the normal backup renaming of files even with the nnfolder buffers. If you wish to switch this off, you could say something like the following in your `.emacs' file:

(defun turn-off-backup ()
  (set (make-local-variable 'backup-inhibited) t))

(add-hook 'nnfolder-save-buffer-hook 'turn-off-backup)

Hook run in a buffer narrowed to the message that is to be deleted. This function can be used to copy the message to somewhere else, or to extract some information from it before removing it.

If non-nil, this back end will ignore any NOV files. The default is nil.

The extension for NOV files. The default is `.nov'.

The directory where the NOV files should be stored. If nil, nnfolder-directory is used.

If non-nil, this back end will ignore any MARKS files. The default is nil.

The extension for MARKS files. The default is `.mrk'.

The directory where the MARKS files should be stored. If nil, nnfolder-directory is used.

If you have lots of nnfolder-like files you'd like to read with nnfolder, you can use the M-x nnfolder-generate-active-file command to make nnfolder aware of all likely files in nnfolder-directory. This only works if you use long file names, though.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Comparing Mail Back Ends

First, just for terminology, the back end is the common word for a low-level access method--a transport, if you will, by which something is acquired. The sense is that one's mail has to come from somewhere, and so selection of a suitable back end is required in order to get that mail within spitting distance of Gnus.

The same concept exists for Usenet itself: Though access to articles is typically done by NNTP these days, once upon a midnight dreary, everyone in the world got at Usenet by running a reader on the machine where the articles lay (the machine which today we call an NNTP server), and access was by the reader stepping into the articles' directory spool area directly. One can still select between either the nntp or nnspool back ends, to select between these methods, if one happens actually to live on the server (or can see its spool directly, anyway, via NFS).

The goal in selecting a mail back end is to pick one which simultaneously represents a suitable way of dealing with the original format plus leaving mail in a form that is convenient to use in the future. Here are some high and low points on each:


UNIX systems have historically had a single, very common, and well- defined format. All messages arrive in a single spool file, and they are delineated by a line whose regular expression matches `^From_'. (My notational use of `_' is to indicate a space, to make it clear in this instance that this is not the RFC-specified `From:' header.) Because Emacs and therefore Gnus emanate historically from the Unix environment, it is simplest if one does not mess a great deal with the original mailbox format, so if one chooses this back end, Gnus' primary activity in getting mail from the real spool area to Gnus' preferred directory is simply to copy it, with no (appreciable) format change in the process. It is the "dumbest" way to move mail into availability in the Gnus environment. This makes it fast to move into place, but slow to parse, when Gnus has to look at what's where.


Once upon a time, there was the DEC-10 and DEC-20, running operating systems called TOPS and related things, and the usual (only?) mail reading environment was a thing called Babyl. I don't know what format was used for mail landing on the system, but Babyl had its own internal format to which mail was converted, primarily involving creating a spool-file-like entity with a scheme for inserting Babyl-specific headers and status bits above the top of each message in the file. Rmail was Emacs' first mail reader, it was written by Richard Stallman, and Stallman came out of that TOPS/Babyl environment, so he wrote Rmail to understand the mail files folks already had in existence. Gnus (and VM, for that matter) continue to support this format because it's perceived as having some good qualities in those mailer-specific headers/status bits stuff. Rmail itself still exists as well, of course, and is still maintained by Stallman.

Both of the above forms leave your mail in a single file on your file system, and they must parse that entire file each time you take a look at your mail.


nnml is the back end which smells the most as though you were actually operating with an nnspool-accessed Usenet system. (In fact, I believe nnml actually derived from nnspool code, lo these years ago.) One's mail is taken from the original spool file, and is then cut up into individual message files, 1:1. It maintains a Usenet-style active file (analogous to what one finds in an INN- or CNews-based news system in (for instance) `/var/lib/news/active', or what is returned via the `NNTP LIST' verb) and also creates overview files for efficient group entry, as has been defined for NNTP servers for some years now. It is slower in mail-splitting, due to the creation of lots of files, updates to the nnml active file, and additions to overview files on a per-message basis, but it is extremely fast on access because of what amounts to the indexing support provided by the active file and overviews.

nnml costs inodes in a big way; that is, it soaks up the resource which defines available places in the file system to put new files. Sysadmins take a dim view of heavy inode occupation within tight, shared file systems. But if you live on a personal machine where the file system is your own and space is not at a premium, nnml wins big.

It is also problematic using this back end if you are living in a FAT16-based Windows world, since much space will be wasted on all these tiny files.


The Rand MH mail-reading system has been around UNIX systems for a very long time; it operates by splitting one's spool file of messages into individual files, but with little or no indexing support---nnmh is considered to be semantically equivalent to "nnml without active file or overviews". This is arguably the worst choice, because one gets the slowness of individual file creation married to the slowness of access parsing when learning what's new in one's groups.


Basically the effect of nnfolder is nnmbox (the first method described above) on a per-group basis. That is, nnmbox itself puts all one's mail in one file; nnfolder provides a little bit of optimization to this so that each of one's mail groups has a Unix mail box file. It's faster than nnmbox because each group can be parsed separately, and still provides the simple Unix mail box format requiring minimal effort in moving the mail around. In addition, it maintains an "active" file making it much faster for Gnus to figure out how many messages there are in each separate group.

If you have groups that are expected to have a massive amount of messages, nnfolder is not the best choice, but if you receive only a moderate amount of mail, nnfolder is probably the most friendly mail back end all over.


For configuring expiry and other things, nnmaildir uses incompatible group parameters, slightly different from those of other mail back ends.

nnmaildir is largely similar to nnml, with some notable differences. Each message is stored in a separate file, but the filename is unrelated to the article number in Gnus. nnmaildir also stores the equivalent of nnml's overview files in one file per article, so it uses about twice as many inodes as nnml. (Use df -i to see how plentiful your inode supply is.) If this slows you down or takes up very much space, consider switching to ReiserFS or another non-block-structured file system.

Since maildirs don't require locking for delivery, the maildirs you use as groups can also be the maildirs your mail is directly delivered to. This means you can skip Gnus' mail splitting if your mail is already organized into different mailboxes during delivery. A directory entry in mail-sources would have a similar effect, but would require one set of mailboxes for spooling deliveries (in mbox format, thus damaging message bodies), and another set to be used as groups (in whatever format you like). A maildir has a built-in spool, in the new/ subdirectory. Beware that currently, mail moved from new/ to cur/ instead of via mail splitting will not undergo treatment such as duplicate checking.

nnmaildir stores article marks for a given group in the corresponding maildir, in a way designed so that it's easy to manipulate them from outside Gnus. You can tar up a maildir, unpack it somewhere else, and still have your marks. nnml also stores marks, but it's not as easy to work with them from outside Gnus as with nnmaildir.

nnmaildir uses a significant amount of memory to speed things up. (It keeps in memory some of the things that nnml stores in files and that nnmh repeatedly parses out of message files.) If this is a problem for you, you can set the nov-cache-size group parameter to something small (0 would probably not work, but 1 probably would) to make it use less memory. This caching will probably be removed in the future.

Startup is likely to be slower with nnmaildir than with other back ends. Everything else is likely to be faster, depending in part on your file system.

nnmaildir does not use nnoo, so you cannot use nnoo to write an nnmaildir-derived back end.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4 Browsing the Web

Web-based discussion forums are getting more and more popular. On many subjects, the web-based forums have become the most important forums, eclipsing the importance of mailing lists and news groups. The reason is easy to understand--they are friendly to new users; you just point and click, and there's the discussion. With mailing lists, you have to go through a cumbersome subscription procedure, and most people don't even know what a news group is.

The problem with this scenario is that web browsers are not very good at being newsreaders. They do not keep track of what articles you've read; they do not allow you to score on subjects you're interested in; they do not allow off-line browsing; they require you to click around and drive you mad in the end.

So--if web browsers suck at reading discussion forums, why not use Gnus to do it instead?

Gnus has been getting a bit of a collection of back ends for providing interfaces to these sources.

6.4.1 Archiving Mail  
6.4.2 Web Searches  Creating groups from articles that match a string.
6.4.3 Slashdot  Reading the Slashdot comments.
6.4.4 Ultimate  The Ultimate Bulletin Board systems.
6.4.5 Web Archive  Reading mailing list archived on web.
6.4.6 RSS  Reading RDF site summary.
6.4.7 Customizing W3  Doing stuff to Emacs/W3 from Gnus.

All the web sources require Emacs/W3 and the url library or those alternatives to work.

The main caveat with all these web sources is that they probably won't work for a very long time. Gleaning information from the HTML data is guesswork at best, and when the layout is altered, the Gnus back end will fail. If you have reasonably new versions of these back ends, though, you should be ok.

One thing all these Web methods have in common is that the Web sources are often down, unavailable or just plain too slow to be fun. In those cases, it makes a lot of sense to let the Gnus Agent (see section 6.8 Gnus Unplugged) handle downloading articles, and then you can read them at leisure from your local disk. No more World Wide Wait for you.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4.1 Archiving Mail

Some of the back ends, notably nnml, nnfolder, and nnmaildir, now actually store the article marks with each group. For these servers, archiving and restoring a group while preserving marks is fairly simple.

(Preserving the group level and group parameters as well still requires ritual dancing and sacrifices to the `.newsrc.eld' deity though.)

To archive an entire nnml, nnfolder, or nnmaildir server, take a recursive copy of the server directory. There is no need to shut down Gnus, so archiving may be invoked by cron or similar. You restore the data by restoring the directory tree, and adding a server definition pointing to that directory in Gnus. The 3.14 Article Backlog, 3.11 Asynchronous Article Fetching and other things might interfere with overwriting data, so you may want to shut down Gnus before you restore the data.

It is also possible to archive individual nnml, nnfolder, or nnmaildir groups, while preserving marks. For nnml or nnmaildir, you copy all files in the group's directory. For nnfolder you need to copy both the base folder file itself (`FOO', say), and the marks file (`FOO.mrk' in this example). Restoring the group is done with G m from the Group buffer. The last step makes Gnus notice the new directory. nnmaildir notices the new directory automatically, so G m is unnecessary in that case.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4.2 Web Searches

It's, like, too neat to search the Usenet for articles that match a string, but it, like, totally sucks, like, totally, to use one of those, like, Web browsers, and you, like, have to, rilly, like, look at the commercials, so, like, with Gnus you can do rad, rilly, searches without having to use a browser.

The nnweb back end allows an easy interface to the mighty search engine. You create an nnweb group, enter a search pattern, and then enter the group and read the articles like you would any normal group. The G w command in the group buffer (see section 2.9 Foreign Groups) will do this in an easy-to-use fashion.

nnweb groups don't really lend themselves to being solid groups--they have a very fleeting idea of article numbers. In fact, each time you enter an nnweb group (not even changing the search pattern), you are likely to get the articles ordered in a different manner. Not even using duplicate suppression (see section 3.29 Duplicate Suppression) will help, since nnweb doesn't even know the Message-ID of the articles before reading them using some search engines (Google, for instance). The only possible way to keep track of which articles you've read is by scoring on the Date header--mark all articles posted before the last date you read the group as read.

If the search engine changes its output substantially, nnweb won't be able to parse it and will fail. One could hardly fault the Web providers if they were to do this--their raison d'Ítre is to make money off of advertisements, not to provide services to the community. Since nnweb washes the ads off all the articles, one might think that the providers might be somewhat miffed. We'll see.

You must have the url and W3 package or those alternatives (try customize-group on the `mm-url' variable group) installed to be able to use nnweb.

Virtual server variables:

What search engine type is being used. The currently supported types are google, dejanews, and gmane. Note that dejanews is an alias to google.

The search string to feed to the search engine.

Advisory maximum number of hits per search to display. The default is 999.

Type-to-definition alist. This alist says what nnweb should do with the various search engine types. The following elements must be present:

Function to decode the article and provide something that Gnus understands.

Function to create an article number to message header and URL alist.

Function to send the search string to the search engine.

The address the aforementioned function should send the search string to.

Format string URL to fetch an article by Message-ID.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4.3 Slashdot

Slashdot is a popular news site, with lively discussion following the news articles. nnslashdot will let you read this forum in a convenient manner.

The easiest way to read this source is to put something like the following in your `~/.gnus.el' file:

(setq gnus-secondary-select-methods
      '((nnslashdot "")))

This will make Gnus query the nnslashdot back end for new comments and groups. The F command will subscribe each new news article as a new Gnus group, and you can read the comments by entering these groups. (Note that the default subscription method is to subscribe new groups as zombies. Other methods are available (see section 1.5.2 Subscription Methods).

If you want to remove an old nnslashdot group, the G DEL command is the most handy tool (see section 2.9 Foreign Groups).

When following up to nnslashdot comments (or posting new comments), some light HTMLizations will be performed. In particular, text quoted with `> ' will be quoted with `blockquote' instead, and signatures will have `br' added to the end of each line. Other than that, you can just write HTML directly into the message buffer. Note that Slashdot filters out some HTML forms.

The following variables can be altered to change its behavior:

Whether nnslashdot should display threaded groups or not. The default is t. To be able to display threads, nnslashdot has to retrieve absolutely all comments in a group upon entry. If a threaded display is not required, nnslashdot will only retrieve the comments that are actually wanted by the user. Threading is nicer, but much, much slower than unthreaded.

The login name to use when posting.

The password to use when posting.

Where nnslashdot will store its files. The default is `~/News/slashdot/'.

The URL format string that will be used to fetch the information on news articles and comments. The default is

The URL format string that will be used to fetch comments.

The URL format string that will be used to fetch the news article. The default is `http://slashdot.org/article.pl?sid=%s&mode=nocomment'.

The score threshold. The default is -1.

The number of old groups, in addition to the ten latest, to keep updated. The default is 0.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4.4 Ultimate

The Ultimate Bulletin Board is probably the most popular Web bulletin board system used. It has a quite regular and nice interface, and it's possible to get the information Gnus needs to keep groups updated.

The easiest way to get started with nnultimate is to say something like the following in the group buffer: B nnultimate RET http://www.tcj.com/messboard/ubbcgi/ RET. (Substitute the URL (not including `Ultimate.cgi' or the like at the end) for a forum you're interested in; there's quite a list of them on the Ultimate web site.) Then subscribe to the groups you're interested in from the server buffer, and read them from the group buffer.

The following nnultimate variables can be altered:

The directory where nnultimate stores its files. The default is

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4.5 Web Archive

Some mailing lists only have archives on Web servers, such as http://www.egroups.com/ and http://www.mail-archive.com/. It has a quite regular and nice interface, and it's possible to get the information Gnus needs to keep groups updated.

The easiest way to get started with nnwarchive is to say something like the following in the group buffer: M-x gnus-group-make-warchive-group RET an_egroup RET egroups RET www.egroups.com RET your@email.address RET. (Substitute the an_egroup with the mailing list you subscribed, the your@email.address with your email address.), or to browse the back end by B nnwarchive RET mail-archive RET.

The following nnwarchive variables can be altered:

The directory where nnwarchive stores its files. The default is

The account name on the web server.

The password for your account on the web server.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4.6 RSS

Some web sites have an RDF Site Summary (RSS). RSS is a format for summarizing headlines from news related sites (such as BBC or CNN). But basically anything list-like can be presented as an RSS feed: weblogs, changelogs or recent changes to a wiki (e.g. http://cliki.net/recent-changes.rdf).

RSS has a quite regular and nice interface, and it's possible to get the information Gnus needs to keep groups updated.

Note: you had better use Emacs which supports the utf-8 coding system because RSS uses UTF-8 for encoding non-ASCII text by default. It is also used by default for non-ASCII group names.

Use G R from the group buffer to subscribe to a feed--you will be prompted for the location, the title and the description of the feed. The title, which allows any characters, will be used for the group name and the name of the group data file. The description can be omitted.

An easy way to get started with nnrss is to say something like the following in the group buffer: B nnrss RET RET y, then subscribe to groups.

The nnrss back end saves the group data file in nnrss-directory (see below) for each nnrss group. File names containing non-ASCII characters will be encoded by the coding system specified with the nnmail-pathname-coding-system variable. If it is nil, in Emacs the coding system defaults to the value of default-file-name-coding-system. If you are using XEmacs and want to use non-ASCII group names, you should set the value for the nnmail-pathname-coding-system variable properly.

The nnrss back end generates `multipart/alternative' MIME articles in which each contains a `text/plain' part and a `text/html' part.

You can also use the following commands to import and export your subscriptions from a file in OPML format (Outline Processor Markup Language).

Function: nnrss-opml-import file
Prompt for an OPML file, and subscribe to each feed in the file.

Function: nnrss-opml-export
Write your current RSS subscriptions to a buffer in OPML format.

The following nnrss variables can be altered:

The directory where nnrss stores its files. The default is `~/News/rss/'.

The coding system used when reading and writing the nnrss groups data files. The default is the value of mm-universal-coding-system (which defaults to emacs-mule in Emacs or escape-quoted in XEmacs).

If you set nnrss-use-local to t, nnrss will read the feeds from local files in nnrss-directory. You can use the command nnrss-generate-download-script to generate a download script using wget.

Non-nil means that nnrss renders text in `text/plain' parts as HTML. The function specified by the mm-text-html-renderer variable (see section `Display Customization' in The Emacs MIME Manual) will be used to render text. If it is nil, which is the default, text will simply be folded. Leave it nil if you prefer to see `text/html' parts.

The following code may be helpful, if you want to show the description in the summary buffer.

(add-to-list 'nnmail-extra-headers nnrss-description-field)
(setq gnus-summary-line-format "%U%R%z%I%(%[%4L: %-15,15f%]%) %s%uX\n")

(defun gnus-user-format-function-X (header)
  (let ((descr
         (assq nnrss-description-field (mail-header-extra header))))
    (if descr (concat "\n\t" (cdr descr)) "")))

The following code may be useful to open an nnrss url directly from the summary buffer.

(require 'browse-url)

(defun browse-nnrss-url( arg )
  (interactive "p")
  (let ((url (assq nnrss-url-field
                     (assq (gnus-summary-article-number)
    (if url
          (browse-url (cdr url))
          (gnus-summary-mark-as-read-forward 1))
      (gnus-summary-scroll-up arg))))

(eval-after-load "gnus"
  #'(define-key gnus-summary-mode-map
      (kbd "<RET>") 'browse-nnrss-url))
(add-to-list 'nnmail-extra-headers nnrss-url-field)

Even if you have added "text/html" to the mm-discouraged-alternatives variable (see section `Display Customization' in The Emacs MIME Manual) since you don't want to see HTML parts, it might be more useful especially in nnrss groups to display `text/html' parts. Here's an example of setting mm-discouraged-alternatives as a group parameter (see section 2.10 Group Parameters) in order to display `text/html' parts only in nnrss groups:

;; Set the default value of mm-discouraged-alternatives.
(eval-after-load "gnus-sum"
      . '("text/html" "image/.*"))))

;; Display `text/html' parts in nnrss groups.
 '("\\`nnrss:" (mm-discouraged-alternatives nil)))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4.7 Customizing W3

Gnus uses the url library to fetch web pages and Emacs/W3 (or those alternatives) to display web pages. Emacs/W3 is documented in its own manual, but there are some things that may be more relevant for Gnus users.

For instance, a common question is how to make Emacs/W3 follow links using the browse-url functions (which will call some external web browser like Netscape). Here's one way:

(eval-after-load "w3"
    (fset 'w3-fetch-orig (symbol-function 'w3-fetch))
    (defun w3-fetch (&optional url target)
      (interactive (list (w3-read-url-with-default)))
      (if (eq major-mode 'gnus-article-mode)
          (browse-url url)
        (w3-fetch-orig url target)))))

Put that in your `.emacs' file, and hitting links in W3-rendered HTML in the Gnus article buffers will use browse-url to follow the link.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5 IMAP

IMAP is a network protocol for reading mail (or news, or ...), think of it as a modernized NNTP. Connecting to a IMAP server is much similar to connecting to a news server, you just specify the network address of the server.

IMAP has two properties. First, IMAP can do everything that POP can, it can hence be viewed as a POP++. Secondly, IMAP is a mail storage protocol, similar to NNTP being a news storage protocol--however, IMAP offers more features than NNTP because news is more or less read-only whereas mail is read-write.

If you want to use IMAP as a POP++, use an imap entry in mail-sources. With this, Gnus will fetch mails from the IMAP server and store them on the local disk. This is not the usage described in this section---See section 6.3.4 Mail Sources.

If you want to use IMAP as a mail storage protocol, use an nnimap entry in gnus-secondary-select-methods. With this, Gnus will manipulate mails stored on the IMAP server. This is the kind of usage explained in this section.

A server configuration in `~/.gnus.el' with a few IMAP servers might look something like the following. (Note that for TLS/SSL, you need external programs and libraries, see below.)

(setq gnus-secondary-select-methods
      '((nnimap "simpleserver") ; no special configuration
        ; perhaps a ssh port forwarded server:
        (nnimap "dolk"
                (nnimap-address "localhost")
                (nnimap-server-port 1430))
        ; a UW server running on localhost
        (nnimap "barbar"
                (nnimap-server-port 143)
                (nnimap-address "localhost")
                (nnimap-list-pattern ("INBOX" "mail/*")))
        ; anonymous public cyrus server:
        (nnimap "cyrus.andrew.cmu.edu"
                (nnimap-authenticator anonymous)
                (nnimap-list-pattern "archive.*")
                (nnimap-stream network))
        ; a ssl server on a non-standard port:
        (nnimap "vic20"
                (nnimap-address "vic20.somewhere.com")
                (nnimap-server-port 9930)
                (nnimap-stream ssl))))

After defining the new server, you can subscribe to groups on the server using normal Gnus commands such as U in the Group Buffer (see section 2.4 Subscription Commands) or via the Server Buffer (see section 6.1 Server Buffer).

The following variables can be used to create a virtual nnimap server:


The address of the remote IMAP server. Defaults to the virtual server name if not specified.

Port on server to contact. Defaults to port 143, or 993 for TLS/SSL.

Note that this should be an integer, example server specification:

(nnimap "mail.server.com"
        (nnimap-server-port 4711))

String or list of strings of mailboxes to limit available groups to. This is used when the server has very many mailboxes and you're only interested in a few--some servers export your home directory via IMAP, you'll probably want to limit the mailboxes to those in `~/Mail/*' then.

The string can also be a cons of REFERENCE and the string as above, what REFERENCE is used for is server specific, but on the University of Washington server it's a directory that will be concatenated with the mailbox.

Example server specification:

(nnimap "mail.server.com"
        (nnimap-list-pattern ("INBOX" "Mail/*" "alt.sex.*"
                               ("~friend/Mail/" . "list/*"))))

The type of stream used to connect to your server. By default, nnimap will detect and automatically use all of the below, with the exception of TLS/SSL. (IMAP over TLS/SSL is being replaced by STARTTLS, which can be automatically detected, but it's not widely deployed yet.)

Example server specification:

(nnimap "mail.server.com"
        (nnimap-stream ssl))

Please note that the value of nnimap-stream is a symbol!

The `imtest' program is shipped with Cyrus IMAPD. If you're using `imtest' from Cyrus IMAPD < 2.0.14 (which includes version 1.5.x and 1.6.x) you need to frob imap-process-connection-type to make imap.el use a pty instead of a pipe when communicating with `imtest'. You will then suffer from a line length restrictions on IMAP commands, which might make Gnus seem to hang indefinitely if you have many articles in a mailbox. The variable imap-kerberos4-program contain parameters to pass to the imtest program.

For TLS connection, the gnutls-cli program from GNUTLS is needed. It is available from http://www.gnu.org/software/gnutls/.

This parameter specifies a list of command lines that invoke a GSSAPI authenticated IMAP stream in a subshell. They are tried sequentially until a connection is made, or the list has been exhausted. By default, `gsasl' from GNU SASL, available from http://www.gnu.org/software/gsasl/, and the `imtest' program from Cyrus IMAPD (see imap-kerberos4-program), are tried.

For SSL connections, the OpenSSL program is available from http://www.openssl.org/. OpenSSL was formerly known as SSLeay, and nnimap support it too--although the most recent versions of SSLeay, 0.9.x, are known to have serious bugs making it useless. Earlier versions, especially 0.8.x, of SSLeay are known to work. The variable imap-ssl-program contain parameters to pass to OpenSSL/SSLeay.

For IMAP connections using the shell stream, the variable imap-shell-program specify what program to call.


The authenticator used to connect to the server. By default, nnimap will use the most secure authenticator your server is capable of.

Example server specification:

(nnimap "mail.server.com"
        (nnimap-authenticator anonymous))

Please note that the value of nnimap-authenticator is a symbol!

Unlike Parmenides the IMAP designers have decided things that don't exist actually do exist. More specifically, IMAP has this concept of marking articles Deleted which doesn't actually delete them, and this (marking them Deleted, that is) is what nnimap does when you delete an article in Gnus (with B DEL or similar).

Since the articles aren't really removed when we mark them with the Deleted flag we'll need a way to actually delete them. Feel like running in circles yet?

Traditionally, nnimap has removed all articles marked as Deleted when closing a mailbox but this is now configurable by this server variable.

The possible options are:

The default behavior, delete all articles marked as "Deleted" when closing a mailbox.
Never actually delete articles. Currently there is no way of showing the articles marked for deletion in nnimap, but other IMAP clients may allow you to do this. If you ever want to run the EXPUNGE command manually, See section 6.5.4 Expunging mailboxes.
When closing mailboxes, nnimap will ask if you wish to expunge deleted articles or not.


If non-nil (the default), marks dormant articles as ticked (as well), for other IMAP clients. Within Gnus, dormant articles will naturally still (only) be marked as dormant. This is to make dormant articles stand out, just like ticked articles, in other IMAP clients. (In other words, Gnus has two "Tick" marks and IMAP has only one.)

Probably the only reason for frobing this would be if you're trying enable per-user persistent dormant flags, using something like:

(setcdr (assq 'dormant nnimap-mark-to-flag-alist)
        (format "gnus-dormant-%s" (user-login-name)))
(setcdr (assq 'dormant nnimap-mark-to-predicate-alist)
        (format "KEYWORD gnus-dormant-%s" (user-login-name)))

In this case, you would not want the per-user dormant flag showing up as ticked for other users.


This variable contain the IMAP search command sent to server when searching for articles eligible for expiring. The default is "UID %s NOT SINCE %s", where the first %s is replaced by UID set and the second %s is replaced by a date.

Probably the only useful value to change this to is "UID %s NOT SENTSINCE %s", which makes nnimap use the Date: in messages instead of the internal article date. See section 6.4.4 of RFC 2060 for more information on valid strings.


A file containing credentials used to log in on servers. The format is (almost) the same as the ftp `~/.netrc' file. See the variable nntp-authinfo-file for exact syntax; also see 6.2.1 NNTP. An example of an .authinfo line for an IMAP server, is:

machine students.uio.no login larsi password geheimnis port imap

Note that it should be port imap, or port 143, if you use a nnimap-stream of tls or ssl, even if the actual port number used is port 993 for secured IMAP. For convenience, Gnus will accept port imaps as a synonym of port imap.


Unselect mailboxes before looking for new mail in them. Some servers seem to need this under some circumstances; it was reported that Courier 1.7.1 did.

6.5.1 Splitting in IMAP  Splitting mail with nnimap.
6.5.2 Expiring in IMAP  Expiring mail with nnimap.
6.5.3 Editing IMAP ACLs  Limiting/enabling other users access to a mailbox.
6.5.4 Expunging mailboxes  Equivalent of a "compress mailbox" button.
6.5.5 A note on namespaces  How to (not) use IMAP namespace in Gnus.
6.5.6 Debugging IMAP  What to do when things don't work.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5.1 Splitting in IMAP

Splitting is something Gnus users have loved and used for years, and now the rest of the world is catching up. Yeah, dream on, not many IMAP servers have server side splitting and those that have splitting seem to use some non-standard protocol. This means that IMAP support for Gnus has to do its own splitting.

And it does.

(Incidentally, people seem to have been dreaming on, and Sieve has gaining a market share and is supported by several IMAP servers. Fortunately, Gnus support it too, See section 2.17.5 Sieve Commands.)

Here are the variables of interest:


If non-nil, do crossposting if several split methods match the mail. If nil, the first match in nnimap-split-rule found will be used.

Nnmail equivalent: nnmail-crosspost.


A string or a list of strings that gives the name(s) of IMAP mailboxes to split from. Defaults to nil, which means that splitting is disabled!

(setq nnimap-split-inbox
      '("INBOX" ("~/friend/Mail" . "lists/*") "lists.imap"))

No nnmail equivalent.


New mail found in nnimap-split-inbox will be split according to this variable.

This variable contains a list of lists, where the first element in the sublist gives the name of the IMAP mailbox to move articles matching the regexp in the second element in the sublist. Got that? Neither did I, we need examples.

(setq nnimap-split-rule
         "^Sender: owner-nnimap@vic20.globalcom.se")
        ("INBOX.junk"    "^Subject:.*MAKE MONEY")
        ("INBOX.private" "")))

This will put all articles from the nnimap mailing list into mailbox INBOX.nnimap, all articles containing MAKE MONEY in the Subject: line into INBOX.junk and everything else in INBOX.private.

The first string may contain `\\1' forms, like the ones used by replace-match to insert sub-expressions from the matched text. For instance:

("INBOX.lists.\\1"     "^Sender: owner-\\([a-z-]+\\)@")

The first element can also be the symbol junk to indicate that matching messages should simply be deleted. Use with care.

The second element can also be a function. In that case, it will be called with the first element of the rule as the argument, in a buffer containing the headers of the article. It should return a non-nil value if it thinks that the mail belongs in that group.

Nnmail users might recollect that the last regexp had to be empty to match all articles (like in the example above). This is not required in nnimap. Articles not matching any of the regexps will not be moved out of your inbox. (This might affect performance if you keep lots of unread articles in your inbox, since the splitting code would go over them every time you fetch new mail.)

These rules are processed from the beginning of the alist toward the end. The first rule to make a match will "win", unless you have crossposting enabled. In that case, all matching rules will "win".

This variable can also have a function as its value, the function will be called with the headers narrowed and should return a group where it thinks the article should be split to. See nnimap-split-fancy.

The splitting code tries to create mailboxes if it needs to.

To allow for different split rules on different virtual servers, and even different split rules in different inboxes on the same server, the syntax of this variable have been extended along the lines of:

(setq nnimap-split-rule
      '(("my1server"    (".*" (("ding"    "ding@gnus.org")
                               ("junk"    "From:.*Simon"))))
        ("my2server"    ("INBOX" nnimap-split-fancy))
        ("my[34]server" (".*" (("private" "To:.*Simon")
                               ("junk"    my-junk-func))))))

The virtual server name is in fact a regexp, so that the same rules may apply to several servers. In the example, the servers my3server and my4server both use the same rules. Similarly, the inbox string is also a regexp. The actual splitting rules are as before, either a function, or a list with group/regexp or group/function elements.

Nnmail equivalent: nnmail-split-methods.


Mail matching this predicate in nnimap-split-inbox will be split, it is a string and the default is `UNSEEN UNDELETED'.

This might be useful if you use another IMAP client to read mail in your inbox but would like Gnus to split all articles in the inbox regardless of readedness. Then you might change this to `UNDELETED'.


It's possible to set nnimap-split-rule to nnmail-split-fancy if you want to use fancy splitting. See section 6.3.6 Fancy Mail Splitting.

However, to be able to have different fancy split rules for nnmail and nnimap back ends you can set nnimap-split-rule to nnimap-split-fancy and define the nnimap specific fancy split rule in nnimap-split-fancy.


(setq nnimap-split-rule 'nnimap-split-fancy
      nnimap-split-fancy ...)

Nnmail equivalent: nnmail-split-fancy.


Set to non-nil to download entire articles during splitting. This is generally not required, and will slow things down considerably. You may need it if you want to use an advanced splitting function that analyzes the body to split the article.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5.2 Expiring in IMAP

Even though nnimap is not a proper nnmail derived back end, it supports most features in regular expiring (see section 6.3.9 Expiring Mail). Unlike splitting in IMAP (see section 6.5.1 Splitting in IMAP) it does not clone the nnmail variables (i.e., creating nnimap-expiry-wait) but reuse the nnmail variables. What follows below are the variables used by the nnimap expiry process.

A note on how the expire mark is stored on the IMAP server is appropriate here as well. The expire mark is translated into a imap client specific mark, gnus-expire, and stored on the message. This means that likely only Gnus will understand and treat the gnus-expire mark properly, although other clients may allow you to view client specific flags on the message. It also means that your server must support permanent storage of client specific flags on messages. Most do, fortunately.


These variables are fully supported. The expire value can be a number, the symbol immediate or never.


This variable is supported, and internally implemented by calling the nnmail functions that handle this. It contains an optimization that if the destination is a IMAP group on the same server, the article is copied instead of appended (that is, uploaded again).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5.3 Editing IMAP ACLs

ACL stands for Access Control List. ACLs are used in IMAP for limiting (or enabling) other users access to your mail boxes. Not all IMAP servers support this, this function will give an error if it doesn't.

To edit an ACL for a mailbox, type G l (gnus-group-edit-nnimap-acl) and you'll be presented with an ACL editing window with detailed instructions.

Some possible uses:

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5.4 Expunging mailboxes

If you're using the never setting of nnimap-expunge-on-close, you may want the option of expunging all deleted articles in a mailbox manually. This is exactly what G x does.

Currently there is no way of showing deleted articles, you can just delete them.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5.5 A note on namespaces

The IMAP protocol has a concept called namespaces, described by the following text in the RFC2060:

5.1.2.  Mailbox Namespace Naming Convention

   By convention, the first hierarchical element of any mailbox name
   which begins with "#" identifies the "namespace" of the remainder of
   the name.  This makes it possible to disambiguate between different
   types of mailbox stores, each of which have their own namespaces.

      For example, implementations which offer access to USENET
      newsgroups MAY use the "#news" namespace to partition the USENET
      newsgroup namespace from that of other mailboxes.  Thus, the
      comp.mail.misc newsgroup would have an mailbox name of
      "#news.comp.mail.misc", and the name "comp.mail.misc" could refer
      to a different object (e.g. a user's private mailbox).

While there is nothing in this text that warrants concern for the IMAP implementation in Gnus, some servers use namespace prefixes in a way that does not work with how Gnus uses mailbox names.

Specifically, University of Washington's IMAP server uses mailbox names like #driver.mbx/read-mail which are valid only in the CREATE and APPEND commands. After the mailbox is created (or a messages is appended to a mailbox), it must be accessed without the namespace prefix, i.e. read-mail. Since Gnus do not make it possible for the user to guarantee that user entered mailbox names will only be used with the CREATE and APPEND commands, you should simply not use the namespace prefixed mailbox names in Gnus.

See the UoW IMAPD documentation for the #driver.*/ prefix for more information on how to use the prefixes. They are a power tool and should be used only if you are sure what the effects are.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5.6 Debugging IMAP

IMAP is a complex protocol, more so than NNTP or POP3. Implementation bugs are not unlikely, and we do our best to fix them right away. If you encounter odd behavior, chances are that either the server or Gnus is buggy.

If you are familiar with network protocols in general, you will probably be able to extract some clues from the protocol dump of the exchanges between Gnus and the server. Even if you are not familiar with network protocols, when you include the protocol dump in IMAP-related bug reports you are helping us with data critical to solving the problem. Therefore, we strongly encourage you to include the protocol dump when reporting IMAP bugs in Gnus.

Because the protocol dump, when enabled, generates lots of data, it is disabled by default. You can enable it by setting imap-log as follows:

(setq imap-log t)

This instructs the imap.el package to log any exchanges with the server. The log is stored in the buffer `*imap-log*'. Look for error messages, which sometimes are tagged with the keyword BAD---but when submitting a bug, make sure to include all the data.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6 Other Sources

Gnus can do more than just read news or mail. The methods described below allow Gnus to view directories and files as if they were newsgroups.

6.6.1 Directory Groups  You can read a directory as if it was a newsgroup.
6.6.2 Anything Groups  Dired? Who needs dired?
6.6.3 Document Groups  Single files can be the basis of a group.
6.6.4 SOUP  Reading SOUP packets "offline".
6.6.5 Mail-To-News Gateways  Posting articles via mail-to-news gateways.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6.1 Directory Groups

If you have a directory that has lots of articles in separate files in it, you might treat it as a newsgroup. The files have to have numerical names, of course.

This might be an opportune moment to mention ange-ftp (and its successor efs), that most wonderful of all wonderful Emacs packages. When I wrote nndir, I didn't think much about it--a back end to read directories. Big deal.

ange-ftp changes that picture dramatically. For instance, if you enter the ange-ftp file name `/ftp.hpc.uh.edu:/pub/emacs/ding-list/' as the directory name, ange-ftp or efs will actually allow you to read this directory over at `sina' as a newsgroup. Distributed news ahoy!

nndir will use NOV files if they are present.

nndir is a "read-only" back end--you can't delete or expire articles with this method. You can use nnmh or nnml for whatever you use nndir for, so you could switch to any of those methods if you feel the need to have a non-read-only nndir.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6.2 Anything Groups

From the nndir back end (which reads a single spool-like directory), it's just a hop and a skip to nneething, which pretends that any arbitrary directory is a newsgroup. Strange, but true.

When nneething is presented with a directory, it will scan this directory and assign article numbers to each file. When you enter such a group, nneething must create "headers" that Gnus can use. After all, Gnus is a newsreader, in case you're forgetting. nneething does this in a two-step process. First, it snoops each file in question. If the file looks like an article (i.e., the first few lines look like headers), it will use this as the head. If this is just some arbitrary file without a head (e.g. a C source file), nneething will cobble up a header out of thin air. It will use file ownership, name and date and do whatever it can with these elements.

All this should happen automatically for you, and you will be presented with something that looks very much like a newsgroup. Totally like a newsgroup, to be precise. If you select an article, it will be displayed in the article buffer, just as usual.

If you select a line that represents a directory, Gnus will pop you into a new summary buffer for this nneething group. And so on. You can traverse the entire disk this way, if you feel like, but remember that Gnus is not dired, really, and does not intend to be, either.

There are two overall modes to this action--ephemeral or solid. When doing the ephemeral thing (i.e., G D from the group buffer), Gnus will not store information on what files you have read, and what files are new, and so on. If you create a solid nneething group the normal way with G m, Gnus will store a mapping table between article numbers and file names, and you can treat this group like any other groups. When you activate a solid nneething group, you will be told how many unread articles it contains, etc., etc.

Some variables:

All the mapping files for solid nneething groups will be stored in this directory, which defaults to `~/.nneething/'.

All files that match this regexp will be ignored. Nice to use to exclude auto-save files and the like, which is what it does by default.

Regexp saying what files to include in the group. If this variable is non-nil, only files matching this regexp will be included.

Name of the map files.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6.3 Document Groups

nndoc is a cute little thing that will let you read a single file as a newsgroup. Several files types are supported:

The Babyl (Rmail) mail box.

The standard Unix mbox file.

The MMDF mail box format.

Several news articles appended into a file.

The rnews batch transport format.

Netscape mail boxes.

MIME multipart messages.

The standard (RFC 1153) digest format.

A MIME digest of messages.

Announcement messages from LANL Gov Announce.

A message forwarded according to RFC822.

The Outlook mail box.

The Outlook Express dbx mail box.

A bounce message from the Exim MTA.

A message forwarded according to informal rules.

An RFC934-forwarded message.

A mailman digest.

A digest of Clarinet brief news items.

Non-standard digest format--matches most things, but does it badly.

The last resort.

You can also use the special "file type" guess, which means that nndoc will try to guess what file type it is looking at. digest means that nndoc should guess what digest type the file is.

nndoc will not try to change the file or insert any extra headers into it--it will simply, like, let you use the file as the basis for a group. And that's it.

If you have some old archived articles that you want to insert into your new & spiffy Gnus mail back end, nndoc can probably help you with that. Say you have an old `RMAIL' file with mail that you now want to split into your new nnml groups. You look at that file using nndoc (using the G f command in the group buffer (see section 2.9 Foreign Groups)), set the process mark on all the articles in the buffer (M P b, for instance), and then re-spool (B r) using nnml. If all goes well, all the mail in the `RMAIL' file is now also stored in lots of nnml directories, and you can delete that pesky `RMAIL' file. If you have the guts!

Virtual server variables:

This should be one of mbox, babyl, digest, news, rnews, mmdf, forward, rfc934, rfc822-forward, mime-parts, standard-digest, slack-digest, clari-briefs, nsmail, outlook, oe-dbx, mailman, and mail-in-mail or guess.

This variable says whether Gnus is to consider the group a news group or a mail group. There are two valid values: mail (the default) and news. Document Server Internals  How to add your own document types.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Document Server Internals

Adding new document types to be recognized by nndoc isn't difficult. You just have to whip up a definition of what the document looks like, write a predicate function to recognize that document type, and then hook into nndoc.

First, here's an example document type definition:

 (article-begin .  "^\^A\^A\^A\^A\n")
 (body-end .  "^\^A\^A\^A\^A\n"))

The definition is simply a unique name followed by a series of regexp pseudo-variable settings. Below are the possible variables--don't be daunted by the number of variables; most document types can be defined with very few settings:

If present, nndoc will skip past all text until it finds something that match this regexp. All text before this will be totally ignored.

This setting has to be present in all document type definitions. It says what the beginning of each article looks like. To do more complicated things that cannot be dealt with a simple regexp, you can use article-begin-function instead of this.

If present, this should be a function that moves point to the beginning of each article. This setting overrides article-begin.

If present, this should be a regexp that matches the head of the article. To do more complicated things that cannot be dealt with a simple regexp, you can use head-begin-function instead of this.

If present, this should be a function that moves point to the head of the article. This setting overrides head-begin.

This should match the end of the head of the article. It defaults to `^$'---the empty line.

This should match the beginning of the body of the article. It defaults to `^\n'. To do more complicated things that cannot be dealt with a simple regexp, you can use body-begin-function instead of this.

If present, this function should move point to the beginning of the body of the article. This setting overrides body-begin.

If present, this should match the end of the body of the article. To do more complicated things that cannot be dealt with a simple regexp, you can use body-end-function instead of this.

If present, this function should move point to the end of the body of the article. This setting overrides body-end.

If present, this should match the beginning of the file. All text before this regexp will be totally ignored.

If present, this should match the end of the file. All text after this regexp will be totally ignored.

So, using these variables nndoc is able to dissect a document file into a series of articles, each with a head and a body. However, a few more variables are needed since not all document types are all that news-like--variables needed to transform the head or the body into something that's palatable for Gnus:

If present, this function will be called when requesting an article. It will be called with point at the start of the body, and is useful if the document has encoded some parts of its contents.

If present, this function is called when requesting an article. It's meant to be used for more wide-ranging transformation of both head and body of the article.

If present, this function is called to generate a head that Gnus can understand. It is called with the article number as a parameter, and is expected to generate a nice head for the article in question. It is called when requesting the headers of all articles.

If present, this function is called to generate an entire article that Gnus can understand. It is called with the article number as a parameter when requesting all articles.

If present, this function is called to dissect a document by itself, overriding first-article, article-begin, article-begin-function, head-begin, head-begin-function, head-end, body-begin, body-begin-function, body-end, body-end-function, file-begin, and file-end.

Let's look at the most complicated example I can come up with--standard digests:

 (first-article . ,(concat "^" (make-string 70 ?-) "\n\n+"))
 (article-begin . ,(concat "\n\n" (make-string 30 ?-) "\n\n+"))
 (prepare-body-function . nndoc-unquote-dashes)
 (body-end-function . nndoc-digest-body-end)
 (head-end . "^ ?$")
 (body-begin . "^ ?\n")
 (file-end . "^End of .*digest.*[0-9].*\n\\*\\*\\|^End of.*Digest *$")
 (subtype digest guess))

We see that all text before a 70-width line of dashes is ignored; all text after a line that starts with that `^End of' is also ignored; each article begins with a 30-width line of dashes; the line separating the head from the body may contain a single space; and that the body is run through nndoc-unquote-dashes before being delivered.

To hook your own document definition into nndoc, use the nndoc-add-type function. It takes two parameters--the first is the definition itself and the second (optional) parameter says where in the document type definition alist to put this definition. The alist is traversed sequentially, and nndoc-type-type-p is called for a given type type. So nndoc-mmdf-type-p is called to see whether a document is of mmdf type, and so on. These type predicates should return nil if the document is not of the correct type; t if it is of the correct type; and a number if the document might be of the correct type. A high number means high probability; a low number means low probability with `0' being the lowest valid number.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6.4 SOUP

In the PC world people often talk about "offline" newsreaders. These are thingies that are combined reader/news transport monstrosities. With built-in modem programs. Yecchh!

Of course, us Unix Weenie types of human beans use things like uucp and, like, nntpd and set up proper news and mail transport things like Ghod intended. And then we just use normal newsreaders.

However, it can sometimes be convenient to do something that's a bit easier on the brain if you have a very slow modem, and you're not really that interested in doing things properly.

A file format called SOUP has been developed for transporting news and mail from servers to home machines and back again. It can be a bit fiddly.

First some terminology:

This is the machine that is connected to the outside world and where you get news and/or mail from.

home machine
This is the machine that you want to do the actual reading and responding on. It is typically not connected to the rest of the world in any way.

Something that contains messages and/or commands. There are two kinds of packets:

message packets
These are packets made at the server, and typically contain lots of messages for you to read. These are called `SoupoutX.tgz' by default, where x is a number.

response packets
These are packets made at the home machine, and typically contains replies that you've written. These are called `SoupinX.tgz' by default, where x is a number.

  1. You log in on the server and create a SOUP packet. You can either use a dedicated SOUP thingie (like the awk program), or you can use Gnus to create the packet with its SOUP commands (O s and/or G s b; and then G s p) (see section SOUP Commands).

  2. You transfer the packet home. Rail, boat, car or modem will do fine.

  3. You put the packet in your home directory.

  4. You fire up Gnus on your home machine using the nnsoup back end as the native or secondary server.

  5. You read articles and mail and answer and followup to the things you want (see section SOUP Replies).

  6. You do the G s r command to pack these replies into a SOUP packet.

  7. You transfer this packet to the server.

  8. You use Gnus to mail this packet out with the G s s command.

  9. You then repeat until you die.

So you basically have a bipartite system--you use nnsoup for reading and Gnus for packing/sending these SOUP packets. SOUP Commands  Commands for creating and sending SOUP packets SOUP Groups  A back end for reading SOUP packets. SOUP Replies  How to enable nnsoup to take over mail and news.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] SOUP Commands

These are commands for creating and manipulating SOUP packets.

G s b
Pack all unread articles in the current group (gnus-group-brew-soup). This command understands the process/prefix convention.

G s w
Save all SOUP data files (gnus-soup-save-areas).

G s s
Send all replies from the replies packet (gnus-soup-send-replies).

G s p
Pack all files into a SOUP packet (gnus-soup-pack-packet).

G s r
Pack all replies into a replies packet (nnsoup-pack-replies).

O s
This summary-mode command adds the current article to a SOUP packet (gnus-soup-add-article). It understands the process/prefix convention (see section 8.1 Process/Prefix).

There are a few variables to customize where Gnus will put all these thingies:

Directory where Gnus will save intermediate files while composing SOUP packets. The default is `~/SoupBrew/'.

This is what Gnus will use as a temporary directory while sending our reply packets. `~/SoupBrew/SoupReplies/' is the default.

Name of the file where Gnus stores the last used prefix. The default is `gnus-prefix'.

A format string command for packing a SOUP packet. The default is `tar cf - %s | gzip > $HOME/Soupout%d.tgz'.

Format string command for unpacking a SOUP packet. The default is `gunzip -c %s | tar xvf -'.

Where Gnus will look for reply packets. The default is `~/'.

Regular expression matching SOUP reply packets in gnus-soup-packet-directory.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] SOUP Groups

nnsoup is the back end for reading SOUP packets. It will read incoming packets, unpack them, and put them in a directory where you can read them at leisure.

These are the variables you can use to customize its behavior:

When nnsoup unpacks a SOUP packet, it does it in this directory. (`/tmp/' by default.)

nnsoup then moves each message and index file to this directory. The default is `~/SOUP/'.

All replies will be stored in this directory before being packed into a reply packet. The default is `~/SOUP/replies/'.

The SOUP format of the replies packets. The default is `?n' (rnews), and I don't think you should touch that variable. I probably shouldn't even have documented it. Drats! Too late!

The index type of the replies packet. The default is `?n', which means "none". Don't fiddle with this one either!

Where nnsoup stores lots of information. This is not an "active file" in the nntp sense; it's an Emacs Lisp file. If you lose this file or mess it up in any way, you're dead. The default is `~/SOUP/active'.

Format string command for packing a reply SOUP packet. The default is `tar cf - %s | gzip > $HOME/Soupin%d.tgz'.

Format string command for unpacking incoming SOUP packets. The default is `gunzip -c %s | tar xvf -'.

Where nnsoup will look for incoming packets. The default is `~/'.

Regular expression matching incoming SOUP packets. The default is `Soupout'.

If non-nil, save the replies buffer after each posted message.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] SOUP Replies

Just using nnsoup won't mean that your postings and mailings end up in SOUP reply packets automagically. You have to work a bit more for that to happen.

The nnsoup-set-variables command will set the appropriate variables to ensure that all your followups and replies end up in the SOUP system.

In specific, this is what it does:

(setq message-send-news-function 'nnsoup-request-post)
(setq message-send-mail-function 'nnsoup-request-mail)

And that's it, really. If you only want news to go into the SOUP system you just use the first line. If you only want mail to be SOUPed you use the second.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6.5 Mail-To-News Gateways

If your local nntp server doesn't allow posting, for some reason or other, you can post using one of the numerous mail-to-news gateways. The nngateway back end provides the interface.

Note that you can't read anything from this back end--it can only be used to post with.

Server variables:

This is the address of the mail-to-news gateway.

News headers often have to be transformed in some odd way or other for the mail-to-news gateway to accept it. This variable says what transformation should be called, and defaults to nngateway-simple-header-transformation. The function is called narrowed to the headers to be transformed and with one parameter--the gateway address.

This default function just inserts a new To header based on the Newsgroups header and the gateway address. For instance, an article with this Newsgroups header:

Newsgroups: alt.religion.emacs

will get this To header inserted:

To: alt-religion-emacs@GATEWAY

The following pre-defined functions exist:

Creates a To header that looks like newsgroup@nngateway-address.

Creates a To header that looks like nngateway-address.

Here's an example:

(setq gnus-post-method

So, to use this, simply say something like:

(setq gnus-post-method '(nngateway "GATEWAY.ADDRESS"))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.7 Combined Groups

Gnus allows combining a mixture of all the other group types into bigger groups.

6.7.1 Virtual Groups  Combining articles from many groups.
6.7.2 Kibozed Groups  Looking through parts of the newsfeed for articles.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.7.1 Virtual Groups

An nnvirtual group is really nothing more than a collection of other groups.

For instance, if you are tired of reading many small groups, you can put them all in one big group, and then grow tired of reading one big, unwieldy group. The joys of computing!

You specify nnvirtual as the method. The address should be a regexp to match component groups.

All marks in the virtual group will stick to the articles in the component groups. So if you tick an article in a virtual group, the article will also be ticked in the component group from whence it came. (And vice versa--marks from the component groups will also be shown in the virtual group.). To create an empty virtual group, run G V (gnus-group-make-empty-virtual) in the group buffer and edit the method regexp with M-e (gnus-group-edit-group-method)

Here's an example nnvirtual method that collects all Andrea Dworkin newsgroups into one, big, happy newsgroup:

(nnvirtual "^alt\\.fan\\.andrea-dworkin$\\|^rec\\.dworkin.*")

The component groups can be native or foreign; everything should work smoothly, but if your computer explodes, it was probably my fault.

Collecting the same group from several servers might actually be a good idea if users have set the Distribution header to limit distribution. If you would like to read `soc.motss' both from a server in Japan and a server in Norway, you could use the following as the group regexp:


(Remember, though, that if you're creating the group with G m, you shouldn't double the backslashes, and you should leave off the quote characters at the beginning and the end of the string.)

This should work kinda smoothly--all articles from both groups should end up in this one, and there should be no duplicates. Threading (and the rest) will still work as usual, but there might be problems with the sequence of articles. Sorting on date might be an option here (see section 2.3 Selecting a Group).

One limitation, however--all groups included in a virtual group have to be alive (i.e., subscribed or unsubscribed). Killed or zombie groups can't be component groups for nnvirtual groups.

If the nnvirtual-always-rescan variable is non-nil (which is the default), nnvirtual will always scan groups for unread articles when entering a virtual group. If this variable is nil and you read articles in a component group after the virtual group has been activated, the read articles from the component group will show up when you enter the virtual group. You'll also see this effect if you have two virtual groups that have a component group in common. If that's the case, you should set this variable to t. Or you can just tap M-g on the virtual group every time before you enter it--it'll have much the same effect.

nnvirtual can have both mail and news groups as component groups. When responding to articles in nnvirtual groups, nnvirtual has to ask the back end of the component group the article comes from whether it is a news or mail back end. However, when you do a ^, there is typically no sure way for the component back end to know this, and in that case nnvirtual tells Gnus that the article came from a not-news back end. (Just to be on the safe side.)

C-c C-n in the message buffer will insert the Newsgroups line from the article you respond to in these cases.

nnvirtual groups do not inherit anything but articles and marks from component groups--group parameters, for instance, are not inherited.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.7.2 Kibozed Groups

Kibozing is defined by the OED as "grepping through (parts of) the news feed". nnkiboze is a back end that will do this for you. Oh joy! Now you can grind any NNTP server down to a halt with useless requests! Oh happiness!

To create a kibozed group, use the G k command in the group buffer.

The address field of the nnkiboze method is, as with nnvirtual, a regexp to match groups to be "included" in the nnkiboze group. That's where most similarities between nnkiboze and nnvirtual end.

In addition to this regexp detailing component groups, an nnkiboze group must have a score file to say what articles are to be included in the group (see section 7. Scoring).

You must run M-x nnkiboze-generate-groups after creating the nnkiboze groups you want to have. This command will take time. Lots of time. Oodles and oodles of time. Gnus has to fetch the headers from all the articles in all the component groups and run them through the scoring process to determine if there are any articles in the groups that are to be part of the nnkiboze groups.

Please limit the number of component groups by using restrictive regexps. Otherwise your sysadmin may become annoyed with you, and the NNTP site may throw you off and never let you back in again. Stranger things have happened.

nnkiboze component groups do not have to be alive--they can be dead, and they can be foreign. No restrictions.

The generation of an nnkiboze group means writing two files in nnkiboze-directory, which is `~/News/kiboze/' by default. One contains the NOV header lines for all the articles in the group, and the other is an additional `.newsrc' file to store information on what groups have been searched through to find component articles.

Articles marked as read in the nnkiboze group will have their NOV lines removed from the NOV file.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8 Gnus Unplugged

In olden times (ca. February '88), people used to run their newsreaders on big machines with permanent connections to the net. News transport was dealt with by news servers, and all the newsreaders had to do was to read news. Believe it or not.

Nowadays most people read news and mail at home, and use some sort of modem to connect to the net. To avoid running up huge phone bills, it would be nice to have a way to slurp down all the news and mail, hang up the phone, read for several hours, and then upload any responses you have to make. And then you repeat the procedure.

Of course, you can use news servers for doing this as well. I've used inn together with slurp, pop and sendmail for some years, but doing that's a bore. Moving the news server functionality up to the newsreader makes sense if you're the only person reading news on a machine.

Setting up Gnus as an "offline" newsreader is quite simple. In fact, you don't even have to configure anything.

Of course, to use it as such, you have to learn a few new commands.

6.8.1 Agent Basics  How it all is supposed to work.
6.8.2 Agent Categories  How to tell the Gnus Agent what to download.
6.8.3 Agent Commands  New commands for all the buffers.
6.8.4 Agent Visuals  Ways that the agent may effect your summary buffer.
6.8.5 Agent as Cache  The Agent is a big cache too.
6.8.6 Agent Expiry  How to make old articles go away.
6.8.7 Agent Regeneration  How to recover from lost connections and other accidents.
6.8.8 Agent and IMAP  How to use the Agent with IMAP.
6.8.9 Outgoing Messages  What happens when you post/mail something?
6.8.10 Agent Variables  Customizing is fun.
6.8.11 Example Setup  An example `~/.gnus.el' file for offline people.
6.8.12 Batching Agents  How to fetch news from a cron job.
6.8.13 Agent Caveats  What you think it'll do and what it does.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.1 Agent Basics

First, let's get some terminology out of the way.

The Gnus Agent is said to be unplugged when you have severed the connection to the net (and notified the Agent that this is the case). When the connection to the net is up again (and Gnus knows this), the Agent is plugged.

The local machine is the one you're running on, and which isn't connected to the net continuously.

Downloading means fetching things from the net to your local machine. Uploading is doing the opposite.

You know that Gnus gives you all the opportunity you'd ever want for shooting yourself in the foot. Some people call it flexibility. Gnus is also customizable to a great extent, which means that the user has a say on how Gnus behaves. Other newsreaders might unconditionally shoot you in your foot, but with Gnus, you have a choice!

Gnus is never really in plugged or unplugged state. Rather, it applies that state to each server individually. This means that some servers can be plugged while others can be unplugged. Additionally, some servers can be ignored by the Agent altogether (which means that they're kinda like plugged always).

So when you unplug the Agent and then wonder why is Gnus opening a connection to the Net, the next step to do is to look whether all servers are agentized. If there is an unagentized server, you found the culprit.

Another thing is the offline state. Sometimes, servers aren't reachable. When Gnus notices this, it asks you whether you want the server to be switched to offline state. If you say yes, then the server will behave somewhat as if it was unplugged, except that Gnus will ask you whether you want to switch it back online again.

Let's take a typical Gnus session using the Agent.

Here are some things you should do the first time (or so) that you use the Agent.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.2 Agent Categories

One of the main reasons to integrate the news transport layer into the newsreader is to allow greater control over what articles to download. There's not much point in downloading huge amounts of articles, just to find out that you're not interested in reading any of them. It's better to be somewhat more conservative in choosing what to download, and then mark the articles for downloading manually if it should turn out that you're interested in the articles anyway.

One of the more effective methods for controlling what is to be downloaded is to create a category and then assign some (or all) groups to this category. Groups that do not belong in any other category belong to the default category. Gnus has its own buffer for creating and managing categories.

If you prefer, you can also use group parameters (see section 2.10 Group Parameters) and topic parameters (see section 2.16.5 Topic Parameters) for an alternative approach to controlling the agent. The only real difference is that categories are specific to the agent (so there is less to learn) while group and topic parameters include the kitchen sink.

Since you can set agent parameters in several different places we have a rule to decide which source to believe. This rule specifies that the parameter sources are checked in the following order: group parameters, topic parameters, agent category, and finally customizable variables. So you can mix all of these sources to produce a wide range of behavior, just don't blame me if you don't remember where you put your settings. Category Syntax  What a category looks like. Category Buffer  A buffer for maintaining categories. Category Variables  Customize'r'Us.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Category Syntax

A category consists of a name, the list of groups belonging to the category, and a number of optional parameters that override the customizable variables. The complete list of agent parameters are listed below.

The name of the category.

The list of groups that are in this category.

A predicate which (generally) gives a rough outline of which articles are eligible for downloading; and

a score rule which (generally) gives you a finer granularity when deciding what articles to download. (Note that this download score is not necessarily related to normal scores.)

a boolean indicating whether the agent should expire old articles in this group. Most groups should be expired to conserve disk space. In fact, its probably safe to say that the gnus.* hierarchy contains the only groups that should not be expired.

an integer indicating the number of days that the agent should wait before deciding that a read article is safe to expire.

an integer that overrides the value of gnus-agent-low-score.

an integer that overrides the value of gnus-agent-high-score.

an integer that overrides the value of gnus-agent-short-article.

an integer that overrides the value of gnus-agent-long-article.

a symbol indicating whether the summary buffer should display undownloaded articles using the gnus-summary-*-undownloaded-face faces. The symbol nil will disable the use of undownloaded faces while all other symbols enable them.

The name of a category can not be changed once the category has been created.

Each category maintains a list of groups that are exclusive members of that category. The exclusivity rule is automatically enforced, add a group to a new category and it is automatically removed from its old category.

A predicate in its simplest form can be a single predicate such as true or false. These two will download every available article or nothing respectively. In the case of these two special predicates an additional score rule is superfluous.

Predicates of high or low download articles in respect of their scores in relationship to gnus-agent-high-score and gnus-agent-low-score as described below.

To gain even finer control of what is to be regarded eligible for download a predicate can consist of a number of predicates with logical operators sprinkled in between.

Perhaps some examples are in order.

Here's a simple predicate. (It's the default predicate, in fact, used for all groups that don't belong to any other category.)


Quite simple, eh? This predicate is true if and only if the article is short (for some value of "short").

Here's a more complex predicate:

(or high
     (not low)
     (not long)))

This means that an article should be downloaded if it has a high score, or if the score is not low and the article is not long. You get the drift.

The available logical operators are or, and and not. (If you prefer, you can use the more "C"-ish operators `|', & and ! instead.)

The following predicates are pre-defined, but if none of these fit what you want to do, you can write your own.

When evaluating each of these predicates, the named constant will be bound to the value determined by calling gnus-agent-find-parameter on the appropriate parameter. For example, gnus-agent-short-article will be bound to (gnus-agent-find-parameter group 'agent-short-article). This means that you can specify a predicate in your category then tune that predicate to individual groups.

True iff the article is shorter than gnus-agent-short-article lines; default 100.

True iff the article is longer than gnus-agent-long-article lines; default 200.

True iff the article has a download score less than gnus-agent-low-score; default 0.

True iff the article has a download score greater than gnus-agent-high-score; default 0.

True iff the Gnus Agent guesses that the article is spam. The heuristics may change over time, but at present it just computes a checksum and sees whether articles match.

Always true.

Always false.

If you want to create your own predicate function, here's what you have to know: The functions are called with no parameters, but the gnus-headers and gnus-score dynamic variables are bound to useful values.

For example, you could decide that you don't want to download articles that were posted more than a certain number of days ago (e.g. posted more than gnus-agent-expire-days ago) you might write a function something along the lines of the following:

(defun my-article-old-p ()
  "Say whether an article is old."
  (< (time-to-days (date-to-time (mail-header-date gnus-headers)))
     (- (time-to-days (current-time)) gnus-agent-expire-days)))

with the predicate then defined as:

(not my-article-old-p)

or you could append your predicate to the predefined gnus-category-predicate-alist in your `~/.gnus.el' or wherever.

(require 'gnus-agent)
(setq  gnus-category-predicate-alist
  (append gnus-category-predicate-alist
         '((old . my-article-old-p))))

and simply specify your predicate as:

(not old)

If/when using something like the above, be aware that there are many misconfigured systems/mailers out there and so an article's date is not always a reliable indication of when it was posted. Hell, some people just don't give a damn.

The above predicates apply to all the groups which belong to the category. However, if you wish to have a specific predicate for an individual group within a category, or you're just too lazy to set up a new category, you can enter a group's individual predicate in its group parameters like so:

(agent-predicate . short)

This is the group/topic parameter equivalent of the agent category default. Note that when specifying a single word predicate like this, the agent-predicate specification must be in dotted pair notation.

The equivalent of the longer example from above would be:

(agent-predicate or high (and (not low) (not long)))

The outer parenthesis required in the category specification are not entered here as, not being in dotted pair notation, the value of the predicate is assumed to be a list.

Now, the syntax of the download score is the same as the syntax of normal score files, except that all elements that require actually seeing the article itself are verboten. This means that only the following headers can be scored on: Subject, From, Date, Message-ID, References, Chars, Lines, and Xref.

As with predicates, the specification of the download score rule to use in respect of a group can be in either the category definition if it's to be applicable to all groups in therein, or a group's parameters if it's to be specific to that group.

In both of these places the download score rule can take one of three forms:

  1. Score rule

    This has the same syntax as a normal Gnus score file except only a subset of scoring keywords are available as mentioned above.


  2. Agent score file

    These score files must only contain the permitted scoring keywords stated above.


  3. Use normal score files

    If you don't want to maintain two sets of scoring rules for a group, and your desired downloading criteria for a group are the same as your reading criteria then you can tell the agent to refer to your normal score files when deciding what to download.

    These directives in either the category definition or a group's parameters will cause the agent to read in all the applicable score files for a group, filtering out those sections that do not relate to one of the permitted subset of scoring keywords.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Category Buffer

You'd normally do all category maintenance from the category buffer. When you enter it for the first time (with the J c command from the group buffer), you'll only see the default category.

The following commands are available in this buffer:

Return to the group buffer (gnus-category-exit).

Use a customization buffer to set all of the selected category's parameters at one time (gnus-category-customize-category).

Kill the current category (gnus-category-kill).

Copy the current category (gnus-category-copy).

Add a new category (gnus-category-add).

Edit the predicate of the current category (gnus-category-edit-predicate).

Edit the list of groups belonging to the current category (gnus-category-edit-groups).

Edit the download score rule of the current category (gnus-category-edit-score).

List all the categories (gnus-category-list).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Category Variables

Hook run in category buffers.

Format of the lines in the category buffer (see section 8.4 Formatting Variables). Valid elements are:

The name of the category.

The number of groups in the category.

Format of the category mode line (see section 8.4.2 Mode Line Formatting).

Articles that have fewer lines than this are short. Default 100.

Articles that have more lines than this are long. Default 200.

Articles that have a score lower than this have a low score. Default 0.

Articles that have a score higher than this have a high score. Default 0.

The number of days that a `read' article must stay in the agent's local disk before becoming eligible for expiration (While the name is the same, this doesn't mean expiring the article on the server. It just means deleting the local copy of the article). What is also important to understand is that the counter starts with the time the article was written to the local disk and not the time the article was read. Default 7.

Determines whether articles in a group are, by default, expired or retained indefinitely. The default is ENABLE which means that you'll have to disable expiration when desired. On the other hand, you could set this to DISABLE. In that case, you would then have to enable expiration in selected groups.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.3 Agent Commands

All the Gnus Agent commands are on the J submap. The J j (gnus-agent-toggle-plugged) command works in all modes, and toggles the plugged/unplugged state of the Gnus Agent. Group Agent Commands  Configure groups and fetch their contents. Summary Agent Commands  Manually select then fetch specific articles. Server Agent Commands  Select the servers that are supported by the agent.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Group Agent Commands

J u
Fetch all eligible articles in the current group (gnus-agent-fetch-groups).

J c
Enter the Agent category buffer (gnus-enter-category-buffer).

J s
Fetch all eligible articles in all groups (gnus-agent-fetch-session).

Send all sendable messages in the queue group (gnus-group-send-queue). See section 5.7 Drafts.

J a
Add the current group to an Agent category (gnus-agent-add-group). This command understands the process/prefix convention (see section 8.1 Process/Prefix).

J r
Remove the current group from its category, if any (gnus-agent-remove-group). This command understands the process/prefix convention (see section 8.1 Process/Prefix).

Synchronize flags changed while unplugged with remote server, if any.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Summary Agent Commands

J #
Mark the article for downloading (gnus-agent-mark-article).

J M-#
Remove the downloading mark from the article (gnus-agent-unmark-article).

Toggle whether to download the article (gnus-agent-toggle-mark). The download mark is `%' by default.

J c
Mark all articles as read (gnus-agent-catchup) that are neither cached, downloaded, nor downloadable.

Download all eligible (see section 6.8.2 Agent Categories) articles in this group. (gnus-agent-fetch-group).

J s
Download all processable articles in this group. (gnus-agent-fetch-series).

J u
Download all downloadable articles in the current group (gnus-agent-summary-fetch-group).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Server Agent Commands

J a
Add the current server to the list of servers covered by the Gnus Agent (gnus-agent-add-server).

J r
Remove the current server from the list of servers covered by the Gnus Agent (gnus-agent-remove-server).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.4 Agent Visuals

If you open a summary while unplugged and, Gnus knows from the group's active range that there are more articles than the headers currently stored in the Agent, you may see some articles whose subject looks something like `[Undownloaded article #####]'. These are placeholders for the missing headers. Aside from setting a mark, there is not much that can be done with one of these placeholders. When Gnus finally gets a chance to fetch the group's headers, the placeholders will automatically be replaced by the actual headers. You can configure the summary buffer's maneuvering to skip over the placeholders if you care (See gnus-auto-goto-ignores).

While it may be obvious to all, the only headers and articles available while unplugged are those headers and articles that were fetched into the Agent while previously plugged. To put it another way, "If you forget to fetch something while plugged, you might have a less than satisfying unplugged session". For this reason, the Agent adds two visual effects to your summary buffer. These effects display the download status of each article so that you always know which articles will be available when unplugged.

The first visual effect is the `%O' spec. If you customize gnus-summary-line-format to include this specifier, you will add a single character field that indicates an article's download status. Articles that have been fetched into either the Agent or the Cache, will display gnus-downloaded-mark (defaults to `+'). All other articles will display gnus-undownloaded-mark (defaults to `-'). If you open a group that has not been agentized, a space (` ') will be displayed.

The second visual effect are the undownloaded faces. The faces, there are three indicating the article's score (low, normal, high), seem to result in a love/hate response from many Gnus users. The problem is that the face selection is controlled by a list of condition tests and face names (See gnus-summary-highlight). Each condition is tested in the order in which it appears in the list so early conditions have precedence over later conditions. All of this means that, if you tick an undownloaded article, the article will continue to be displayed in the undownloaded face rather than the ticked face.

If you use the Agent as a cache (to avoid downloading the same article each time you visit it or to minimize your connection time), the undownloaded face will probably seem like a good idea. The reason being that you do all of our work (marking, reading, deleting) with downloaded articles so the normal faces always appear.

For occasional Agent users, the undownloaded faces may appear to be an absolutely horrible idea. The issue being that, since most of their articles have not been fetched into the Agent, most of the normal faces will be obscured by the undownloaded faces. If this is your situation, you have two choices available. First, you can completely disable the undownload faces by customizing gnus-summary-highlight to delete the three cons-cells that refer to the gnus-summary-*-undownloaded-face faces. Second, if you prefer to take a more fine-grained approach, you may set the agent-disable-undownloaded-faces group parameter to t. This parameter, like all other agent parameters, may be set on an Agent Category (see section 6.8.2 Agent Categories), a Group Topic (see section 2.16.5 Topic Parameters), or an individual group (see section 2.10 Group Parameters).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.5 Agent as Cache

When Gnus is plugged, it is not efficient to download headers or articles from the server again, if they are already stored in the Agent. So, Gnus normally only downloads headers once, and stores them in the Agent. These headers are later used when generating the summary buffer, regardless of whether you are plugged or unplugged. Articles are not cached in the Agent by default though (that would potentially consume lots of disk space), but if you have already downloaded an article into the Agent, Gnus will not download the article from the server again but use the locally stored copy instead.

If you so desire, you can configure the agent (see gnus-agent-cache see section 6.8.10 Agent Variables) to always download headers and articles while plugged. Gnus will almost certainly be slower, but it will be kept synchronized with the server. That last point probably won't make any sense if you are using a nntp or nnimap back end.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.6 Agent Expiry

The Agent back end, nnagent, doesn't handle expiry. Well, at least it doesn't handle it like other back ends. Instead, there are special gnus-agent-expire and gnus-agent-expire-group commands that will expire all read articles that are older than gnus-agent-expire-days days. They can be run whenever you feel that you're running out of space. Neither are particularly fast or efficient, and it's not a particularly good idea to interrupt them (with C-g or anything else) once you've started one of them.

Note that other functions, e.g. gnus-request-expire-articles, might run gnus-agent-expire for you to keep the agent synchronized with the group.

The agent parameter agent-enable-expiration may be used to prevent expiration in selected groups.

If gnus-agent-expire-all is non-nil, the agent expiration commands will expire all articles--unread, read, ticked and dormant. If nil (which is the default), only read articles are eligible for expiry, and unread, ticked and dormant articles will be kept indefinitely.

If you find that some articles eligible for expiry are never expired, perhaps some Gnus Agent files are corrupted. There's are special commands, gnus-agent-regenerate and gnus-agent-regenerate-group, to fix possible problems.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.7 Agent Regeneration

The local data structures used by nnagent may become corrupted due to certain exceptional conditions. When this happens, nnagent functionality may degrade or even fail. The solution to this problem is to repair the local data structures by removing all internal inconsistencies.

For example, if your connection to your server is lost while downloaded articles into the agent, the local data structures will not know about articles successfully downloaded prior to the connection failure. Running gnus-agent-regenerate or gnus-agent-regenerate-group will update the data structures such that you don't need to download these articles a second time.

The command gnus-agent-regenerate will perform gnus-agent-regenerate-group on every agentized group. While you can run gnus-agent-regenerate in any buffer, it is strongly recommended that you first close all summary buffers.

The command gnus-agent-regenerate-group uses the local copies of individual articles to repair the local NOV(header) database. It then updates the internal data structures that document which articles are stored locally. An optional argument will mark articles in the agent as unread.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.8 Agent and IMAP

The Agent works with any Gnus back end, including nnimap. However, since there are some conceptual differences between NNTP and IMAP, this section (should) provide you with some information to make Gnus Agent work smoother as a IMAP Disconnected Mode client.

The first thing to keep in mind is that all flags (read, ticked, etc) are kept on the IMAP server, rather than in `.newsrc' as is the case for nntp. Thus Gnus need to remember flag changes when disconnected, and synchronize these flags when you plug back in.

Gnus keeps track of flag changes when reading nnimap groups under the Agent. When you plug back in, Gnus will check if you have any changed any flags and ask if you wish to synchronize these with the server. The behavior is customizable by gnus-agent-synchronize-flags.

If gnus-agent-synchronize-flags is nil, the Agent will never automatically synchronize flags. If it is ask, which is the default, the Agent will check if you made any changes and if so ask if you wish to synchronize these when you re-connect. If it has any other value, all flags will be synchronized automatically.

If you do not wish to synchronize flags automatically when you re-connect, you can do it manually with the gnus-agent-synchronize-flags command that is bound to J Y in the group buffer.

Some things are currently not implemented in the Agent that you'd might expect from a disconnected IMAP client, including:

Technical note: the synchronization algorithm does not work by "pushing" all local flags to the server, but rather incrementally update the server view of flags by changing only those flags that were changed by the user. Thus, if you set one flag on an article, quit the group and re-select the group and remove the flag; the flag will be set and removed from the server when you "synchronize". The queued flag operations can be found in the per-server flags file in the Agent directory. It's emptied when you synchronize flags.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.9 Outgoing Messages

When Gnus is unplugged, all outgoing messages (both mail and news) are stored in the draft group "queue" (see section 5.7 Drafts). You can view them there after posting, and edit them at will.

When Gnus is plugged again, you can send the messages either from the draft group with the special commands available there, or you can use the J S command in the group buffer to send all the sendable messages in the draft group.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.10 Agent Variables

Where the Gnus Agent will store its files. The default is `~/News/agent/'.

Groups on levels (see section 2.6 Group Levels) higher than this variable will be ignored by the Agent. The default is gnus-level-subscribed, which means that only subscribed group will be considered by the Agent by default.

Hook run when connecting to the network.

Hook run when disconnecting from the network.

Hook run when finished fetching articles.

Variable to control whether use the locally stored NOV and articles when plugged, e.g. essentially using the Agent as a cache. The default is non-nil, which means to use the Agent as a cache.

If gnus-agent-go-online is nil, the Agent will never automatically switch offline servers into online status. If it is ask, the default, the Agent will ask if you wish to switch offline servers into online status when you re-connect. If it has any other value, all offline servers will be automatically switched into online status.

If gnus-agent-mark-unread-after-downloaded is non-nil, mark articles as unread after downloading. This is usually a safe thing to do as the newly downloaded article has obviously not been read. The default is t.

If gnus-agent-consider-all-articles is non-nil, the agent will let the agent predicate decide whether articles need to be downloaded or not, for all articles. When nil, the default, the agent will only let the predicate decide whether unread articles are downloaded or not. If you enable this, you may also want to look into the agent expiry settings (see section Category Variables), so that the agent doesn't download articles which the agent will later expire, over and over again.

The agent fetches articles into a temporary buffer prior to parsing them into individual files. To avoid exceeding the max. buffer size, the agent alternates between fetching and parsing until all articles have been fetched. gnus-agent-max-fetch-size provides a size limit to control how often the cycling occurs. A large value improves performance. A small value minimizes the time lost should the connection be lost while fetching (You may need to run gnus-agent-regenerate-group to update the group's state. However, all articles parsed prior to loosing the connection will be available while unplugged). The default is 10M so it is unusual to see any cycling.

Perhaps not an Agent variable, but closely related to the Agent, this variable says what will happen if Gnus cannot open a server. If the Agent is enabled, the default, nil, makes Gnus ask the user whether to deny the server or whether to unplug the agent. If the Agent is disabled, Gnus always simply deny the server. Other choices for this variable include denied and offline the latter is only valid if the Agent is used.

Another variable that isn't an Agent variable, yet so closely related that most will look for it here, this variable tells the summary buffer how to maneuver around undownloaded (only headers stored in the agent) and unfetched (neither article nor headers stored) articles.

The valid values are nil (maneuver to any article), undownloaded (maneuvering while unplugged ignores articles that have not been fetched), always-undownloaded (maneuvering always ignores articles that have not been fetched), unfetched (maneuvering ignores articles whose headers have not been fetched).

If you have never used the Agent before (or more technically, if `~/News/agent/lib/servers' does not exist), Gnus will automatically agentize a few servers for you. This variable control which backends should be auto-agentized. It is typically only useful to agentize remote backends. The auto-agentizing has the same effect as running J a on the servers (see section Server Agent Commands). If the file exist, you must manage the servers manually by adding or removing them, this variable is only applicable the first time you start Gnus. The default is `(nntp nnimap)'.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.11 Example Setup

If you don't want to read this manual, and you have a fairly standard setup, you may be able to use something like the following as your `~/.gnus.el' file to get started.

;;; Define how Gnus is to fetch news.  We do this over NNTP
;;; from your ISP's server.
(setq gnus-select-method '(nntp "news.your-isp.com"))

;;; Define how Gnus is to read your mail.  We read mail from
;;; your ISP's POP server.
(setq mail-sources '((pop :server "pop.your-isp.com")))

;;; Say how Gnus is to store the mail.  We use nnml groups.
(setq gnus-secondary-select-methods '((nnml "")))

;;; Make Gnus into an offline newsreader.
;;; (gnus-agentize) ; The obsolete setting.
;;; (setq gnus-agent t) ; Now the default.

That should be it, basically. Put that in your `~/.gnus.el' file, edit to suit your needs, start up PPP (or whatever), and type M-x gnus.

If this is the first time you've run Gnus, you will be subscribed automatically to a few default newsgroups. You'll probably want to subscribe to more groups, and to do that, you have to query the NNTP server for a complete list of groups with the A A command. This usually takes quite a while, but you only have to do it once.

After reading and parsing a while, you'll be presented with a list of groups. Subscribe to the ones you want to read with the u command. l to make all the killed groups disappear after you've subscribe to all the groups you want to read. (A k will bring back all the killed groups.)

You can now read the groups at once, or you can download the articles with the J s command. And then read the rest of this manual to find out which of the other gazillion things you want to customize.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.12 Batching Agents

Having the Gnus Agent fetch articles (and post whatever messages you've written) is quite easy once you've gotten things set up properly. The following shell script will do everything that is necessary:

You can run a complete batch command from the command line with the following incantation:

emacs -batch -l ~/.emacs -l ~/.gnus.el gnus-agent-batch >/dev/null 2>&1

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8.13 Agent Caveats

The Gnus Agent doesn't seem to work like most other offline newsreaders. Here are some common questions that some imaginary people may ask:

If I read an article while plugged, do they get entered into the Agent?

No. If you want this behavior, add gnus-agent-fetch-selected-article to gnus-select-article-hook.

If I read an article while plugged, and the article already exists in
the Agent, will it get downloaded once more?

No, unless gnus-agent-cache is nil.

In short, when Gnus is unplugged, it only looks into the locally stored articles; when it's plugged, it talks to your ISP and may also use the locally stored articles.

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by XEmacs Webmaster on October, 2 2007 using texi2html