Skip to content
This repository has been archived by the owner on Nov 10, 2022. It is now read-only.

Add support for SES Event Publishing #10

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 40 additions & 5 deletions django_bouncy/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

from django.contrib import admin

from django_bouncy.models import Bounce, Complaint, Delivery
from django_bouncy.models import Bounce, Complaint, Delivery, Send, Open, Click, RenderingFailure, DeliveryDelay


class BounceAdmin(admin.ModelAdmin):
"""Admin model for 'Bounce' objects"""
list_display = (
'address', 'mail_from', 'bounce_type', 'bounce_subtype', 'status')
'feedback_timestamp', 'address', 'mail_from', 'bounce_type', 'bounce_subtype', 'status')
list_filter = (
'hard', 'action', 'bounce_type', 'bounce_subtype',
'feedback_timestamp'
Expand All @@ -18,18 +18,53 @@ class BounceAdmin(admin.ModelAdmin):

class ComplaintAdmin(admin.ModelAdmin):
"""Admin model for 'Complaint' objects"""
list_display = ('address', 'mail_from', 'feedback_type')
list_display = ('feedback_timestamp', 'address', 'mail_from', 'feedback_type')
list_filter = ('feedback_type', 'feedback_timestamp')
search_fields = ('address',)


class DeliveryAdmin(admin.ModelAdmin):
"""Admin model for 'Delivery' objects"""
list_display = ('address', 'mail_from')
list_filter = ('feedback_timestamp',)
list_display = ('delivered_time', 'address', 'mail_from')
list_filter = ('delivered_time',)
search_fields = ('address',)


class SendAdmin(admin.ModelAdmin):
list_display = ('mail_timestamp', 'address', 'mail_from',)
list_filter = ('mail_timestamp',)
search_fields = ('address',)


class OpenAdmin(admin.ModelAdmin):
list_display = ('opened_time', 'address', 'mail_from',)
list_filter = ('opened_time',)
search_fields = ('address',)


class ClickAdmin(admin.ModelAdmin):
list_display = ('clicked_time', 'address', 'mail_from', 'link',)
list_filter = ('clicked_time',)
search_fields = ('address',)


class RenderingFailureAdmin(admin.ModelAdmin):
list_display = ('mail_timestamp', 'address', 'mail_from', 'template_name', 'error_message',)
list_filter = ('mail_timestamp',)
search_fields = ('address', 'template_name',)


class DeliveryDelayAdmin(admin.ModelAdmin):
list_display = ('delayed_time', 'address', 'mail_from', 'delay_type',)
list_filter = ('delayed_time',)
search_fields = ('address', 'delay_type',)


admin.site.register(Bounce, BounceAdmin)
admin.site.register(Complaint, ComplaintAdmin)
admin.site.register(Delivery, DeliveryAdmin)
admin.site.register(Send, SendAdmin)
admin.site.register(Open, OpenAdmin)
admin.site.register(Click, ClickAdmin)
admin.site.register(RenderingFailure, RenderingFailureAdmin)
admin.site.register(DeliveryDelay, DeliveryDelayAdmin)
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.23 on 2020-12-09 02:03
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('django_bouncy', '0005_auto_20190731_0423'),
]

