Commission Music

Commission Music
Bespoke Noise!!

Thursday, 24 April 2014

Personalised Jpegs for emailed wedding invitations

Let's say you want to invite a bunch of people to your wedding and your soon-to-be-spouse wants some nice graphic you can mail to folks that has their name in it. You can do this! This script works with Linux and should work with OS X. It will require a few changes to work with windows.

Install some nifty software

I'm using both imagemagick and OptiPNG, both of which I got through apt-get. Probably, the png step is overkill and you could go straight to jpeg.

I'm also using Inkscape, Python and LibreOffice, but you can use any spreadsheet you want.

Make the graphic template

  1. Find some nice border of some kind. I drew one and scanned it, but there are other options.
  2. Open your nice border in inkscape (or other svg editor).
  3. Put all the text you want into your graphic, with the font you want.
  4. In the part where you want their name, put GUEST_NAME
  5. Save your lovely creation as template.svg

Compile names and email addresses

In LibreOffice, open a new spreadsheet and make a bunch of entries for your guests.

The first column should be email addresses.

If you are NOT saving the images, then the next column can all say 'invite' for every single entry. If you want to save the jpegs (say to post them to facebook walls as well as emailing them), then give them a short name associated with the person. This will be a file name, so it should be all one word that starts with a letter and contains only letters, numbers and underscores.

The last column should be the name you want to appear in the invite. You know from making your template how much space you have for names, so keep that in mind, if you're deciding to put in Reverend Doctor Julius Milliband Cameron III's full name or not. Or you may need to go back and tweak your template.

Your speadsheet should look something like this:

foo@example.comjenJennifer
bar@example.comralphRalph & Morris
dr_rev@example.comjuDr Cameron

Save this spreadsheet as guests.csv

The script

Get ready

Save your template, your spreadsheet and the script (cut and past from below), all to the same folder on your system. Call the script doemail.py

You will need to modify this script a bit.

Put in your own text where you see the part that says YOUR OWN TEXT. You'll see it asks for your own text twice. One of those times is plain text. The other one is HTML. the plain text one is just text. Don't include any html tags. If you put in links, you just have to put in the link as plain text. In the HTML part, you can use a lot of markup, including <a href="blah.com">blahblah</a> tags and whatnot. You can do inline CSS, if you like, but it's email, so keep it relatively simple. In both sections, don't forget to include a link to your website. And if you are using an online form for RSVPs, link to that as well.

You'll also need to put in your own email address, and your own password. If you are using gmail, you can use an application-specific password.

Finally, you will also need to put in the smpt server for your mail server. Near the top of the file, you'll see lines for hotmail and gmail. Delete any that don't apply to you. If you are using a different server, you'll have to find out what to put there.

If you want to save the nice jpegs, say to also post them in facebook messages, then look for the line:

jpegname = "/tmp/"+name+".jpeg"
and change the '/tmp/' part to another directory on your system.

You need to make the script executable. Open the terminal application and cd to the directory with the script, template, and spreadsheet. Type:

 chmod +x doemail.py
This will make the script executable as a program you can run. then, double check your spreadsheet is ok. Type:
less guests.csv
It should look like:
foo@example.com,jen,Jennifer
bar@example.com,ralph,Ralph & Morris
dr_rev@example.com,ju,Dr Cameron
If you see semicolons instead of commas, then you need to change your script to tell it that. Change
guestreader = csv.reader(csvfile)
to
guestreader = csv.reader(csvfile, delimiter=';')

To run the script, still from your terminal, type:

 ./doemail.py

The Actual script to cut and paste

#! /usr/bin/python

import smtplib
import re
import subprocess
import os
import cgi
import uuid
import csv

from subprocess import call
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text      import MIMEText
from email.mime.image     import MIMEImage
from email.header         import Header    



# me == my email address
me = "example@hotmail.co.uk"
password = "yourEmailPassword"
smpt_server = "smtp.live.com:587" #hotmail
smpt_server = "smtp.gmail.com:587" #gmail

with open('guests.csv') as csvfile:
    guestreader = csv.reader(csvfile)
    for row in guestreader:
        you = row[0]
        name = row[1]
        salutation = row[2]

        name = ''.join(name.split())



        text = "Dear " + salutation + ",\n\n  YOUR TEXT GOES HERE http://YOURWEBSITE.COM"


        html = """\
<html>
  <head></head>
  <body>
    <p>
<a href="YOUR WEDDING WEBSITE">
        """
        html = html + "<img src=\"cid:{}@example.com\" alt=\"[More Information]\" /></a></p>\n<p>Dear {},</p>".format(img['cid'], salutation)
        html = html + """\
<p>YOUR TEXT GOES HERE</p>
</body></html>
    </p>
  </body>
</html>
        """


        print (salutation)

        # Create message container - the correct MIME type is multipart/alternative.
        msg = MIMEMultipart('related')
        text_msg = MIMEMultipart('alternative')
        msg['Subject'] = Header(u'Wedding Invitation', 'utf-8')
        msg['From'] = me
        msg['To'] = you



        # make the image

        filename = "/tmp/"+name+".svg"
        pngname = "/tmp/"+name+".png"
        jpegname = "/tmp/"+name+".jpeg"

        svg = open("template.svg");
        svgn = open(filename, 'w');
        lines = svg.read().split('\n')
        for line in lines:
            line = re.sub('GUEST_NAME',re.sub('&', '&amp;', salutation), line)
            svgn.write(line)
        #endfor

        svg.close()
        svgn.close()

        os.system("inkscape -f " + filename + " -e " + pngname)
        os.system("optipng " + pngname);
        os.system("convert -compress JPEG -quality 87 " + pngname + " " + jpegname);

        os.system("rm " + filename)

    
        # attach the image to the email

        img = dict(title=u'Invitation', path=jpegname, cid=str(uuid.uuid4()))
                                                        #cid=name)
                                                        #cid=str(uuid.uuid4()))
        with open(img['path'], 'rb') as file:
            msg_img = MIMEImage(file.read(), name=os.path.basename(img['path']))
            #msg.attach(msg_img)
            msg_img.add_header('Content-ID', '<{}@example.com>'.format(img['cid']))
            msg_img.add_header('Content-Name', img['cid'])
            msg_img.add_header('X-Attachment-ID', '{}@example.com'.format(img['cid']))
            #msg_img.add_header('Content-Disposition', 'attachment', filename=os.path.basename(img['path']))
            msg_img.add_header('Content-Disposition', 'inline', filename=os.path.basename(img['path']))

        print('<{}>'.format(img['cid']))



        # Create the body of the message (a plain-text and an HTML version).



        # Record the MIME types of both parts - text/plain and text/html.
        part1 = MIMEText(text, 'plain')
        part2 = MIMEText(html, 'html')

        # Attach parts into message container.
        # According to RFC 2046, the last part of a multipart message, in this case
        # the HTML message, is best and preferred.
        text_msg.attach(part1)
        text_msg.attach(part2)
        msg.attach(text_msg)
        msg.attach(msg_img)


        # Send the message via local SMTP server.
        server = smtplib.SMTP(smpt_server)
        server.ehlo()
        server.starttls()
        server.login(me,password)
        # sendmail function takes 3 arguments: sender's address, recipient's address
        # and message to send - here it is sent as one string.
        server.sendmail(me, you, msg.as_string())
        server.close()
        #server.quit()

        os.system("rm " + pngname)

    #end for (going through rows in the database)
    csvfile.close()
#end with    

No comments: