Comment utiliser une fonction Lambda pour stocker les notifications Amazon SES envoyées via Amazon SNS dans DynamoDB ?

Date de la dernière mise à jour : 22/02/2021

J'utilise le service Amazon Simple Notification Service (Amazon SNS) pour recevoir des notifications sur les e-mails envoyés via le service Amazon Simple Email Service (Amazon SES). Comment stocker ces notifications dans une table Amazon DynamoDB en utilisant une fonction AWS Lambda ?

Résolution

Remarque : L'exemple suivant de fonction Lambda peut être utilisé comme modèle pour écrire des données vers un CRM ou d'autres destinations, en fonction de l'endroit où vous hébergez votre liste de diffusion.

Si vous ne l'avez pas encore fait, configurez un compte Amazon SES (e-mail ou domaine) sur lequel une rubrique Amazon SNS est configurée pour recevoir des notifications d'Amazon SES. Pour plus d'informations, consultez Réception des notifications Amazon SES en utilisant Amazon SNS.

Puis, procédez comme suit :

Créez une table DynamoDB

1.    Créez une table dans DynamoDB avec les attributs suivants :
Pour le Nom de table, entrez SESNotifications.
Pour la Clé de partition primaire, entrez SESMessageId.
Pour la Clé de tri primaire, entrez SnsPublishTime.

2.    Configurez les index secondaires comme décrit dans le tableau ci-dessous. Cette configuration permettra à Lambda d'interroger la table et de créer un rapport Amazon SES.

Nom d'index Clé de partition Clé de tri
SESMessageType-Index SESMessageType (Chaîne) SnsPublishTime (Chaîne)
SESMessageComplaintType-Index SESComplaintFeedbackType (Chaîne) SnsPublishTime (Chaîne)

Remarque : Vous pouvez ajouter d'autres index secondaires si nécessaire.

Pour plus d'informations sur la création d'une table dans DynamoDB, consultez Démarrez avec Amazon DynamoDB.

Ajoutez des autorisations au rôle IAM de la fonction Lambda qui lui permettent d'appeler la table DynamoDB

Créez un nouveau rôle AWS Identity and Access Management (IAM) qui permet à votre fonction Lambda d'appeler l'API DynamoDB:PutItem en procédant comme suit :

Remarque : La création et l'utilisation d'un nouveau rôle IAM pour différentes fonctions Lambda font partie des bonnes pratiques. Évitez de réutiliser un même rôle dans plusieurs fonctions.

1.    Dans le panneau de navigation de gauche de la console IAM, choisissez Roles (Rôles).

2.    Sélectionnez Create role (Créer un rôle).

