Email merging and attachments with Python

Yesterday I had to send out a bunch of personalized emails. The messages were mostly the same, but each message had some unique information (aside from the To address). I’m sure there are several email merge programs available, and probably even some online tools for doing this, but since I’ve already written a couple of Python scripts that send mail, I figured it would be at least as fast to rejigger one of those as it would be to find and learn a new app.

The one thing that worried me was the need for an attachment to be included with each email. My earlier scripts were for text messages only, and I didn’t know how to do the base64 encoding of the (PDF) attachment. Python has a base64 library, and I’m sure I would have learned a lot by digging into it, but I didn’t want to learn base64—I just wanted to get the damned emails out the door.

So I cheated. I sent myself a test email with the PDF attached. Then I opened it in Mail and invoked the View▸Message▸Raw Source command (⌥⌘U).

I copied the block of gibberish that represents the encoded file, all 192 kilobytes of it, and pasted it straight into the appropriate spot in my Python source code, making this by far the longest script I’ve ever written. Not as elegant as opening the PDF, reading it in, and encoding it—but a hell of a lot faster.

The rest of the script was pretty prosaic: loop through the lines of STDIN to get the recipient-specific text, stick it into the appropriate places of the template with the % operator, and call sendmail via the Popen function of the subprocess library. It was the cheat that made the script fun.