O'Reilly Hacks
oreilly.comO'Reilly NetworkSafari BookshelfConferences Sign In/My Account | View Cart   
Book List Learning Lab PDFs O'Reilly Gear Newsletters Press Room Jobs  



Interleave Mail and Pine
Use Mac OS X's Mail and Terminal-based Pine mail applications interchangeably as the mood strikes.

Contributed by:
Rael Dornfest
[04/14/03 | Discuss (3) | Link to this hack]

Sometimes you feel like a GUI, sometimes you don't.

Mac OS X's built-in Mail application is a crisp, clean, all-but-powerful email client used by just about everyone who comes to OS X. It sports easy configuration, an intuitive interface, simple mail shuffling and filtering, and a terrific adaptive spam filter.

Pine is a lightweight, powerful, and just-about-as-intuitive-as-you-can-get-on-the-command-line text-based email client. Featuring configurability to the nth, an all-keystroke interface, and countless ways to sort, shuffle, and sift through your email, Pine is often the quickest way to deal with your morning's -- or, indeed, vacation's -- worth of email. Not to mention using email remotely via telnet or SSH over a slow, choppy modem connection ill suited to remote desktop Mail usage.

While Mail satisfies my sweet tooth, I often yearn for the no-nonsense interface to my email of Pine, my mailer of choice for a good many years. Then again, Pine has nothing on Mail when it comes to viewing HTML and oddly encoded messages and dealing with attachments. Wouldn't it be nice to use them interchangeably as the mood strikes?

Of course IMAP is always an option, allowing for virtually-seemless switching between about any IMAP-enabled email client, Pine included. But I usually find myself wanting the raw sorting abilities of Pine when I'm blazing through old email on a plane flight and, without connectivity, I'm pretty well out of luck. A local IMAP install (in concert with fetchmail mail retrieval) does the trick, allowing you to have your mail on your laptop, yet still usable from about any email client. But this means dealing with some of the oddities, restrictions, and speed of IMAP -- these sometimes differ from client to client.

There is a simpler and more efficient solution, at least when it comes to using the Mail and Pine email clients specifically. It turns out that both share the same semi-standard "mbox" mailbox format. So you can point Pine at one of your Mail mailboxes -- whether an Inbox or arbitrary mail folder -- and it'll read from and write to it like a champ. The inconvenience comes in not being able to simply point Pine at Mail's Mailboxes directory (Home > Library > Mail > Mailboxes) since Mail lays things out differently and makes use of some index and other files that would only clutter Pine's Folder List.

A typical Mail folder looks something like this:

House
  Home Repair.mbox
    Info.plist
    mbox.SKindex
    mbox.SKindex.isValid
    table_of_contents
House.mbox
  Info.plist
  mbox.SKindex
  mbox.SKindex.isValid
  table_of_contents
Here, House is a folder containing a Home Repair mailbox, but House is also, itself, a mailbox -- notice House.mbox. So you can drop messages into both the Home Repair mailbox and into the House folder enclosing it, a somewhat confusing dual-role when you look at it from the command-line point-of-view, even though perfectly understandable from within Mail.

Each mailbox (.mbox) contains several files, only one of which is useful for our purposes at hand: mbox. The mbox file contains the actual messages in a particular mailbox in plain text, readable by Pine. The Info.plist file contains internal user preferences for the mailbox at hand and those SKindex and table_of_contents files are Mail's indexes for the mailbox -- all useless to Pine.

The Code

Loosely based on an idea posted to MacOSXHints, the following script traverses your Mail mailboxes and creates a representative mailbox/folder hierarchy in Pine's preferred mail directory, Home/mail.
Note: MacOSXHints's version didn't quite suit my needs since it didn't take into account mailboxes within folders within folders within... Also, this version is a self-contained script taking care of Inboxes, mailboxes/folders, and Sent Items in one fell swoop.
Nested folders (e.g. House > Home Repair) are represented as nested folders/directories and the mailboxes they contain as mailboxname.mbox (e.g. Home Repair.mbox). Also symlinked are the Inboxes associated with each of your Mail accounts and the Sent Messages folder associated with the first account the script finds so that your sent messages are also archived in a Mail-accessible location.
#!/usr/bin/perl

# Mail2Pine
# Author: Rael Dornfest <rael@oreilly.com>
# Version: 2003-04-14

# Creates symbolic links between Mac OS X's Mail.app inboxes and
# mailboxes and Pine's mail directory (~/mail) allowing you to interleave
# Mail.app and Pine usage as the mood strikes.

my $user = $ENV{USER};
my $account_dir = "/Users/$user/Library/Mail/";
my $mailbox_dir = "/Users/$user/Library/Mail/Mailboxes";
my $mail_dir = "/Users/$user/mail";

use File::Find;

# Make a pine mail directory
-d $mail_dir or mkdir $mail_dir, 0700;

# Find and symlink Mail.app's account inboxes to ~/mail
find(\&accounts, $account_dir);

sub accounts {
  $File::Find::name =~ m!(POP-[^\/]+)/INBOX.mbox/mbox$! or return 0;

  # Symlink the INBOX  
  -e "$mail_dir/INBOX-$1" 
    or symlink($File::Find::name, "$mail_dir/INBOX-$1");

  # Symlink the Sent Messages mailbox if first account found
  -e "$mail_dir/sent-mail"
    or `ln -s "$account_dir/$1/Sent Messages.mbox/mbox" "$mail_dir/sent-mail"`;
}

# Find and symlink Mail.app's mailboxes to ~/mail
find(\&mailboxes, $mailbox_dir);

sub mailboxes {
  $File::Find::name =~ /SKindex/ and return 0;

  my($path, $mbox) = $File::Find::name =~ 
    m!^$mailbox_dir/(.*/)?([^\/]+)\.mbox/mbox!;
  
  $mbox or return 0;

  # Perform a little cleanup on paths and mbox filenames
  $path =~ s!^/|/$!!g;
  $path =~ s/[^\w\/]/_/g;
  $mbox =~ s!^/|/$!!g;
  $mbox =~ s/\W/_/g;

  $File::Find::name =~ s! !\\ !g;

  #print "$File::Find::name ~/mail/$path/$mbox\n";

  `mkdir -p $mail_dir/$path`;
  -e "$mail_dir/$path/$mbox" 
    or `ln -s $File::Find::name $mail_dir/$path/$mbox.mbox`;
}

Running the Hack

Copy and paste the script into TextEdit or the like and save it to a text file -- mail2pine.pl on your Desktop, for example. Fire up the Terminal application (Applications > Utilities > Terminal) and run it like so:
% cd ~/Desktop
% perl mail2pine.pl
That's all there is to it. Your Pine mail directory (Home > mail) hierarchy should look something like:
sent-mail
Drafts.mbox
Family.mbox
Friends.mbox
House
  Home Repair.mbox
House.mbox
INBOX-POP-rael@oreilly.com
INBOX-POP-raelity@raelity.org
...
Of course your accounts and folders will be different from mine. Notice how the script keeps the mailboxes proper as .mbox so as to distinguish them from folders of the same name (e.g. House vs. House.mbox).

Using Pine

Let's take a gander at those new accounts, folders, and mailboxes in Pine, shall we? Launch Pine by typing pine on your Terminal command-line. Select Folder List by typing an L and your list should look something like:
  PINE 4.53   FOLDER LIST        Folder: INBOX-POP-rael@localhost  5 Messages   

INBOX                                  sent-mail
Drafts.mbox                            Family.mbox
Friends.mbox                           House
INBOX-POP-rael@oreilly.com             INBOX-POP-raelity@raelity.org
...

                              [ALL of folder list]
? Help       < Main Menu   P PrevFldr     - PrevPage A Add        R Rename      
O OTHER CMDS > [View Fldr] N NextFldr   Spc NextPage D Delete     W WhereIs 
Of course your accounts and folders will be different from mine. I have two accounts, represented by the two INBOX-POP files; most of you will have only one. The sent-mail file is a symbolic link to Mail's Sent Items folder associated with the first account the mail2pine.pl script found, INBOX-POP-rael@oreilly.com. Notice the couple of mailboxes, Family.mbox and Friends.mbox, along with our House folder we mentioned above.

To visit an account's Inbox, select the appropriate INBOX-POP-account_name using the arrow keys and hit the return key to select it. Here's my rael@oreilly.com inbox, doctored more than slightly for illustrative purposes:

  PINE 4.53   MESSAGE INDEX Folder: BOX-POP-rael@oreilly.com  Message 5 of 5 NEW  

      1 Apr  9 Silly Sammy Slick   (2144) mail2pine is nifty!                      
  N   2 Apr 14 JJJ Schmidt         (6269) you gotta love that... 
...

? Help       < FldrList   P PrevMsg       - PrevPage D Delete     R Reply       
O OTHER CMDS > [ViewMsg]  N NextMsg     Spc NextPage U Undelete   F Forward    
Visiting my House folder, either from the Folder List or from the Message window by typing G (as in "Go"), House, hitting the tab key, and selecting the House/ folder, finds it contains, as expected, a Home Repair mailbox:
  PINE 4.53   FOLDER LIST Folder: -POP-rael@rael@oreilly.com       22 Messages   

                             Local folders in mail/
                                   Dir: House/
--------------------------------------------------------------------------------

Home_Repair.mbox 
...

Fetching Mail

You'll still want Mail fetching your mail for your various accounts from their associated mail servers, filtering and junking using your rules and Mail's Junk Mail filter. Just leave it running, hiding it from the Desktop if you so wish -- it is less confusing than having both it and Pine running on your Desktop at the same time.


O'Reilly Home | Privacy Policy

© 2007 O'Reilly Media, Inc.
Website: | Customer Service: | Book issues:

All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.