コード例 #1
0
ファイル: views.py プロジェクト: ibraheem4/django-ses
def handle_bounce(request):
    """
    Handle a bounced email via an SNS webhook.

    Parse the bounced message and send the appropriate signal.
    For bounce messages the bounce_received signal is called.
    For complaint messages the complaint_received signal is called.
    See: http://docs.aws.amazon.com/sns/latest/gsg/json-formats.html#http-subscription-confirmation-json
    See: http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/NotificationsViaSNS.html
    
    In addition to email bounce requests this endpoint also supports the SNS
    subscription confirmation request. This request is sent to the SNS
    subscription endpoint when the subscription is registered.
    See: http://docs.aws.amazon.com/sns/latest/gsg/Subscribe.html

    For the format of the SNS subscription confirmation request see this URL:
    http://docs.aws.amazon.com/sns/latest/gsg/json-formats.html#http-subscription-confirmation-json
    
    SNS message signatures are verified by default. This funcionality can
    be disabled by setting AWS_SES_VERIFY_BOUNCE_SIGNATURES to False.
    However, this is not recommended.
    See: http://docs.amazonwebservices.com/sns/latest/gsg/SendMessageToHttp.verify.signature.html
    """

    # For Django >= 1.4 use request.body, otherwise
    # use the old request.raw_post_data
    if hasattr(request, "body"):
        raw_json = request.body
    else:
        raw_json = request.raw_post_data

    try:
        notification = json.loads(raw_json)
    except ValueError as e:
        # TODO: What kind of response should be returned here?
        logger.warning('Recieved bounce with bad JSON: "%s"', e)
        return HttpResponseBadRequest()

    # Verify the authenticity of the bounce message.
    if settings.VERIFY_BOUNCE_SIGNATURES and not utils.verify_bounce_message(notification):
        # Don't send any info back when the notification is not
        # verified. Simply, don't process it.
        logger.info(
            "Recieved unverified notification: Type: %s", notification.get("Type"), extra={"notification": notification}
        )
        return HttpResponse()

    if notification.get("Type") in ("SubscriptionConfirmation", "UnsubscribeConfirmation"):
        # Process the (un)subscription confirmation.

        logger.info(
            "Recieved subscription confirmation: TopicArn: %s",
            notification.get("TopicArn"),
            extra={"notification": notification},
        )

        # Get the subscribe url and hit the url to confirm the subscription.
        subscribe_url = notification.get("SubscribeURL")
        try:
            urlopen(subscribe_url).read()
        except URLError as e:
            # Some kind of error occurred when confirming the request.
            logger.error('Could not confirm subscription: "%s"', e, extra={"notification": notification}, exc_info=True)
    elif notification.get("Type") == "Notification":
        try:
            message = json.loads(notification["Message"])
        except ValueError as e:
            # The message isn't JSON.
            # Just ignore the notification.
            logger.warning('Recieved bounce with bad JSON: "%s"', e, extra={"notification": notification})
        else:
            mail_obj = message.get("mail")
            notification_type = message.get("notificationType")

            if notification_type == "Bounce":
                # Bounce
                bounce_obj = message.get("bounce", {})

                # Logging
                feedback_id = bounce_obj.get("feedbackId")
                bounce_type = bounce_obj.get("bounceType")
                bounce_subtype = bounce_obj.get("bounceSubType")
                logger.info(
                    "Recieved bounce notification: feedbackId: %s, bounceType: %s, bounceSubType: %s",
                    feedback_id,
                    bounce_type,
                    bounce_subtype,
                    extra={"notification": notification},
                )

                signals.bounce_received.send(
                    sender=handle_bounce, mail_obj=mail_obj, bounce_obj=bounce_obj, raw_message=raw_json
                )
            elif notification_type == "Complaint":
                # Complaint
                complaint_obj = message.get("complaint", {})

                # Logging
                feedback_id = complaint_obj.get("feedbackId")
                feedback_type = complaint_obj.get("complaintFeedbackType")
                logger.info(
                    "Recieved complaint notification: feedbackId: %s, feedbackType: %s",
                    feedback_id,
                    feedback_type,
                    extra={"notification": notification},
                )

                signals.complaint_received.send(
                    sender=handle_bounce, mail_obj=mail_obj, complaint_obj=complaint_obj, raw_message=raw_json
                )
            else:
                # We received an unknown notification type. Just log and
                # ignore it.
                logger.warning("Recieved unknown notification", extra={"notification": notification})
    else:
        logger.info(
            "Recieved unknown notification type: %s", notification.get("Type"), extra={"notification": notification}
        )

    # AWS will consider anything other than 200 to be an error response and
    # resend the SNS request. We don't need that so we return 200 here.
    return HttpResponse()
