Logo Spiria

Utilisation du service SES d’Amazon

15 septembre 2020.

Dans le cadre d’un projet interne, j’ai été chargé d’explorer les services infonuagiques d’Amazon. Dans cet article, je vais partager ce que j’ai appris sur les fonctionnalités du service de courrier électronique simple d’Amazon (SES) : envoi, rebond, messages d’absence, plaintes, liste noire et analyse antivirus. Parmi les nombreux services Amazon, le SES est à la fois simple et complexe.

L’une des complexités des services de “cloud computing” d’Amazon est leur modularité : chaque service AWS ne fait qu’une seule chose et il faut donc assembler un pipeline de services pour obtenir des fonctionnalités plus évoluées. Bien qu’il soit possible d’utiliser SES seul, ce serait difficile de le faire, car tous les courriels de feed-back d’information seraient envoyés à l’adresse électronique qui a envoyé les courriels. Afin de contrôler ces notifications, nous devons utiliser plusieurs autres services AWS : le service de notification simple (Simple Notification Service, SNS) et le service de file d’attente simple (Simple Queue Service, SQS). Le SNS est utilisé pour recevoir les retours du SES et le SQS pour recevoir les notifications du SNS.

C’est pourquoi nous nous intéresserons aux outils suivants sur AWS, le cloud d’Amazon :

  • Service de courrier électronique simple (SES)
  • Service de notification simple (SNS)
  • Service de file d'attente simple (SQS)
  • boto3, le SDK AWS pour Python

Les 5 étapes

Voici un aperçu de la manière de configurer SES pour une application, dans ce cas-ci écrite en Python.

  1. Créez un compte AWS.
  2. Créez le sujet SNS pour recevoir des notifications.
  3. Enregistrez les expéditeurs de courrier électronique dans SES.
  4. Créez la file d'attente SQS pour recevoir des commentaires par courriels.
  5. Écrivez le code Python en utilisant le SDK AWS pour envoyer des courriels et recevoir des notifications.

Les étapes détaillées

Créez un compte AWS

Pour cette étape, rendez-vous sur le site Amazon AWS et enregistrez un compte. Si votre équipe possède déjà un compte, le gestionnaire du compte devra peut-être créer une invitation pour vous. Pour vous créer un compte pour vos tests personnels, allez à aws.amazon.com et cliquez sur le bouton orange “Create an AWS Account” en haut à droite.

Une fois que vous aurez un compte, vous pourrez vous connecter à la console AWS. Par exemple, à partir de la page SES : aws.amazon.com/ses, cliquez sur le bouton orange “Get started with Amazon SES”.

Créer un sujet SNS

Dans la console AWS, sélectionnez le service SNS dans le menu déroulant “Services” en haut (il se trouve dans la section “Application Integration”). Sur la page du service SNS, sélectionnez l'onglet “Topics” à gauche et sélectionnez le bouton orange “Create a topic” en haut à droite. Créez le sujet avec un nom clair. Par exemple : “My-Project-Send-Email-Feedback”.

S’inscrire avec SES

Dans la console AWS, sélectionnez le service SES dans le menu déroulant “Services” en haut (il se trouve dans la section “Consumer Engagement”). Sur la page SES, sélectionnez la section “Manage Identities” au milieu de la page. Sur cette page, sélectionnez l’onglet “Email Addresses” à gauche. Ensuite, sélectionnez le bouton bleu “Verify a New Email Address” en haut de la page. L’adresse électronique que vous ajoutez ici recevra un courriel pour confirmer sa validité.

Pour enregistrer un domaine au lieu d’un e-mail, vous devez sélectionner l’onglet “Domains” à gauche et cliquer sur le bouton bleu “Verify a new Domain” en haut. Amazon générera des enregistrements DNS TXT qui devront être ajoutés aux enregistrements DNS du domaine afin qu’Amazon puisse valider que nous sommes propriétaires du domaine.