operations = [
migrations.CreateModel(
name='Click',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('modified_at', models.DateTimeField(auto_now=True)),
('sns_topic', models.CharField(max_length=350)),
('sns_messageid', models.CharField(max_length=100)),
('mail_timestamp', models.DateTimeField()),
('mail_id', models.CharField(max_length=100)),
('mail_from', models.EmailField(max_length=254)),
('address', models.EmailField(max_length=254)),
('feedback_id', models.CharField(blank=True, max_length=100, null=True)),
('feedback_timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Feedback Time')),
('clicked_time', models.DateTimeField(blank=True, null=True)),
('ip_address', models.GenericIPAddressField(blank=True, null=True)),
('useragent', models.TextField(blank=True, null=True)),
('link', models.TextField(blank=True, null=True)),
('link_tags', models.TextField(blank=True, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='DeliveryDelay',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('modified_at', models.DateTimeField(auto_now=True)),
('sns_topic', models.CharField(max_length=350)),
('sns_messageid', models.CharField(max_length=100)),
('mail_timestamp', models.DateTimeField()),
('mail_id', models.CharField(max_length=100)),
('mail_from', models.EmailField(max_length=254)),
('address', models.EmailField(max_length=254)),
('feedback_id', models.CharField(blank=True, max_length=100, null=True)),
('feedback_timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Feedback Time')),
('delayed_time', models.DateTimeField(blank=True, null=True)),
('delay_type', models.TextField(blank=True, null=True)),
('expiration_time', models.DateTimeField(blank=True, null=True)),
('reporting_mta', models.GenericIPAddressField(blank=True, null=True)),
('status', models.TextField(blank=True, null=True)),
('diagnostic_code', models.TextField(blank=True, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Open',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('modified_at', models.DateTimeField(auto_now=True)),
('sns_topic', models.CharField(max_length=350)),
('sns_messageid', models.CharField(max_length=100)),
('mail_timestamp', models.DateTimeField()),
('mail_id', models.CharField(max_length=100)),
('mail_from', models.EmailField(max_length=254)),
('address', models.EmailField(max_length=254)),
('feedback_id', models.CharField(blank=True, max_length=100, null=True)),
('feedback_timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Feedback Time')),
('opened_time', models.DateTimeField(blank=True, null=True)),
('ip_address', models.GenericIPAddressField(blank=True, null=True)),
('useragent', models.TextField(blank=True, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Reject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('modified_at', models.DateTimeField(auto_now=True)),
('sns_topic', models.CharField(max_length=350)),
('sns_messageid', models.CharField(max_length=100)),
('mail_timestamp', models.DateTimeField()),
('mail_id', models.CharField(max_length=100)),
('mail_from', models.EmailField(max_length=254)),
('address', models.EmailField(max_length=254)),
('feedback_id', models.CharField(blank=True, max_length=100, null=True)),
('feedback_timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Feedback Time')),
('reason', models.TextField(blank=True, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='RenderingFailure',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('modified_at', models.DateTimeField(auto_now=True)),
('sns_topic', models.CharField(max_length=350)),
('sns_messageid', models.CharField(max_length=100)),
('mail_timestamp', models.DateTimeField()),
('mail_id', models.CharField(max_length=100)),
('mail_from', models.EmailField(max_length=254)),
('address', models.EmailField(max_length=254)),
('feedback_id', models.CharField(blank=True, max_length=100, null=True)),
('feedback_timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Feedback Time')),
('template_name', models.TextField(blank=True, null=True)),
('error_message', models.TextField(blank=True, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Send',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('modified_at', models.DateTimeField(auto_now=True)),
('sns_topic', models.CharField(max_length=350)),
('sns_messageid', models.CharField(max_length=100)),
('mail_timestamp', models.DateTimeField()),
('mail_id', models.CharField(max_length=100)),
('mail_from', models.EmailField(max_length=254)),
('address', models.EmailField(max_length=254)),
('feedback_id', models.CharField(blank=True, max_length=100, null=True)),
('feedback_timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Feedback Time')),
],
options={
'abstract': False,
},
),
]
85 changes: 85 additions & 0 deletions django_bouncy/migrations/0007_auto_20210317_0440.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.23 on 2021-03-17 04:40
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('django_bouncy', '0006_click_deliverydelay_open_reject_renderingfailure_send'),
]

operations = [
migrations.AlterField(
model_name='bounce',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
migrations.AlterField(
model_name='click',
name='clicked_time',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AlterField(
model_name='click',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
migrations.AlterField(
model_name='complaint',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
migrations.AlterField(
model_name='delivery',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
migrations.AlterField(
model_name='deliverydelay',
name='delay_type',
field=models.TextField(blank=True, db_index=True, null=True),
),
migrations.AlterField(
model_name='deliverydelay',
name='delayed_time',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AlterField(
model_name='deliverydelay',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
migrations.AlterField(
model_name='open',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
migrations.AlterField(
model_name='open',
name='opened_time',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AlterField(
model_name='reject',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
migrations.AlterField(
model_name='renderingfailure',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
migrations.AlterField(
model_name='renderingfailure',
name='template_name',
field=models.TextField(blank=True, db_index=True, null=True),
),
migrations.AlterField(
model_name='send',
name='mail_id',
field=models.CharField(db_index=True, max_length=100),
),
]
79 changes: 78 additions & 1 deletion django_bouncy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Feedback(models.Model):
sns_topic = models.CharField(max_length=350)
sns_messageid = models.CharField(max_length=100)
mail_timestamp = models.DateTimeField()
mail_id = models.CharField(max_length=100)
mail_id = models.CharField(db_index=True, max_length=100)
mail_from = models.EmailField()
address = models.EmailField()
# no feedback for delivery messages
Expand Down Expand Up @@ -79,3 +79,80 @@ def __str__(self):
class Meta(object):
"""Meta info for the Delivery model"""
verbose_name_plural = 'deliveries'


@python_2_unicode_compatible
class Send(Feedback):
"""A send report for an individual email address"""

def __str__(self):
"""Unicode representation of Send"""
return "%s Send (email sender: %s)" % (
self.address, self.mail_from)


@python_2_unicode_compatible
class Reject(Feedback):
"""A reject report for an individual email address"""
reason = models.TextField(blank=True, null=True)

def __str__(self):
"""Unicode representation of Reject"""
return "%s %s Reject (email sender: %s)" % (
self.address, self.reason, self.mail_from)


@python_2_unicode_compatible
class Open(Feedback):
"""An open report for an individual email address"""
opened_time = models.DateTimeField(blank=True, null=True, db_index=True)
ip_address = models.GenericIPAddressField(blank=True, null=True)
useragent = models.TextField(blank=True, null=True)

def __str__(self):
"""Unicode representation of Open"""
return "%s Open (email sender: %s)" % (
self.address, self.mail_from)


@python_2_unicode_compatible
class Click(Feedback):
"""A click report for an individual email address"""
clicked_time = models.DateTimeField(blank=True, null=True, db_index=True)
ip_address = models.GenericIPAddressField(blank=True, null=True)
useragent = models.TextField(blank=True, null=True)
link = models.TextField(blank=True, null=True)
link_tags = models.TextField(blank=True, null=True)

def __str__(self):
"""Unicode representation of Click"""
return "%s %s Open (email sender: %s)" % (
self.address, self.link, self.mail_from)


@python_2_unicode_compatible
class RenderingFailure(Feedback):
"""A rendering failure report for an individual email address"""
template_name = models.TextField(blank=True, null=True, db_index=True)
error_message = models.TextField(blank=True, null=True)

def __str__(self):
"""Unicode representation of Rendering Failure"""
return "%s %s rendering failure %s" % (
self.address, self.template_name, self.error_message)


@python_2_unicode_compatible
class DeliveryDelay(Feedback):
"""A delivery delay report for an individual email address"""
delayed_time = models.DateTimeField(blank=True, null=True, db_index=True)
delay_type = models.TextField(blank=True, null=True, db_index=True)
expiration_time = models.DateTimeField(blank=True, null=True)
reporting_mta = models.GenericIPAddressField(blank=True, null=True)
status = models.TextField(blank=True, null=True)
diagnostic_code = models.TextField(blank=True, null=True)

def __str__(self):
"""Unicode representation of Delivery Delay"""
return "%s delivery delay %s %s" % (
self.address, self.status, self.diagnostic_code)
Loading