Home » Python Corner » SES Mail mit Python, boto3 und Anhängen versenden

SES Mail mit Python, boto3 und Anhängen versenden

Mit der library boto3 lassen sich recht einfach die Amazon Web Services nutzen, für den Simple Email Service SES ist dabei allerdings (mittlerweile) nur noch eine Low-Level API integriert. Da ich selbst ein paar Probleme hatte, diese API zu nutzen, um raw Mails (v.a. für Anhänge) zu versenden, findet Ihr hier ein vollständiges Beispiel-Script mit dem es funktioniert. Die benutzte Python-Version war dabei 3.5.2 (via Anaconda). Um das Snippet zu nutzen, muss das Paket boto3 installiert sein (pip install boto3) und die Parameter am Anfang des Scripts müssen die richtigen Werte enthalten. Für den produktiven Einsatz fehlt dann nur noch ein wenig Fehlerbehandlung.

# -*- coding: utf-8 -*-
# pip install boto3
import boto3
#the email package was already included, so no need to install
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

# replace the following with your values
sender                  = "<the senders mail here>" # this has to be a verified mail in SES
recipients              = ["recipient@one.com", "recipient@two.com"] # replace with valid mails
mail_subject            = "This is the mail subject line"
mail_body               = "This is the body text of the mail to send"
attachments             = {"file_1.pdf": "/path/file/one.pdf"}
aws_access_key_id       = "AWS_ACCESSKEY_ID_HERE"
aws_secret_access_key   = "AWS_SECRET_KEY_HERE"
aws_region              = "eu-west-1" # pick the right one

def send_mail(sender:str, recipients:list, title:str, body:str, attachments:dict, client: object)->list:
    '''
    This sends a new Mail to every recipient in the recipients lists. It sends one mail per recipient
    It returns a  list of responses (one per mail)
    attachments look like this {"filename1": "/path/to/file1", "filename2": "/path/to/file2" ... }
    '''
    # create raw email
    msg = MIMEMultipart()
    msg['Subject'] = title
    msg['From'] = sender

    part = MIMEText(body)
    msg.attach(part)

    for attachment in attachments:
        part = MIMEApplication(open(attachments[attachment], 'rb').read())
        part.add_header('Content-Disposition', 'attachment', filename=attachment)
        msg.attach(part)

    # end create raw email
    responses = []
    for recipient in recipients:
        # important: msg['To'] has to be a string. If you want more than one recipient,
        # you need to do sth. like ", ".join(recipients)
        msg['To'] = recipient
        response = client.send_raw_email(
            Source=sender,
            Destinations=[recipient],  # here it has to be a list, even if it is only one recipient
            RawMessage={
                'Data': msg.as_string() # this generates all the headers and stuff for a raw mail message
            })
        responses.append(response)
    return responses

ses_client = boto3.client('ses',
                          aws_access_key_id=aws_access_key_id,
                          aws_secret_access_key=aws_secret_access_key,
                          region_name=aws_region)


if __name__ == '__main__':
    responses = send_mail(
        sender,
        recipients,
        mail_subject,
        mail_body,
        attachments,
        ses_client)

    print(responses)
    '''
    example output:
    [
     {
        'ResponseMetadata': {
            'RetryAttempts': 0, 
            'RequestId': '187214fa-49e8-11e8-92ed-c564d0fa0526', 
            'HTTPStatusCode': 200, 
            'HTTPHeaders': {
                'content-type': 'text/xml', 
                'date': 'Tue, 1 Apr 2018 06:56:22 GMT', 
                'content-length': '222', 
                'x-amzn-requestid': '187214fa-49e8-11e8-91ee-c564d0fa0562'
            }
        }, 
        'MessageId': '0102016305e3745f-3e81a118-b622-42e3-bdac-b51c8c015abd-000000'
     }
    ]
    '''

Für den produktiven Einsatz fehlt noch eine vernünftige Fehlerbehandlung, ansonsten ist das Snippet voll funktionsfähig

Post Tag With : , , , , ,

One Response so far.

  1. Joao Coelho says:

    Tx for the code snippet.
    Just adding that if you want to send a html email, in line 30 set

    part = MIMEText(self.text, ‘html’)

    The second parameter is the content subtype and defaults to ‘plain’.

Leave a Reply