Import mailqueue app from pgeu
authorMagnus Hagander <magnus@hagander.net>
Tue, 9 Feb 2016 15:28:21 +0000 (16:28 +0100)
committerMagnus Hagander <magnus@hagander.net>
Tue, 9 Feb 2016 15:28:21 +0000 (16:28 +0100)
hamnadmin/hamnadmin/mailqueue/__init__.py [new file with mode: 0644]
hamnadmin/hamnadmin/mailqueue/admin.py [new file with mode: 0644]
hamnadmin/hamnadmin/mailqueue/management/__init__.py [new file with mode: 0644]
hamnadmin/hamnadmin/mailqueue/management/commands/__init__.py [new file with mode: 0644]
hamnadmin/hamnadmin/mailqueue/management/commands/send_queued_mail.py [new file with mode: 0755]
hamnadmin/hamnadmin/mailqueue/migrations/0001_initial.py [new file with mode: 0644]
hamnadmin/hamnadmin/mailqueue/migrations/__init__.py [new file with mode: 0644]
hamnadmin/hamnadmin/mailqueue/models.py [new file with mode: 0644]
hamnadmin/hamnadmin/mailqueue/util.py [new file with mode: 0644]
hamnadmin/hamnadmin/settings.py

diff --git a/hamnadmin/hamnadmin/mailqueue/__init__.py b/hamnadmin/hamnadmin/mailqueue/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/hamnadmin/hamnadmin/mailqueue/admin.py b/hamnadmin/hamnadmin/mailqueue/admin.py
new file mode 100644 (file)
index 0000000..ccabb81
--- /dev/null
@@ -0,0 +1,5 @@
+from django.contrib import admin
+
+from models import QueuedMail
+
+admin.site.register(QueuedMail)
diff --git a/hamnadmin/hamnadmin/mailqueue/management/__init__.py b/hamnadmin/hamnadmin/mailqueue/management/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/hamnadmin/hamnadmin/mailqueue/management/commands/__init__.py b/hamnadmin/hamnadmin/mailqueue/management/commands/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/hamnadmin/hamnadmin/mailqueue/management/commands/send_queued_mail.py b/hamnadmin/hamnadmin/mailqueue/management/commands/send_queued_mail.py
new file mode 100755 (executable)
index 0000000..6319b2e
--- /dev/null
@@ -0,0 +1,34 @@
+# Script to send off all queued email.
+#
+# This script is intended to be run frequently from cron. We queue things
+# up in the db so that they get automatically rolled back as necessary,
+# but once we reach this point we're just going to send all of them one
+# by one.
+#
+from django.core.management.base import BaseCommand, CommandError
+from django.db import connection
+
+import smtplib
+
+from hamnadmin.mailqueue.models import QueuedMail
+
+class Command(BaseCommand):
+       help = 'Send queued mail'
+
+       def handle(self, *args, **options):
+               # Grab advisory lock, if available. Lock id is just a random number
+               # since we only need to interlock against ourselves. The lock is
+               # automatically released when we're done.
+               curs = connection.cursor()
+               curs.execute("SELECT pg_try_advisory_lock(72181378)")
+               if not curs.fetchall()[0][0]:
+                       raise CommandException("Failed to get advisory lock, existing send_queued_mail process stuck?")
+
+               for m in QueuedMail.objects.all():
+                       # Yes, we do a new connection for each run. Just because we can.
+                       # If it fails we'll throw an exception and just come back on the
+                       # next cron job. And local delivery should never fail...
+                       smtp = smtplib.SMTP("localhost")
+                       smtp.sendmail(m.sender, m.receiver, m.fullmsg.encode('utf-8'))
+                       smtp.close()
+                       m.delete()
diff --git a/hamnadmin/hamnadmin/mailqueue/migrations/0001_initial.py b/hamnadmin/hamnadmin/mailqueue/migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..cd39282
--- /dev/null
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='QueuedMail',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('sender', models.EmailField(max_length=100)),
+                ('receiver', models.EmailField(max_length=100)),
+                ('fullmsg', models.TextField()),
+            ],
+        ),
+    ]
diff --git a/hamnadmin/hamnadmin/mailqueue/migrations/__init__.py b/hamnadmin/hamnadmin/mailqueue/migrations/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/hamnadmin/hamnadmin/mailqueue/models.py b/hamnadmin/hamnadmin/mailqueue/models.py
new file mode 100644 (file)
index 0000000..f2e7d19
--- /dev/null
@@ -0,0 +1,11 @@
+from django.db import models
+
+class QueuedMail(models.Model):
+       sender = models.EmailField(max_length=100, null=False, blank=False)
+       receiver = models.EmailField(max_length=100, null=False, blank=False)
+       # We store the raw MIME message, so if there are any attachments or
+       # anything, we just push them right in there!
+       fullmsg = models.TextField(null=False, blank=False)
+
+       def __unicode__(self):
+               return "%s: %s -> %s" % (self.pk, self.sender, self.receiver)
diff --git a/hamnadmin/hamnadmin/mailqueue/util.py b/hamnadmin/hamnadmin/mailqueue/util.py
new file mode 100644 (file)
index 0000000..2f616b6
--- /dev/null
@@ -0,0 +1,46 @@
+from email.mime.text import MIMEText
+from email.mime.multipart import MIMEMultipart
+from email.mime.nonmultipart import MIMENonMultipart
+from email.Utils import formatdate
+from email import encoders
+
+from models import QueuedMail
+
+def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, bcc=None, sendername=None, receivername=None):
+       # attachment format, each is a tuple of (name, mimetype,contents)
+       # content should be *binary* and not base64 encoded, since we need to
+       # use the base64 routines from the email library to get a properly
+       # formatted output message
+       msg = MIMEMultipart()
+       msg['Subject'] = subject
+       if receivername:
+               msg['To'] = u'{0} <{1}>'.format(receivername, receiver)
+       else:
+               msg['To'] = receiver
+       if sendername:
+               msg['From'] = u'{0} <{1}>'.format(sendername, sender)
+       else:
+               msg['From'] = sender
+       msg['Date'] = formatdate(localtime=True)
+
+       msg.attach(MIMEText(msgtxt, _charset='utf-8'))
+
+       if attachments:
+               for filename, contenttype, content in attachments:
+                       main,sub = contenttype.split('/')
+                       part = MIMENonMultipart(main,sub)
+                       part.set_payload(content)
+                       part.add_header('Content-Disposition', 'attachment; filename="%s"' % filename)
+                       encoders.encode_base64(part)
+                       msg.attach(part)
+
+
+       # Just write it to the queue, so it will be transactionally rolled back
+       QueuedMail(sender=sender, receiver=receiver, fullmsg=msg.as_string()).save()
+       # Any bcc is just entered as a separate email
+       if bcc:
+               QueuedMail(sender=sender, receiver=bcc, fullmsg=msg.as_string()).save()
+
+def send_mail(sender, receiver, fullmsg):
+       # Send an email, prepared as the full MIME encoded mail already
+       QueuedMail(sender=sender, receiver=receiver, fullmsg=fullmsg).save()
index 649f41ae46af4340c3ed98c4a0ccd8a7ae95cbc7..2c6c9b4ce9c4c3d4ca1a9d642481e5f43c324017 100644 (file)
@@ -57,6 +57,7 @@ INSTALLED_APPS = (
     'django.contrib.sites',
        'django.contrib.staticfiles',
     'hamnadmin.register',
+    'hamnadmin.mailqueue',
     'django.contrib.admin',
 )