Une fois que l’e-mail (ou le domaine) est vérifié (il aura le statut “Verified” dans la liste), nous devons le relier au sujet SNS. Cliquez sur l’e-mail dans la liste, puis développez le panneau “Notifications” au milieu de la page. Cliquez sur le bouton “Edit Configuration” et configurez toutes les notifications pour qu’elles utilisent le sujet SNS. Le sujet se trouve dans la section “SNS Topic Configuration” au milieu de la page. Ensuite, changez le “Email Feedback Forwarding” en “Disabled”, en bas (c’est très important ! Sinon, les rebonds, les plaintes, etc. les feed-back seront toujours envoyés dans l’e-mail au lieu du sujet).

À ce stade, le service SES est dans un bac à sable et seule l’adresse de courrier électronique enregistrée peut envoyer ou recevoir des courriers électroniques. Il faut envoyer une demande à Amazon via la console pour sortir du bac à sable. Pour l’instant, nous utilisons toujours SES uniquement dans son bac à sable. Amazon fournit quelques adresses e-mail pour permettre de tester quelques scénarios :

  • Pour une livraison réussie : success@simulator.amazonses.com
  • Pour obtenir une notification de rebond : bounce@simulator.amazonses.com
  • Pour obtenir une notification d'absence du bureau : ooto@simulator.amazonses.com
  • Pour obtenir une notification de plainte du destinataire : complaint@simulator.amazonses.com
  • Pour obtenir une notification de liste noire : suppressionlist@simulator.amazonses.com
  • Pour obtenir un refus d'envoi de virus, joindre un fichier avec le contenu : X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

File d’attente SQS

Dans la console AWS, sélectionnez le service SQS dans le menu déroulant “Services” en haut (il se trouve dans la section “Application Integration”). Sur cette page, cliquez sur le bouton bleu “Create New Queue”. Créez une file d’attente avec un nom clair. Par exemple : “My-Project-Send-Email-Queue”.

La file d’attente doit être liée au thème du SNS. Pour ce faire, sélectionnez la file d’attente en cliquant sur la case à cocher située à côté de son nom dans la liste. Une fois sélectionnée, cliquez sur le bouton “Queue Actions” en haut et sélectionnez “Subscribe Queue to SNS Topic”. Sélectionnez le sujet que vous avez créé précédemment.

Attention : il y a un énorme “piège” dans la liaison SNS/SQS. Vous pouvez relier le sujet SNS à la file d’attente SQS à partir de la page SNS. En procédant de cette façon, les notifications SNS ne sont pas envoyées à la file d’attente ! Cela semble être un bogue dans AWS. Le faire à partir de la page SQS fonctionne, c’est donc ce qui a été documenté ici. C’est un problème, car certains guides rapides AWS documentaient la manière qui échoue, ce qui était un grand gaspillage de temps.

À ce stade, votre pipeline AWS SES est prêt. Vous pouvez envoyer des courriels par SES et vous recevrez des informations sur les courriels envoyés, les rebonds, etc. par le biais de la file d’attente SQS.

Code Python

Cette section décrit comment accéder à SES avec Python.

SDK AWS

Pour interagir avec SES avec du code Python, on utilise le SDK AWS. En Python, c’est le paquet boto3. On installe le paquet par les moyens habituels : pip ou pipenv, etc. Par exemple :

pipenv install boto3

Client Python AWS

Pour accéder aux services AWS, il faut disposer des éléments suivants :

  • Autorisations d’accès à l’AWS.
  • Une session avec AWS.
  • Un client spécifique au service AWS.

Les informations d’identification sont conservées dans un fichier privé dans le dossier personnel de votre système d’exploitation. Le chemin d’accès à ce fichier doit ressembler à quelque chose comme $HOME/.aws/credentials. Vous pouvez donner à votre identité un nom qui peut être utilisé dans le code. Par exemple, votre fichier d’identification pourrait ressembler à ceci :

[profile-name-here]
aws_access_key_id = <AWS access key here>
aws_secret_access_key = <AWS secret access key here>
region=us-west-2

Une fois que le nom du profil d'identification AWS est connu, il peut être utilisé pour créer une session en Python et à partir de cette session, un client peut être créé pour accéder à un service. La forme la plus simple de code Python est la suivante.

import boto3
session = boto3.Session(profile_name=‘profile-name-here’)
email_client = session.client(‘ses’)
queue_client = session.client(‘sqs’)

Envoyer un courriel

