flail - a hacker's mailer in Perl
# to run a single flail command: $ flail -1 -other_options [cmd ... args ...] # to get into the interactive command loop $ flail # to get a usage message: $ flail -h # to get the whole manual $ flail -hv
flail is a hacker's mailer, written in Perl, and sporting a command-line interface. It currently supports pop3 and imap for access to remote maildrops, as well as regular old Unix mail spool files for local maildrops (e.g. because you use fetchmail).
The commands are vaguely Unix-like (rm, cp, mv, cat, ls). There are facilities for mapping bits of perl code over some subset of the messages in a folder, crypto, external editors, and user-defined commands.
You naturally invoke flail on the command-line. It takes single-letter options, just like Pan intended. Where it makes sense, we note the name of the config variable corresponding to each option in parentheses.
Do not ask for Cc: addresses by default in the composer
Confirm with user before sending message
Allow the alias command to override built-in commands.
Be Vewy Quiet: Only produce error messages and explicitly request output (e.g. ls)
Remove messages from server during get processing.
get
When by itself, display usage message. When specified with -v, display this POD.
Automatically sync the current folder after operations that change it, e.g. mv, rm, ...
Read message from stdin; really only useful in conjunction with <-1>. Implies -c.
-c
Run a single flail command, specified as arguments on the command line. For instance
$ flail -1 send rms@mit.edu
can be used to send a single message to someone famous.
Make ourselves verbose.
Specify an alternate rc file. The default is ~/.flailrc
~/.flailrc
Specify an alternative directory for mail folders. The default is ~/mail
~/mail
Specify an alterntive incoming mail folder name. The default is INCOMING
INCOMING
These options are largely outdated, but can still be useful, especially in conjunction with -1.
-1
In both cases, a string of the form user@server:port, where user and port are both optional, and given the obvious default values if left unspecified.
user@server:port
user
port
These are also probably only really useful with -1, since your ~/.flailrc will probably arrange to set them in less obvious ways. These options set the From address, domain, and SMTP relay used to send a message.
Set the temp dir used for e.g. message composition.
Set the external editor used from the composer. Defaults to your $EDITOR environment variable.
$EDITOR
Set the folder name in which to automatically file outgoing messages.
Outdated: specify default message check method, pop3 or imap. Since you can have more than one account of each kind, sort of silly. If you do not specify any arguments to check, we use $CheckType as the default.
check
$CheckType
File containing your addressbook as a dbm file.
Do not use an addressbook.
Automatically try to look up all outgoing addresses in our addressbook.
Interactively prompt the user for address book matches before sending.
Only match two addresses if the hostnames are identical.
Make addressbook functionality quiet.
Label all incoming messages with newlabel by default.
newlabel
Look for dot.sigs in dot.sig.dir
Turn on debugging output. Not useful for ordinary use.
Set the default subject for outgoing email. None by default
If -p is specified, then -U says that the entire message, including headers, is coming in on stdin.
-p
-U
The command language is vaguely Unixy. Commands look like:
word [arg arg...]
Some commands take slash-style options, ala TOPS-20:
send/as:someone@somewhere ...
Many (most?) commands at least will pay attention to options named debug, verbose and quiet. For instance, to turn on SMTP debugging when you send an email:
debug
verbose
quiet
send/debug to@some.one
The first character of a command might specify another action than a normal command:
Execute Unix command cmd and display results on stdout
cmd
Pipe the current message through cmd and display the results on stdout
Evaluate the perl code code. Does not display results by default, if you want them, use the print statement, e.g.
code
print
,print $Editor
Other than those special cases, we look at our first word and dispatched based on it. The complete list of built-in commands follows, grouped by function. For information on adding your own commands, see the section on CONFIGURATION, below.
Message Sequences (also called "Range Expressions") are an important part of the flail command language. The following are all valid range expressions:
Message 1
1:3
Messages 1 through 3
3:$
Messages 3 through the end of the folder.
$-3:$
The last three messages in a folder
1,3,5,$-3:$-1
The first, third, and fifth messages, as well as the second two from the end (not including the last one)
In addition, you can specify -label to include all messages tagged with the given label, so the range expression -marked expands to all marked messages.
-label
-marked
Many commands take message sequences in place of single message numbers. Some do not. Hopefully, I'll do a good job of telling you which is which.
Commands to query and fetch mail from mail spools.
Check a mailbox for mail. The full syntax is
check type user server
e.g.
check pop3 attila mailserver
looks for mail using pop3 on mailserver as the user attila. You will be prompted for a password, unless flail remembers what it is. The remember_password internal function can be useful in your configuration file to keep you from having to type your password all the time. If you insist, you can specify your password as the final argument on the command line, but we don't recommend it.
remember_password
To check a local spool file, use
check spool /path/to/spool
The default spool is /var/mail/yourusername, so if this is correct you can just do
/var/mail/yourusername
check spool
to check your local mail spool. You can override both the file name and directory with the $SpoolFile and $SpoolDir configuration variables in your ~/.flailrc.
$SpoolFile
$SpoolDir
Just like the check command, except that we fetch the mail and incorporate it into the incoming folder. It takes the same type parameter as its first argument, e.g.
type
get spool
grabs (and expunges) your local mail spool.
These commands are for stumbling around in the folder tree and looking at messages.
If you have a folder selected, flail shows you what it is in your prompt. If your prompt is simply
flail>
then you are not in any folder, and many of these commands will fail with an error.
Move to the next message.
Move to the previous message.
Go to a message by number, e.g.
goto 3
moves to the message numbered 3 in the output of ls
ls
Displays the current message, or one by number if specified. Output is paginated if we know how to do that on your terminal.
The cat command normally shows abbreviated headers. The headers command shows only the headers for a message, and it shows them all.
cat
headers
Not yet implemented.
Copy a message to another folder, e.g.
cp 3 spam
copies message 3 to the folder named SPAM
Like cp, but removes the message from the current folder after it is copied. If $SyncImmediately is true, we sync the folder afterwards. Otherwise, the message appears with the D (Deleted) flag turned on until you sync.
cp
$SyncImmediately
D
sync
A message sequence can be specified, e.g.
mv 1,2,$-3:$ odd_folder
Delete a message or messages, e.g.
rm 1:$
deletes all messages in the current folder.
flail uses Mail::Folder, and can thus support any type of mail folder that it supports. Generally, we use mbox folders, which are single files containing multiple messages. None the less, we treat "folders" as if they were directories from the command language, for consistency.
Change the object of your affections to another folder, e.g.
cd INCOMING
Show the current folder and your state in it.
List the contents of the folder, one message per line. If $PlainOutput is not true, we try to color it nicely for ttys that support ANSI color sequences, like xterm. If a message sequence is specified, we only show those messages. Output is paginated.
$PlainOutput
xterm
If you are not in a folder, then ls shows you the subfolders in whatever part of the folder tree you happen to be in. If you are at top level, this is all of the top-level folders under the root.
You can specify an arbitrary range expression to ls, as you can with many other commands. For instance,
ls -marked
will list all marked messages.
Not yet implemented. For now, use the following idiom
!touch foldername
to create a new blank folder (remember: we chdir to your $FolderDir on startup...).
$FolderDir
Things that call the composer. See MESSAGE COMPOSITION INTERFACE, below, for details.
Send a message to the addresses given as arguments. The From address can be set explicitly with the as option, e.g.
From
as
send/as:bozo@clown.com gosper@mathematicians.org
If there is a problem, you might re-trying the send command with the debug option, which turns on Net::SMTP debugging and will produce a large amount of output.
send
We invoke the external editor of your choice for composition, which should return a valid status code. You will generally have a chance to go over it, re-edit it, abort, cryptosign, attach .sig, etc. after you're done editing.
Like send, but replies to the sender of a previous message.
Like send, but forwards an existing message to a third party.
Like send, but resends a message that was bounced.
The address command has several subcommands to help you manage your addresses. Flail stores these in a dbm file, typically called ~/.flail_addressbook.
address
~/.flail_addressbook
Subcommands:
Add a new entry. Nickname must be unique in your addressbook.
Show the address associated with the given nickname.
Search the addressbook by regexp, or list the whole thing if no regexp specified
Remove an entry by nickname
Import address book data stored in a file. The two kinds of files we currently support are LDIF and CSV; files should have extensions that reflect their type, e.g .ldif or .csv.
.ldif
.csv
Extract email addresses from one or more messages and import them into your addressbook. If no label is specified, the current message is examined; otherwise, all messages in the current folder with the specified label are examined.
Messages can have an arbitrary set of labels associated with them. Some, such as deleted and filed, have meaning to flail itself. Some, such as marked or whatever other string you might use, are just for your own purposes. Marking messages lets you apply code to them, so flail users do it alot.
deleted
filed
marked
In the absence of any arguments, applies the marked label to the current message.
If a message sequence is specified, then all messages in that sequence get the marked label. If the word all is specified, then all messages get marked.
all
If the first character of our first argument is a comma, then the rest of the arguments are treated as a bit of perl code that is invoked for every message in the folder. The token %m will be substituted for a variable that is bound to an Mail::Internet object representing each message in the folder on subsequence calls.
%m
For instance, if we have in our configuration
sub is_blue { shift->get("Subject") =~ /\[blue\]/; }
Then we can do
mark ,is_blue(%m)
to mark all messages whose Subject headers contain the string [blue].
Subject
[blue]
Unmark takes the same argumentology as mark, but removes the marked label instead.
map label ...
Run a command or piece of code over a set of messages, specified by a label. If the label is all, then all messages have the action applied to them. The action can be a flail command, or a piece of random Perl code. In the latter case, the first character of the code should be a curly brace, and the code should end with one as well, e.g.
map marked { grep_msg('Foo'); }
Runs the given code for each message. The code is called in a context where the following globals are available in the main namespace:
main
If there are no curly braces, the command should be a legal flail command. In both cases, two additional substitutions take place:
after
This last substitution is a bit odd, and requires explaining.
Supposing we have our hypothetical sub grep_msg (which does in fact come with the dot.flailrc in the distribution). It wants a regexp as its argument. It uses $M, etc. to get at the message it is grepping. Supposing we want to be able to type
grep_msg
dot.flailrc
$M
mgrep pattern
to run grep_msg("pattern") over each message. How do we do it?
grep_msg("pattern")
alias mgrep map all { grep_msg("%*"); }
Now, when we type
The %* is substituted with pattern. This is why map is useful even when operating on a single message.
%*
pattern
map
Another enlightening example:
alias mmv map marked mv %n %*
This creates an alias, mmv, which can be used thusly:
mmv
# arrange to mark the messages that are spam, # either by hand ... mark 1,3,5 # or by some automated oracle mark ,is_spam(%m) # now, move it all to a folder named spam mmv spam
Of course this is just a contrived example, since you can accomplish the same thing with labels, e.g.
mv -marked spam
will move all marked messages to the folder named spam.
spam
Given a label, count the messages that match it. If no label is specified, marked is assumed.
Given a label, run all of the message hooks associated with that label over every message that has that label in the current folder. See the discussion on message hooks in Hacking Flail, below.
Flush any changes to the current folder to disk. This includes expunging messages labeled deleted.
Resets the password cache and/or the connection cache.
This needs a rewrite, as my crypto fu relies on outdated modules and must be rewritten.
Create a new command. You cannot overwrite existing command table entries this way; use Perl code in your config file instead.
Example:
alias mvspam map marked mv %n spam
Remove an alias.
You can ask for help on any specific command or alias by using it as an argument, e.g.
help ls
Invoking help with no arguments produces a list of commands.
In addition to commands, you can ask for help on the following subjects
spit out the flail manual (thanks to Pod::Usage)
show our version information
show our full license
show our warranty
Bug out, flushing all changes.
If you want to bug out without saving anything, use Perl:
,exit
When you are sending a message, you will be generally be prompted before it goes out. The prompt allows you to perform some fairly complex sequences of actions with a few keystrokes, and is usually called the composer.
XXX Write more.
flail is a hacker's mailer. Configuring flail means writing Perl code. If this does not fill you with joy, you're in the wrong bar.
Flail loads ~/.flailrc upon startup. An extensive example comes with the distribution (dot.flailrc). You can specify another file with the -c command-line option.
Command-line options will already have been parsed by the time your rc file is loaded. This means you can check for the value of e.g. $SingleCommand to see if -1 was specified on the command line, etc.
$SingleCommand
Flail is ultimately just a bunch of Perl subs. It currently all lives in the main package, which is where your flailrc is loaded as well. This means you can write code that calls any flail primitive, add new primitives, or extend the command set using the same API (if you want to diginfy it with that name) that I use.
WARNING: I will be rewriting flail to use OO techniques in the very near future. You should get on the flail-dev mailing list if you are interested.
flail-dev
Too many bugs to count at the moment...
Sean Levy <snl@cluefactory.com> wrote this thing, sometime in or around 2000 most likely, although he can't quite remember the exact year. It started out as a pile of hacks and has matured and blossomed into a GREAT FREAKING HUGE PILE OF HACKS.
Sean is also known as attila <attila@stalphonsos.com>, for historical reasons almost entirely under his control. That's "Saint Alphonsos".
Alice: Well I must say I've never heard it that way before...
Caterpillar: I know, I have improved it.
0.2.5 06 Sep 08 attila found some lost hacks from a source tree recovered from a dead laptop: semi-colon-separated commands, send_via_program, a couple other things. 0.2.4 05 Aug 08 attila revived from the dead AGAIN after t-bird screwed me hard. 0.2.3 30 Jun 06 attila released on freshmeat 0.2.2 26 Jun 06 attila wrote pod, use strict, blah blah added local spools 0.2.1 25 Jun 06 attila fixed horrible bug in get_imap 0.2.0 24 Jun 06 attila resurrected after i got sick of VM 0.1.28 26 Feb 03 attila 0.1.28 released 0.1.? ?? ??? 02 attila Somewhere around 2002 I found myself using flail everyday and thought perhaps I should release it or something 0.0.0 ?? ??? 00 attila Sometime in y2k I had a brain schizm and decided to write an MUA in perl
Copyright (C) 1999,2000 St. Alphonsos. Copyright (C) 2000-2008 by Sean Levy <snl@cluefactory.com>. All Rights Reserved. Redistribution and use in any form, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. The names "St. Alphonsos", "The Clue Factory", and "Sean Levy" must not be used to endorse or promote products derived from this software without prior written permission. To obtain permission, contact info@stalphonsos.com or snl@cluefactory.com 3. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by St. Alphonsos http://www.stalphonsos.com/ and Sean Levy <snl@cluefactory.com>" THIS SOFTWARE IS PROVIDED BY ST. ALPHONSOS, THE CLUE FACTORY AND SEAN LEVY ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ST. ALPHONSOS NOR ITS EMPLOYEES, THE CLUE FACTORY NOR ITS EMPLOYEES, OR SEAN LEVY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4 POD Errors
The following errors were encountered while parsing the POD:
Expected '=item 2'
Expected '=item 3'
Expected '=item 4'
Expected '=item 5'
To install Flail, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Flail
CPAN shell
perl -MCPAN -e shell install Flail
For more information on module installation, please visit the detailed CPAN module installation guide.