コード例 #2
0
ファイル: views.py プロジェクト: IanLewis/django-ses
    # use the old request.raw_post_data
    if hasattr(request, 'body'):
        raw_json = request.body
    else:
        raw_json = request.raw_post_data

    try:
        notification = json.loads(raw_json)
    except ValueError, e:
        # TODO: What kind of response should be returned here?
        logger.warning('Recieved bounce with bad JSON: "%s"', e)
        return HttpResponseBadRequest()

    # Verify the authenticity of the bounce message.
    if (settings.VERIFY_BOUNCE_SIGNATURES and 
            not utils.verify_bounce_message(notification)):
        # Don't send any info back when the notification is not
        # verified. Simply, don't process it.
        logger.info('Recieved unverified notification: Type: %s', 
            notification.get('Type'),
            extra={
                'notification': notification,
            },
        )
        return HttpResponse()

    if notification.get('Type') in ('SubscriptionConfirmation',
                                    'UnsubscribeConfirmation'):
        # Process the (un)subscription confirmation.

        logger.info('Recieved subscription confirmation: TopicArn: %s', 
コード例 #3
0
def handle_bounce(request):
    """
    Handle a bounced email via an SNS webhook.

    Parse the bounced message and send the appropriate signal.
    For bounce messages the bounce_received signal is called.
    For complaint messages the complaint_received signal is called.
    See: http://docs.aws.amazon.com/sns/latest/gsg/json-formats.html#http-subscription-confirmation-json
    See: http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/NotificationsViaSNS.html

    In addition to email bounce requests this endpoint also supports the SNS
    subscription confirmation request. This request is sent to the SNS
    subscription endpoint when the subscription is registered.
    See: http://docs.aws.amazon.com/sns/latest/gsg/Subscribe.html

    For the format of the SNS subscription confirmation request see this URL:
    http://docs.aws.amazon.com/sns/latest/gsg/json-formats.html#http-subscription-confirmation-json

    SNS message signatures are verified by default. This funcionality can
    be disabled by setting AWS_SES_VERIFY_BOUNCE_SIGNATURES to False.
    However, this is not recommended.
    See: http://docs.amazonwebservices.com/sns/latest/gsg/SendMessageToHttp.verify.signature.html
    """

    raw_json = request.body

    try:
        notification = json.loads(raw_json.decode('utf-8'))
    except ValueError as e:
        # TODO: What kind of response should be returned here?
        logger.warning(u'Received bounce with bad JSON: "%s"', e)
        return HttpResponseBadRequest()

    # Verify the authenticity of the bounce message.
    if (settings.VERIFY_BOUNCE_SIGNATURES and
            not utils.verify_bounce_message(notification)):
        # Don't send any info back when the notification is not
        # verified. Simply, don't process it.
        logger.info(u'Received unverified notification: Type: %s',
            notification.get('Type'),
            extra={
                'notification': notification,
            },
        )
        return HttpResponse()

    if notification.get('Type') in ('SubscriptionConfirmation',
                                    'UnsubscribeConfirmation'):
        # Process the (un)subscription confirmation.

        logger.info(u'Received subscription confirmation: TopicArn: %s',
            notification.get('TopicArn'),
            extra={
                'notification': notification,
            },
        )

        # Get the subscribe url and hit the url to confirm the subscription.
        subscribe_url = notification.get('SubscribeURL')
        try:
            urlopen(subscribe_url).read()
        except URLError as e:
            # Some kind of error occurred when confirming the request.
            logger.error(u'Could not confirm subscription: "%s"', e,
                extra={
                    'notification': notification,
                },
                exc_info=True,
            )
    elif notification.get('Type') == 'Notification':
        try:
            message = json.loads(notification['Message'])
        except ValueError as e:
            # The message isn't JSON.
            # Just ignore the notification.
            logger.warning(u'Received bounce with bad JSON: "%s"', e, extra={
                'notification': notification,
            })
        else:
            mail_obj = message.get('mail')
            notification_type = message.get('notificationType')

            if notification_type == 'Bounce':
                # Bounce
                bounce_obj = message.get('bounce', {})

                # Logging
                feedback_id = bounce_obj.get('feedbackId')
                bounce_type = bounce_obj.get('bounceType')
                bounce_subtype = bounce_obj.get('bounceSubType')
                logger.info(
                    u'Received bounce notification: feedbackId: %s, bounceType: %s, bounceSubType: %s',
                    feedback_id, bounce_type, bounce_subtype,
                    extra={
                        'notification': notification,
                    },
                )

                signals.bounce_received.send(
                    sender=handle_bounce,
                    mail_obj=mail_obj,
                    bounce_obj=bounce_obj,
                    raw_message=raw_json,
                )
            elif notification_type == 'Complaint':
                # Complaint
                complaint_obj = message.get('complaint', {})

                # Logging
                feedback_id = complaint_obj.get('feedbackId')
                feedback_type = complaint_obj.get('complaintFeedbackType')
                logger.info(u'Received complaint notification: feedbackId: %s, feedbackType: %s',
                    feedback_id, feedback_type,
                    extra={
                        'notification': notification,
                    },
                )

                signals.complaint_received.send(
                    sender=handle_bounce,
                    mail_obj=mail_obj,
                    complaint_obj=complaint_obj,
                    raw_message=raw_json,
                )
            elif notification_type == 'Delivery':
                # Delivery
                delivery_obj = message.get('delivery', {})

                # Logging
                feedback_id = delivery_obj.get('feedbackId')
                feedback_type = delivery_obj.get('deliveryFeedbackType')
                logger.info(u'Received delivery notification: feedbackId: %s, feedbackType: %s',
                    feedback_id, feedback_type,
                    extra={
                        'notification': notification,
                    },
                )

                signals.delivery_received.send(
                    sender=handle_bounce,
                    mail_obj=mail_obj,
                    delivery_obj=delivery_obj,
                    raw_message=raw_json,
                )
            else:
                # We received an unknown notification type. Just log and
                # ignore it.
                logger.warning(u"Received unknown notification", extra={
                    'notification': notification,
                })
    else:
        logger.info(u'Received unknown notification type: %s',
            notification.get('Type'),
            extra={
                'notification': notification,
            },
        )

    # AWS will consider anything other than 200 to be an error response and
    # resend the SNS request. We don't need that so we return 200 here.
    return HttpResponse()
コード例 #4
0
    # use the old request.raw_post_data
    if hasattr(request, 'body'):
        raw_json = request.body
    else:
        raw_json = request.raw_post_data

    try:
        notification = json.loads(raw_json)
    except ValueError, e:
        # TODO: What kind of response should be returned here?
        logger.warning('Recieved bounce with bad JSON: "%s"', e)
        return HttpResponseBadRequest()

    # Verify the authenticity of the bounce message.
    if (settings.VERIFY_BOUNCE_SIGNATURES
            and not utils.verify_bounce_message(notification)):
        # Don't send any info back when the notification is not
        # verified. Simply, don't process it.
        logger.info(
            'Recieved unverified notification: Type: %s',
            notification.get('Type'),
            extra={
                'notification': notification,
            },
        )
        return HttpResponse()

    if notification.get('Type') in ('SubscriptionConfirmation',
                                    'UnsubscribeConfirmation'):
        # Process the (un)subscription confirmation.