通过试验,我想出了一个错误——它适用于 Django,但对我来说做得不错。
首先是模型,然后是请求处理程序......
class ComplaintType:
ABUSE = 'abuse'
AUTH_FAILURE = 'auth-failure'
FRAUD = 'fraud'
NOT_SPAM = 'not-spam'
OTHER = 'other'
VIRUS = 'virus'
COMPLAINT_FEEDBACK_TYPE_CHOICES = [
[ComplaintType.ABUSE, _('Unsolicited email or some other kind of email abuse')],
[ComplaintType.AUTH_FAILURE, _('Unsolicited email or some other kind of email abuse')],
[ComplaintType.FRAUD, _('Some kind of fraud or phishing activity')],
[ComplaintType.NOT_SPAM, _('Entity providing the report does not consider the message to be spam')],
[ComplaintType.OTHER, _('Feedback does not fit into any other registered type')],
[ComplaintType.VIRUS, _('A virus was found in the originating message')]
]
class SES_Complaint(models.Model):
subject = models.CharField(max_length=255)
message = models.TextField()
email_address = models.EmailField(db_index=True)
user_agent = models.CharField(max_length=255)
complaint_feedback_type = models.CharField(max_length=255, choices=COMPLAINT_FEEDBACK_TYPE_CHOICES)
arrival_date = models.DateTimeField()
timestamp = models.DateTimeField()
feedback_id = models.CharField(max_length=255)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'SES Complaint'
verbose_name_plural = 'SES Complaints'
def get_reason(self):
return self.get_complaint_feedback_type_display()
class BounceType:
UNDETERMINED = 'Undetermined'
PERMANENT = 'Permanent'
TRANSIENT = 'Transient'
class BounceSubType:
UNDETERMINED = 'Undetermined'
GENERAL = 'General'
NO_EMAIL = 'NoEmail'
SUPPRESSED = 'Suppressed'
MAILBOX_FULL = 'MailboxFull'
MESSAGE_TOO_LARGE = 'MessageToolarge'
CONTENT_REJECTED = 'ContentRejected'
ATTACHMENT_REJECTED = 'AttachmentRejected'
BOUNCE_TYPE_CHOICES = [
[BounceType.UNDETERMINED, _('Unable to determine a specific bounce reason')],
[BounceType.PERMANENT, _('Unable to successfully send')],
[BounceType.TRANSIENT, _('All retry attempts have been exhausted')],
]
BOUNCE_SUB_TYPE_CHOICES = [
[BounceSubType.UNDETERMINED, _('Unable to determine a specific bounce reason')],
[BounceSubType.GENERAL, _('General bounce. You may be able to successfully retry sending to that recipient in the future.')],
[BounceSubType.NO_EMAIL, _('Permanent hard bounce. The target email address does not exist.')],
[BounceSubType.SUPPRESSED, _('Address has a recent history of bouncing as invalid.')],
[BounceSubType.MAILBOX_FULL, _('Mailbox full')],
[BounceSubType.MESSAGE_TOO_LARGE, _('Message too large')],
[BounceSubType.CONTENT_REJECTED, _('Content rejected')],
[BounceSubType.ATTACHMENT_REJECTED, _('Attachment rejected')]
]
class SES_Bounce(models.Model):
subject = models.CharField(max_length=255)
message = models.TextField()
bounce_type = models.CharField(max_length=255, choices=BOUNCE_TYPE_CHOICES)
bounce_sub_type = models.CharField(max_length=255, choices=BOUNCE_SUB_TYPE_CHOICES)
timestamp = models.DateTimeField()
feedback_id = models.CharField(max_length=255)
status = models.CharField(max_length=255)
action = models.CharField(max_length=255)
diagnostic_code = models.CharField(max_length=255)
email_address = models.EmailField(db_index=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True, db_index=True)
class Meta:
verbose_name = 'SES Bounce'
verbose_name_plural = 'SES Bounces'
def get_reason(self):
return '%s - %s' % (self.get_bounce_type_display(), self.get_bounce_sub_type_display())
这是请求处理程序:
@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()