Skip to content

aligrudi/neatmail

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NEATMAIL
========

Neatmail is a noninteractive mail client.  It generates listings of,
and executes ex-like commands on messages in mailboxes in mbox format.

Neatmail provides the following commands (when invoked without an
argument, most of them show a summary of supported options).

* mk: generate a listing of messages in an mbox.
* ex: execute the specified commands on an mbox.
* pg: page a message in an mbox.
* pn: prune an mbox (shorten messages).
* ns: check for new messages among several mboxes.
* me: MIME-encode message headers.

For each message, the mk command writes tab-separated values of some
of its headers.  This set of headers and the maximum length of each of
them can be specified with -0 option.  In addition to message headers,
~subject (more compact subject header with thread indentation), ~size
(message size), and ~date (receiving date) can also be given.  Each
line begins with the value of the status header of the message (N if
it is missing) and its message number.  Neatmail assumes that the
status of a message, if present, is one or two capital letters (the
first letter may be N for new, R for read, and O for old; the second
letter, if present, may indicate user-defined categories).  This is an
example invocation of mk:

$ neatmail mk -0 10from:20~subject: -st test/test.mbox
N00000	[A <a@a.eu>]	[Message from A      ]
N00001	[B <b@b.eu>]	[Message from B      ]
N00002	[C <c@c.eu>]	[Message from C      ]

The ex command reads a list of commands from the standard input and
executes them on a given mbox file.  It ignores all input lines except
those beginning with a colon or a capital letter.  Lines beginning
with a capital letter like "R100 ...", change the value of the status
header of the message whose number follows the letter.  It also marks
the current message.  Lines beginning with a colon are named commands.
The list of named commands are as follows:

* rm: remove the message.
* cp: copy the message to another mbox.
* mv: move the message to another mbox.
* hd, set: change the value of the given header of the message.
* ft, filt: filter the message through the given command.
* w: write the mbox.
* g, g!: ex-like global command.
* tj: join threads by modifying "Reply-To" headers.
* ch: chop the message at the specified offset in kilobytes.

These commands act on the current message by default (if applicable),
but different messages may be specified using ex-like addresses.  For
instance, "2,5rm" removes messages 2 through 5.  Addresses may contain
search patterns, like "/pattern/rm", in which the pattern is a POSIX
extended regular expression (the same applies to global command
patterns like "%g/pattern/rm").  Search patterns are matched to the
subject field of message headers, except when the pattern is "^field:
value", in which it is matched against the specified header field
instead.

In the following example, ex removes message 1, moves all messages
whose subjects match ".*neatmail.*" to mail.mbox file, and updates the
mbox.

$ neatmail ex new.mbox <<EOF
O000
O001
:rm
R003
R002
N004
:%g/^subject:.*neatmail.*/mv mail.mbox
:w
EOF

SUGGESTED USAGE
===============

Generate a message listing (see mk options):
$ neatmail mk -st -r inbox >inbox.nm

Open inbox.nm in an editor, change the status field of
messages, and append ex commands.

Page, reply, or forward messages (see pg options):
$ neatmail pg -m -h from: -h subject: -h to: -h cc: 23@inbox >mail

Execute the commands specified in inbox.nm:
$ (cat inbox.nm; echo ":w") | neatmail ex inbox

It is more convenient to place these commands in a script.  For
fetching and sending messages, I use https://github.com/aligrudi/neatpop3
and https://github.com/aligrudi/neatsmtp.

LARGE MBOXES
============

Mbox files can gradually get very large, particularly because of
messages with large attachments.  This makes Neatmail commands slow.
To reduce the size of such files, I move old messages to new, archival
mboxes using :mv ex command.  Then, I use the pn command to obtain
smaller versions of these mbox files by removing message bodies and
unnecessary headers (I use a Makefile to update them automatically):

$ neatmail pn -H -s0 old >old.i

Note that the original messages are kept just in case their contents
are needed.  Neatmail commands can read multiple mbox files.  This
makes it possible to generate a mail listing of the main mbox and
pruned files:

$ neatmail mk -m6 -st -r inbox old.i >inbox.nm

The -m option forces mk to include the first few letters of the file
that contains this message, like "R0020@old.i", which means the 20th
message in the old.i mbox file (it does so only for messages not in
the first given mbox file).  To obtain the contents of the message,
the original file can be read.  For instance, the following command
prints the 20th message in old:

$ neatmail pg 20@old

To make pg faster for large mbox files, pn includes a Neatmail-Source
header to indicate the exact position of the original message (before
pruning).  When accessing the message, pg reads it from the location
indicated by Neatmail-Source, if the header is present and -s is
provided.  Because the offset of the message is stored in
Neatmail-Source, the whole mbox need not be read and it is much faster
(compare pg -s 20@old.i and pg 20@old in the above example).