12
votes

Traitement automatiquement les notifications Amazon SES pour les notifications de rebond et de plainte

Nous utilisons AWS SES pour envoyer des mails. Amazon SES envoie des notifications de rebond et de plainte via e-mails ou AWS SNS . Nous souhaitons traiter automatiquement les notifications de rebond et de plainte (provenant de courrier électronique ou AWS SNS) pour extraire les identifiants de messagerie afin que ces courriels puissent être supprimés de la liste d'origine.

Un moyen d'automatiser est d'envoyer ces notifications à un sujet dans AWS SNS, puis abonnez-vous au sujet à l'aide de AWS SQS et de lire enfin les messages dans les SQS AWS. SNS prend en charge l'abonnement sur les protocoles suivants - http / https / email / email (JSON) / SMS / SQS. Ceci est réalisable, mais je trouve trop lourd pour une tâche simple de traiter automatiquement les notifications de rebond et de plainte.

Y a-t-il un moyen élégant de clouer ce problème?


J'ai trouvé un Entrée de blog de Amazon avec le code en C #. Y a-t-il une meilleure solution?


0 commentaires

5 Réponses :


2
votes

Je pense que la façon dont vous décrivez est probablement la manière la plus élégante. Vous avez déjà des services très appropriés dans SNS et SQS qui ont associé des SDK dans la plupart des langues principales pour vous permettre de faire ce dont vous avez besoin facilement. La partie la plus difficile consiste à écrire le code pour mettre à jour / supprimer les enregistrements de vos listes de diffusion.


0 commentaires

10
votes

Je trouve que cela s'abonne directement à SNS à l'aide d'un point d'extrémité HTTP est l'approche la plus simple. Vous devez littéralement écrire seulement quelques lignes de code. Voici mon exemple de Django: xxx


1 commentaires

Ceci est moins fiable que d'utiliser des SQS si elle échoue, elle n'essaiera plus jamais - d'où la SQS est préférable.



1
votes

Récemment, j'ai pu obtenir ce travail en utilisant un point d'extrémité HTTP via SNS. J'utilise Python / Django pour consommer la notification. Vous devez d'abord traiter le message d'abonnement avant de consommer les notifications; Vous pouvez lire sur les abonnements dans la documentation SNS.

Je pense que si vous avez une application plus petite qui n'envoie pas à de nombreux courriels; Le point d'extrémité HTTP devrait fonctionner correctement. Ce code nécessite que vous ayez un modèle de notification créé. P>

#process an amazon sns http endpoint notification for amazon ses bounces and complaints
@csrf_exempt
def process_ses_notification(request):

    if request.POST:

        json_body = request.body
        #remove this control character(throws an error) thats present inside the test subscription confirmation
        js = loads(json_body.replace('\n', ''))

        if js["Type"] == "SubscriptionConfirmation":

             subscribe_url = js["SubscribeURL"]
             urllib.urlopen(subscribe_url)
             return HttpResponse(status=200)

    elif js["Type"] == "Notification":

        #process message from amazon sns
        arg_info = loads(js["Message"]) # may need to use loads(js["Message"]) after testing with amazon
        arg_notification_type = arg_info["notificationType"]

        if arg_notification_type == 'Bounce':
            #required bounce object fields
            arg_emails=arg_info["bounce"]["bouncedRecipients"]
            arg_notification_subtype=arg_info["bounce"]["bounceType"]
            arg_feedback_id=arg_info["bounce"]["feedbackId"]
            arg_date_recorded=arg_info["bounce"]["timestamp"]
        elif arg_notification_type == 'Complaint':
            #required complaint object fields
            arg_emails=arg_info["complaint"]["complainedRecipients"]
            arg_feedback_id=arg_info["complaint"]["feedbackId"]
            arg_date_recorded=arg_info["complaint"]["timestamp"]
            #check if feedback type is inside optional field name
            if "complaintFeedbackType" in arg_info["complaint"]:
                arg_notification_subtype=arg_info["complaint"]["complaintFeedbackType"]
            else:
                arg_notification_subtype=""
        else:
            HttpResponse(status=400)

        #save notifications for multiple emails
        for arg_email in arg_emails:
            notification = SES_Notification(info=json_body, notification_type=arg_notification_type, 
                                            email=arg_email["emailAddress"], notification_subtype=arg_notification_subtype, 
                                            date_recorded=arg_date_recorded, feedback_id=arg_feedback_id)
            notification.save()
        return HttpResponse(status=200)

