As the title suggests, I was looking for a way to send HTML mails in python using Amazon SES but did not find anything (or maybe my search skills are bad). So, once I found the solution, I thought I might share it with everyone.

The basic idea is that contents of the mail (raw-message) must be a JSON dictionary with “Data” as main key whose value is a key value pair containing entries with keys like “From”, “To” etc. Sample code can be seen below.

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

import commands
import json
import logging
import sys
import tempfile

def sendEmail(mail_sender, mail_subject, mail_content, mail_receivers_list):
  """
  Args:
  mail_sender: str, sender's email address.
  mail_subject: str, subject of the email.
  mail_content: str, content (html data) of the email.
  mail_receivers_list: str, comma separated list of receivers.
  """
  # This style is specific to AWS SES.
  message_dict = { 'Data':
  'From: ' + mail_sender + '\n'
  'To: ' + mail_receivers_list + '\n'
  'Subject: ' + mail_subject + '\n'
  'MIME-Version: 1.0\n'
  'Content-Type: text/html;\n\n' +
  mail_content}
  try:
    _, message_dict_filename = tempfile.mkstemp()
    f = open(message_dict_filename,'w')
    f.write(json.dumps(message_dict))
  except IOError as e:
    logging.error(str(e))
    sys.exit(1)
  finally:
    f.close()
  aws_send_email_cmd = [
      'aws', 'ses', 'send-raw-email', '--region=us-east-1',
      '--raw-message=file://%s' % message_dict_filename]
  result = commands.getstatusoutput(' '.join(aws_send_email_cmd))
  logging.info('Sending message with subject "%s", result:%s.', mail_subject,
      result)
  if result[0] != 0:
    logging.error('Mail sending failed. Command: %s',
        ' '.join(aws_send_email_cmd))
  # It is usually a good idea to delete the file "f" at this stage.

def main():
  sendEmail('sender@gmail.com', 'mail subject', 'content of the mail',
      'foo@gmail.com, blah@gmail.com')

if __name__ == '__main__':
  main()