Beautiful Code [165]
The new IPC::Run-based Crypt::GPG was uploaded to CPAN at the end of 2005. It now worked on a larger range of operating systems, and was more reliable and secure than its Expect-based predecessor.
Secure Communication: The Technology Of Freedom > The Invisible Hand Moves
11.9. The Invisible Hand Moves
By mid-2004, Neomailbox was a year old and had attracted quite a few paying customers. Cryptonite development was put on hold for a bit while I worked on developing various aspects of the Neomailbox service as well as on a few other projects I just couldn't wait to get started on.
But being out in the market was great, as it brought market forces, from competition to user feedback, to bear on the development process, and helped sharpen and clarify priorities. Customer requests and queries helped keep me intimately connected to what the users and the market wanted. Meeting the market's demands is how application code becomes beautiful in a commercial sense, after all, so interaction with the market became an integral and critical component of the development process.
Cryptonite was designed to be easy to maintain and modify, precisely because I knew that at some point it would have to start to evolve in new ways, both in response to and in anticipation of what the customer wanted. Being in the market enabled me to see that emerging demand: it was clear that IMAP was the future of remote mailbox access.
IMAP has a lot of attractive features that make it a very powerful and practical mail access protocol. One of the most important of these is the ability to access the same mailbox using multiple clients, which becomes increasingly important with the proliferation of computing devices. The typical user now has a desktop, a laptop, a PDA, and a cellphone, all capable of accessing her mailbox.
This posed a slight problem, as I'd already implemented a full mail store for Cryptonite, and it was not IMAP-based. There were two ways forward: either implement a full IMAP server based on the Cryptonite mail store (a big job), or modify Cryptonite to enable it to use an IMAP mail store as a backend. In fact, the second would have to be done either way.
Again, opting to reduce complexity of the system, and focusing on its primary purpose, I decided not to develop the Cryptonite mail store into a full-blown IMAP server. Instead, I modified it into a caching mechanism, which caches MIME skeletons (just the structure information, without the content) of multipart MIME messages listed by the user, and also entire messages read by the user, so that the next time a user opens a message she's read before, Cryptonite doesn't need to go back to the IMAP server to fetch it again.
This gave me the best of both worlds. Cryptonite could reflect the contents of an IMAP mailbox, while simultaneously posessing full information of each message's exact MIME structure, as well as being able to keep decrypted messages available in the shadow folders the Cryptonite mail store supported.
The modifications to the code were straightforward. Whenever the user clicks to read a message that isn't in the cache, Cryptonite caches it in the corresponding Mail::Folder:: Shadow folder:
my $folder = $session->folder; # The folder name
my $mbox = _opencache($username, $folder); # The M::F::Shadow cache
unless ($msgnum and grep { $_ == $msgnum } $mbox->message_list) {
# Message is not in cache. Fetch from IMAP server and cache it.
my $imap = $self->_open_imapconn($username, $user->password)
or sleep(int(rand(3))+2), return $self->cluebat (EBADLOGIN);
$imap->select($folder) or return $self->cluebat (ENOFOLDER, $folder);
$imap->Uid(1);
my ($tmpfh, $tmpnam) =
tempfile( $self->tmpfiles, DIR => "$HOME/tmp",
SUFFIX => $self->tmpsuffix, UNLINK => 1);
$imap->message_to_file($tmpfh, $msgnum);
$imap->logout;
my $parser = new MIME::Parser; $parser->output_dir("$HOME/tmp/");
$parser->filer->ignore_filename(1); # Do NOT use suggested filename
seek