return HttpResponse(status=400)  


0 commentaires

2
votes

Par l'essai Une erreur que je suis arrivée avec celui-ci - c'est pour Django, mais fait un travail décent pour moi.

D'abord les modèles, puis le gestionnaire de demande ... P>

@csrf_exempt
def aws_sns(request):
    logger.debug('Incoming SNS')

    if request.method == 'POST':

        logger.debug('Incoming SNS is POST')

        sns_message_type = request.META.get('HTTP_X_AMZ_SNS_MESSAGE_TYPE', None)

        if sns_message_type is not None:

            logger.debug('Incoming SNS - %s', sns_message_type)

            json_body = request.body
            json_body = json_body.replace('\n', '')
            js = loads(json_body)

            if sns_message_type == "SubscriptionConfirmation":

                subscribe_url = js["SubscribeURL"]
                logger.debug('Incoming subscription - %s', subscribe_url)
                urllib.urlopen(subscribe_url)

            elif sns_message_type == "Notification":

                message = js.get("Message", None)
                message = message.replace('\n', '')
                message = loads(message)

                notification_type = message.get("notificationType", None)

                if notification_type == 'AmazonSnsSubscriptionSucceeded':
                    logger.debug('Subscription succeeded')

                elif notification_type == 'Bounce':

                    logger.debug('Incoming bounce')

                    bounce = message['bounce']
                    bounce_type = bounce['bounceType']
                    bounce_sub_type = bounce['bounceSubType']
                    timestamp = bounce['timestamp']
                    feedback_id = bounce['feedbackId']

                    bounce_recipients = bounce['bouncedRecipients']

                    for recipient in bounce_recipients:
                        status = recipient.get('status')
                        action = recipient.get('action')
                        #diagnostic_code = recipient['diagnosticCode']
                        email_address = recipient['emailAddress']

                        SES_Bounce.objects.filter(email_address=email_address).delete()

                        SES_Bounce.objects.create(
                            message=message,
                            bounce_type=bounce_type,
                            bounce_sub_type=bounce_sub_type,
                            timestamp=timestamp,
                            feedback_id=feedback_id,
                            status=status,
                            action=action,
                            #diagnostic_code=diagnostic_code,
                            email_address=email_address
                        )

                elif notification_type == 'Complaint':

                    logger.debug('Incoming complaint')

                    complaint = message['complaint']

                    user_agent = complaint.get('userAgent')
                    complaint_feedback_type = complaint.get('complaintFeedbackType')
                    arrival_date = complaint.get('arrivalDate')

                    timestamp = complaint['timestamp']
                    feedback_id = complaint['feedbackId']
                    recipients = complaint['complainedRecipients']

                    for recipient in recipients:
                        email_address = recipient['emailAddress']

                        SES_Complaint.objects.filter(email_address=email_address).delete()

                        SES_Complaint.objects.create(
                            #subject=subject,
                            message=message,
                            email_address=email_address,
                            user_agent=user_agent,
                            complaint_feedback_type=complaint_feedback_type,
                            arrival_date=arrival_date,
                            timestamp=timestamp,
                            feedback_id=feedback_id
                        )

                else:
                    logger.exception('Incoming Notification SNS is not supported: %s', notification_type)

            return HttpResponse()
        else:
            logger.exception('Incoming SNS did not have the right header')

            for key, value in request.META.items():
                logger.debug('Key: %s - %s', key, value)

    else:
        logger.exception('Incoming SNS was not a POST')

    return HttpResponseBadRequest()


0 commentaires

1
votes

Toutes les réponses ci-dessus sont superbes, mais juste un petit et important ajout:

Vous devez d'abord vérifier que la demande provient d'Amazon SNS: (comme décrit à Vérification des signatures des messages Amazon SNS )

Pour le code Python qui valide la signature - un bon exemple est ici


0 commentaires