L’envoi d’un courriel est facile une fois que vous avez le client SES. Pour cela, il suffit de remplir quelques dict avec les informations requises et d’appeler send_email(). Par exemple, en supposant que vous avez déjà créé le client comme indiqué ci-dessus.

sender = ‘someone@somewhere.com’
recipient = ‘friend@house.com’
subject = ‘hi there!’
body_text = ‘bla bla’
body_html = ‘<H1>bla bla</H1>‘
charset = ‘UTF-8’
dest = { ‘ToAddresses’: [ recipient ] }
msg = {
    ‘Body’: {
        ‘Html’: { ‘Charset’: charset, ‘Data’: body_html },
        ‘Text’: { ‘Charset’: charset, ‘Data’: body_text },
    },
    ‘Subject’: { ‘Charset’: charset, ‘Data’: subject },
}

response = email_client.send_email(Destination = dest, Message = msg, Source = sender)
message_id = response[‘MessageId’]

Note : cet exemple ne montre pas le traitement des erreurs.

Recevoir le feed-back des courriels

L’envoi de courrier électronique est fondamentalement asynchrone. Le code ci-dessus renvoie des erreurs pour des éléments qui peuvent être vérifiés immédiatement, comme la validité du format de l’adresse électronique, mais d’autres erreurs, comme les rebonds, ne seront connues que plus tard. Même une livraison réussie n’est pas immédiatement connue. C’est pourquoi le pipeline SQS a été mis en place. Le code doit savoir quelle file d’attente SQS utiliser : celle qui a été créée lors de la configuration du pipeline ci-dessus. Pour recevoir le feed-back du SQS, il faut interroger la file d’attente du SQS :

url_response = queue_client.get_queue_url(QueueName=‘your-SQS-queue-name’)
queue_url = url_response[‘QueueUrl’]
response = queue_client.receive_message(
    QueueUrl=queue_url,
    AttributeNames=[],
    MaxNumberOfMessages=1,
    MessageAttributeNames=[‘All’],
    VisibilityTimeout=0,
    WaitTimeSeconds=0)

if response and ‘Messages’ in response:
    message = response[‘Messages’][0]
    receipt_handle = message[‘ReceiptHandle’]

Notez que le message reçu ici n’est pas le message électronique. Le SDK AWS utilise beaucoup le mot “Message”… et en fait, ce message a un triple niveau de JSON-dans-JSON pour accéder à la véritable information sur le message électronique ! Voici le code pour décoder tous ces JSON à plusieurs niveaux :

# The following code decodes sub-JSON embedded within text string within JSON…
# Note all the ‘Message’ entries within ‘Message’entries... confusing!
message = response[‘Messages’][0]
if message is not None:
    if ‘Body’ in message:
        body = json.loads(message[‘Body’])
        if ‘Message’ in body:
            msg = json.loads(body[‘Message’])
            body[‘Message’] = msg
        message[‘Body’] = body

Le feed-back JSON contient beaucoup d’informations. Je ne présenterai ici que les parties les plus pertinentes pour le retour d’information par e-mail : le type de message et l’adresse e-mail. Voici un extrait du JSON avec uniquement les parties pertinentes. Dans ce cas, nous recevons une notification de rebond :

{
    "Body": {
        "Type": "Notification",
        "Message": {
            "notificationType": "Bounce",
            "mail": {
                "source": "your-source-email-address@your-domain.com",
                "destination": [
                    "bounce@simulator.amazonses.com"
                ]
            }
        }
    }
}

Pièges

Il y a quelques points à surveiller lorsque vous utilisez le SDK pour envoyer des courriels. En voici quelques-unes que nous avons enregistrées jusqu’à présent :

  • Comme expliqué dans les sections SQS/SNS, il faut s’abonner au sujet SNS via la page SQS et non l’inverse.
  • Les noms de domaine de l’expéditeur et du destinataire doivent être encodés en utilisant la norme Punycode s’ils sont en Unicode.
  • L’adresse électronique de l’expéditeur et du destinataire doit être en ASCII 7 bits.
  • Le nom d’ami de l’expéditeur doit être encodé selon la norme MIME (RFC2047) s’il contient de l’Unicode. Par exemple : =?charset?encodage?texte-codé?=