3.    Pour Select type of trusted entity (Sélectionner le type d'entité de confiance), sélectionnez Service AWS.

4.    Pour Choose a use case (Choisir un cas d'utilisation), choisissez Lambda, puis choisissez Next: Permissions (Suivant : Autorisations).

5.    Pour Attach permissions policies (Attacher des stratégies d'autorisations), cochez la case à côté de la stratégie gérée AWSLambdaBasicExecutionRole . Ensuite, choisissez Next: Tags (Suivant : Balises).

6.    (Facultatif) Ajoutez des balises IAM au rôle correspondant à votre cas d'utilisation. Pour plus d'informations, consultez Balisage des ressources IAM.

7.    Choisissez Next: Review (Suivant : Vérification).

8.    Pour Role name* (Nom du rôle*), entrez lambda_ses_execution.

9.    Sélectionnez Create role (Créer un rôle).

10.    Revenez à la vue IAM Roles (Rôles IAM) et choisissez le rôle que vous avez créé.

11.    Dans la vue Permissions (Autorisations), choisissez Add inline policy (Ajouter une stratégie en ligne).

12.    Dans l'onglet Visual editor (Éditeur visuel), sélectionnez Choose a service (Choisir un service).

13.    Choisissez DynamoDB. Ensuite, pour Actions, entrez PutItem dans le champ de recherche et cochez la case située à côté de PutItem dans la liste déroulante qui apparaît.

14.    Pour Resources (Ressources), choisissez Specific (Spécifique). Ensuite, choisissez Add ARN (Ajouter un ARN) et entrez l'ARN de la table DynamoDB que vous avez créée.

15.    Choisissez Examiner une stratégie.

16.    Pour Name (Nom), entrez un nom pour la stratégie. Ensuite, choisissez Create policy (Créer une stratégie).

Exemple de stratégie IAM en ligne qui accorde l'accès à une table DynamoDB

------------------------IAM Policy Begins---------------------------
{
    "Version": "2012-10-17",
    "Statement": [
         {
            "Sid": "Stmt1428510662000",
            "Effect": "Allow",
            "Action": [
                "DynamoDB:PutItem"
            ],
            "Resource": [
                "arn:aws:DynamoDB:us-east-1:12345678912:table/SESNotifications"
            ]
        }
    ]
}
------------------------IAM Policy Ends-----------------------------

Créez une fonction Lambda pour traiter les notifications Amazon SES et Amazon SNS

Créez une fonction Lambda en utilisant l'exemple de code suivant, puis nommez-la sesnotificationscode. Lors de la création de la fonction, assurez-vous que vous lui attribuez le rôle lambda_ses_execution que vous avez créé.

Exemple de code de fonction Lambda pour traiter les notifications Amazon SES et Amazon SNS

L'exemple suivant de code de fonction Lambda vérifie les trois types de notifications Amazon SNS. La fonction place également la notification Amazon SES associée dans une table DynamoDB. Pour plus d'informations sur les types de notifications, consultez Exemples de notifications Amazon SNS pour Amazon SES.

Important : Remplacez la valeur du paramètre TableName SESNotifications par le nom de votre table DynamoDB.

--------------------------Lambda Code Begins------------------------
console.log("Loading event");

var aws = require("aws-sdk");
var ddb = new aws.DynamoDB({ params: { TableName: "SESNotifications" } });

exports.handler = function (event, context, callback) {
  console.log("Received event:", JSON.stringify(event, null, 2));

  var SnsPublishTime = event.Records[0].Sns.Timestamp;
  var SnsTopicArn = event.Records[0].Sns.TopicArn;
  var SESMessage = event.Records[0].Sns.Message;

  SESMessage = JSON.parse(SESMessage);

  var SESMessageType = SESMessage.notificationType;
  var SESMessageId = SESMessage.mail.messageId;
  var SESDestinationAddress = SESMessage.mail.destination.toString();
  var LambdaReceiveTime = new Date().toString();

  if (SESMessageType == "Bounce") {
    var SESreportingMTA = SESMessage.bounce.reportingMTA;
    var SESbounceSummary = JSON.stringify(SESMessage.bounce.bouncedRecipients);
    var itemParams = {
      Item: {
        SESMessageId: { S: SESMessageId },
        SnsPublishTime: { S: SnsPublishTime },
        SESreportingMTA: { S: SESreportingMTA },
        SESDestinationAddress: { S: SESDestinationAddress },
        SESbounceSummary: { S: SESbounceSummary },
        SESMessageType: { S: SESMessageType },
      },
    };
    ddb.putItem(itemParams, function (err, data) {
      if (err) {
        callback(err)
      } else {
        console.log(data);
        callback(null,'')
      }
    });
  } else if (SESMessageType == "Delivery") {
    var SESsmtpResponse1 = SESMessage.delivery.smtpResponse;
    var SESreportingMTA1 = SESMessage.delivery.reportingMTA;
    var itemParamsdel = {
      Item: {
        SESMessageId: { S: SESMessageId },
        SnsPublishTime: { S: SnsPublishTime },
        SESsmtpResponse: { S: SESsmtpResponse1 },
        SESreportingMTA: { S: SESreportingMTA1 },
        SESDestinationAddress: { S: SESDestinationAddress },
        SESMessageType: { S: SESMessageType },
      },
    };
    ddb.putItem(itemParamsdel, function (err, data) {
      if (err) {
        callback(err)
      } else {
        console.log(data);
        callback(null,'')
      }
    });
  } else if (SESMessageType == "Complaint") {
    var SESComplaintFeedbackType = SESMessage.complaint.complaintFeedbackType;
    var SESFeedbackId = SESMessage.complaint.feedbackId;
    var itemParamscomp = {
      Item: {
        SESMessageId: { S: SESMessageId },
        SnsPublishTime: { S: SnsPublishTime },
        SESComplaintFeedbackType: { S: SESComplaintFeedbackType },
        SESFeedbackId: { S: SESFeedbackId },
        SESDestinationAddress: { S: SESDestinationAddress },
        SESMessageType: { S: SESMessageType },
      },
    };
    ddb.putItem(itemParamscomp, function (err, data) {
      if (err) {
        callback(err)
      } else {
        console.log(data);
        callback(null,'')
      }
    });
  }
};
------------------------Lambda Code Ends----------------------------

Souscrivez la fonction Lambda à une ou plusieurs rubriques Amazon SNS

Si vous ne l'avez pas encore fait, créez au moins une rubrique Amazon SNS et configurez un domaine de messagerie Amazon SES pour utiliser cette rubrique SNS pour les notifications de commentaires. Ensuite, procédez comme suit, en utilisant la console Amazon SNS ou la console Lambda.

Pour souscrire une fonction à une rubrique Amazon SNS à l'aide de la console Amazon SNS

1.    Dans le panneau de navigation gauche de la console Amazon SNS, choisissez Topics (Rubriques). Ensuite, identifiez la rubrique SNS utilisée dans Amazon SES pour les notifications de retour à l'expéditeur. Par exemple, identifiez une rubrique SNS nommée ses_notifications_repo.

2.    Choisissez l'ARN de la rubrique SNS pour ouvrir la page Topic Details (Détails de la rubrique).

3.    Choisissez Create Subscription (Créer un abonnement).

4.    Pour Protocol (Protocole), choisissez AWS Lambda.

5.    Pour Endpoint (Point de terminaison), entrez l'ARN de la fonction Lambda que vous avez créée. Ensuite, choisissez Create Subscription (Créer un abonnement).

Pour souscrire une fonction à une rubrique Amazon SNS à l'aide de la console Lambda

1.    Dans la console Lambda, choisissez la fonction Lambda que vous avez créée précédemment.

2.    Dans la page Configuration , dans le panneauDesigner (Concepteur), cliquez sur le bouton +Add trigger (+Ajouter un déclencheur).

3.    Dans la liste déroulante Trigger configuration (Configuration du déclencheur), choisissez SNS. Un panneau de configuration apparaît sous le concepteur.

4.    Dans la liste déroulante de SNS topic (rubrique SNS), choisissez la rubrique SNS à laquelle vous souhaitez souscrire la fonction. Cliquez ensuite sur le bouton Add (Ajouter).

Répétez ce processus pour ajouter les différents rubriques de notification auxquelles vous souhaitez souscrire cette fonction Lambda.

Testez la configuration en envoyant un message Amazon SES pour invoquer la fonction Lambda

Pour envoyer un message de test, utilisez l'une des adresses de simulateur de boîte aux lettres email (mailbox) disponibles pour éviter un impact négatif sur vos métriques de délivrabilité SES. Pour plus d'informations, consultez Utilisation du simulateur de boîte aux lettres email (mailbox).

Une fois le message envoyé, Amazon SES publie une notification dans la rubrique SNS. Amazon SNS délivre ensuite la notification à Lambda sous forme d'objet de notification d'événement SES JSON-escaped dans l'objet d'événement SNS.

Pour créer des exemples d'événements pour les tests locaux à l'aide de la console Lambda, consultez Exemples de données d'événement qu'Amazon SES publie sur Amazon SNS.

Pour des exemples de notification SES de retour à l'expéditeur, de réclamation et de livraison, consultez Exemples de données d'événements qu'Amazon SES publie sur Amazon SNS.

Téléchargez un rapport depuis DynamoDB pour afficher des notifications Amazon SES

Pour interroger, trier et télécharger le contenu de la table DynamoDB en tant que fichier CSV, procédez comme suit :

1.    Dans la console DynamoDB, choisissez la table SESNotifications.

2.    Choisissez l'onglet Items (Éléments).

3.    Créez une recherche par Requête ou par Analyse. Pour plus d'informations, consultez Bonnes pratiques pour l'interrogation et l'analyse de données.

Remarque : Vous pouvez utiliser l'exportation de table DynamoDB pour planifier un téléchargement du fichier vers un compartiment Amazon Simple Storage Service (Amazon S3) à intervalles réguliers. Pour plus d'informations, consultez Exportation de données de table DynamoDB vers Amazon S3.