I recently released new distribution on CPAN called Courriel. The word “courriel” is the official French word for email. I chose it because the Mail and Email namespaces are already very crowded, and there’s really no good namespaces left there.

This gets to the why. Courriel is a distribution for processing and creating modern email. What’s modern? In ye olde dayes of RFC822 email, an email was a bunch of headers followed by a message for the recipient. Ye olde days are long gone. In these modern times, multipart emails are extremely common, and they’re a lot more complicated than the emails of olde.

It’s quite common nowadays to receive email consisting of nested multipart messages. The top level part will be multipart/mixed, which in turn contains a multipart/alternative part as well as a bunch of attachments (spreadsheet, image, etc.). That multipart/alternative part will typically contain both text/plain and text/html parts. These are two versions of the “body” of the message, the part that’s intended to be read by the recipient in their mail client.

Here’s a diagram:

multipart/mixed
  |
  |-- multipart/alternative
  |     |
  |     |-- text/plain (disposition = inline)
  |     |-- text/html  (disposition = inline)
  |
  |-- application/vnd.ms-excel (disposition = attachment)
  |-- image/png                (disposition = attachment)

It can actually be even more complicated. If the HTML body has references to images or CSS, you might get something more like this:

multipart/mixed
  |
  |-- multipart/alternative
  |     |
  |     |-- text/plain (disposition = inline)
  |     |-- multipart/related
  |           |
  |           |-- text/html  (disposition = inline)
  |           |-- image/jpeg (disposition = attachment, Content-ID = image1)
  |           |-- image/jpeg (disposition = attachment, Content-ID = image2)
  |
  |-- application/vnd.ms-excel (disposition = attachment)
  |-- image/png                (disposition = attachment)

That’s quite a structure!

If you just wanted to generate these sorts of emails, the existing options were acceptable(ish). Between Email::Stuff and Email::MIME::CreateHTML, you could get by. But if you wanted to process this email as part of an application, you were really stuck.

The Perl Email Project was started way back in 2004 with the release of Email::Simple by Simon Cozens. I was excited when this happened, as I was really hoping for something like the Perl DateTime Project, a powerful ecosystem of modules backed by a usable, feature-rich core implementation.

Unfortunately, Email::Simple and its companion module Email::MIME never really did what I wanted. While simple is good, the project never really advanced beyond simple to provide a featureful, user-friendly API.

The fundamental problems with these modules are several fold.

First, the internals of the modules are way too chummy. Rather than building clear APIs between components, the modules simply step all over each other’s guts.

Second, the internals of the modules are all about strings. When you add a part to a MIME message, internally that part will be immediately serialized as a string and tacked onto the existing body as a string. This problem manifests in many other ways (when dealing with headers, content types, content disposition, and elsewhere). This makes building higher level APIs much more complicated than it should be.

Finally, the fact that Email::MIME treats all parts as equal is really problematic. While in theory an email is simply a nested set of identical things (MIME parts), in practice some parts are more important than others. The headers attached to the top level part are different (in content) from headers attached to “internal” parts, as that’s where you’ll find things like the From header, Subject, and so on. Other parts have their own important roles, like providing a message body or being an attachment. The Email project doesn’t provide any convenient APIs for getting this type of data.

Courriel aims to address these problems. It’s built with Moose, which makes it easier to build clean APIs across multiple modules. The internals aren’t perfect though, as I still ended up calling private methods on another class’s object in a couple spots. Patches are definitely welcome!

Internally, Courriel is all about objects. It’s happy to accept strings through various parsing methods, but internally parts are objects, and it won’t rebuild the stringified representation as state changes. Instead, it only builds the fully stringified form when you ask for it.

As an aside, Courriel is a lot less mutable than Email::MIME. While you can mutate the headers of a part, you can’t really change anything else about it. If you wanted to add or remove parts, you must make a new object with the old one’s parts, plus or minus something.

Courriel provides a low-level API where all parts are equal and a high-level API on top of it that helps you get stuff done. You can write code like this:

my $courriel = Courriel->parse( text => $raw_email );

print $courriel->subject(), "\n\n", $courriel->plain_body()->content();

Doing this same sort of thing with Email::MIME requires a lot more code.

Finally, it provides a simplified email creation module called Courriel::Builder.

I’ve already found Courriel useful in simplifying and improving my own code, and I hope others find it useful. I’m sure it has lots of bugs, misfeatures, and missing features, of course. The repository is on my git server and you can clone it anonymously from git://git.urth.org/Courriel.git.

I recently started using flymake-mode in emacs, which does a “make on the fly” for the buffer you’re currently editing. For Perl, that basically means checking the code by running perl -c on it. If it sees any errors or warnings, it highlights this in the buffer. This is pretty handy for catching typos, although I’ve seen some weird false positive. Anyway, it’s a great tool, except that it does its checking by creating a file in the same directory as the one you’re editing. So if you’re editing MyApp/lib/MyApp.pm, flymake will create (and delete) a MyApp/lib/MyApp_flymake.pm. Catalyst’s Restarter watches the lib directory for file changes, and restarted the dev server on each change. Combined with flymake, this means a lot of useless restarting. Fortunately, it’s easy enough to get flymake to create its files elsewhere. Here’s a snippet that includes some code off the FlymakeRuby page on the Emacs Wiki:

(defun flymake-perl-init ()
  (let* ((temp-file (flymake-init-create-temp-buffer-copy
                     'flymake-create-temp-intemp))
         (local-file (file-relative-name
                      temp-file
                      (file-name-directory buffer-file-name))))
    (list "/home/autarch/perl5/perlbrew/perls/current/bin/perl"
          (list "-MProject::Libs" "-wc" local-file)))
)

You can change the perl path to just be

perl or /usr/bin/perl. Obviously, I’m using perlbrew. I got most of this bit from Damien Krotkine’s post on perlbrew and flymake, but I replaced the use of “flymake-create-temp-inplace” with “flymake-create-temp-intemp”, defined below.

(defun flymake-create-temp-intemp (file-name prefix)
  "Return file name in temporary directory for checking
   FILE-NAME. This is a replacement for
   `flymake-create-temp-inplace'. The difference is that it gives
   a file name in `temporary-file-directory' instead of the same
   directory as FILE-NAME.

   For the use of PREFIX see that function.

   Note that not making the temporary file in another directory
   \(like here) will not if the file you are checking depends on
   relative paths to other files \(for the type of checks flymake
   makes)."
  (unless (stringp file-name)
    (error "Invalid file-name"))
  (or prefix
      (setq prefix "flymake"))
  (let* ((name (concat
                (file-name-nondirectory
                 (file-name-sans-extension file-name))
                "_" prefix))
         (ext  (concat "." (file-name-extension file-name)))
         (temp-name (make-temp-file name nil ext))
         )
    (flymake-log 3 "create-temp-intemp: file=%s temp=%s" file-name temp-name)
    temp-name))

This is the bit from the Emacs Wiki (thanks, whoever wrote this!). It tells flymake to make its files in a temp directory.

(setq temporary-file-directory "~/.emacs.d/tmp/")

You can set this to whatever you want. And poof, flymake is no longer making the Catalyst Restarter work so hard.