diff --git a/src/teams/email.py b/src/teams/email.py index f20a5055..8a90e82c 100644 --- a/src/teams/email.py +++ b/src/teams/email.py @@ -1,4 +1,4 @@ -from utils.email import _send_email +from utils.email import add_outgoing_email import logging logger = logging.getLogger("bornhack.%s" % __name__) @@ -9,7 +9,7 @@ def send_add_membership_email(membership): 'camp': membership.team.camp.title } - return _send_email( + return add_outgoing_email( text_template='emails/add_membership_email.txt', html_template='emails/add_membership_email.html', recipient=membership.user.email, @@ -31,7 +31,7 @@ def send_remove_membership_email(membership): text_template = 'emails/unapproved_membership_email.txt', html_template = 'emails/unapproved_membership_email.html' - return _send_email( + return add_outgoing_email( text_template=text_template, html_template=html_template, recipient=membership.user.email, @@ -46,10 +46,12 @@ def send_new_membership_email(membership): 'camp': membership.team.camp.title } - return _send_email( + return add_outgoing_email( text_template='emails/new_membership_email.txt', html_template='emails/new_membership_email.html', - recipient=[resp.email for resp in membership.team.responsible], + recipients=', '.join( + [resp.email for resp in membership.team.responsible] + ), formatdict=formatdict, subject='New membership request for {} at {}'.format( membership.team.name, diff --git a/src/utils/admin.py b/src/utils/admin.py new file mode 100644 index 00000000..7eb6ca09 --- /dev/null +++ b/src/utils/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin + +from .models import OutgoingEmail + + +@admin.register(OutgoingEmail) +class OutgoingEmailAdmin(admin.ModelAdmin): + pass diff --git a/src/utils/email.py b/src/utils/email.py index b7b3dc5c..6fbd10cb 100644 --- a/src/utils/email.py +++ b/src/utils/email.py @@ -1,6 +1,8 @@ from django.core.mail import EmailMultiAlternatives from django.conf import settings from django.template.loader import render_to_string +from django.core.validators import validate_email +from .models import OutgoingEmail import logging logger = logging.getLogger("bornhack.%s" % __name__) @@ -8,12 +10,11 @@ logger = logging.getLogger("bornhack.%s" % __name__) def _send_email( text_template, recipient, - formatdict, subject, - html_template=None, + html_template='', sender='BornHack ', - attachment=None, - attachment_filename=None + attachment='', + attachment_filename='' ): if not isinstance(recipient, list): recipient = [recipient] @@ -22,7 +23,7 @@ def _send_email( # put the basic email together msg = EmailMultiAlternatives( subject, - render_to_string(text_template, formatdict), + text_template, sender, recipient, [settings.ARCHIVE_EMAIL] @@ -31,7 +32,7 @@ def _send_email( # is there a html version of this email? if html_template: msg.attach_alternative( - render_to_string(html_template, formatdict), + html_template, 'text/html' ) @@ -47,3 +48,39 @@ def _send_email( msg.send() return True + + +def add_outgoing_email( + text_template, + recipients, + formatdict, + subject, + html_template='', + sender='BornHack ', + attachment='', + attachment_filename='' +): + """ adds an email to the outgoing queue + recipients is either just a str email or a str commaseperated emails + """ + text_template = render_to_string(text_template, formatdict) + + if html_template: + html_template = render_to_string(html_template, formatdict) + + if ',' in recipients: + for recipient in recipients.split(','): + validate_email(recipient.strip()) + else: + validate_email(recipients) + + OutgoingEmail.objects.create( + text_template=text_template, + html_template=html_template, + subject=subject, + sender=sender, + recipient=recipients, + attachment=attachment, + attachment_filename=attachment_filename + ) + return True diff --git a/src/utils/models.py b/src/utils/models.py index 4b6fe155..51c10bbb 100644 --- a/src/utils/models.py +++ b/src/utils/models.py @@ -68,3 +68,14 @@ class CampRelatedModel(CreatedUpdatedModel): raise ValidationError('This camp is in read only mode.') super().delete(**kwargs) + + +class OutgoingEmail(CreatedUpdatedModel): + subject = models.CharField(max_length=500) + text_template = models.TextField() + html_template = models.TextField(blank=True) + recipient = models.CharField(max_length=500) + sender = models.CharField(max_length=500) + attachment = models.CharField(max_length=500, blank=True) + attachment_filename = models.CharField(max_length=500, blank=True) + processed = models.BooleanField(default=False) diff --git a/src/utils/outgoingemailworker.py b/src/utils/outgoingemailworker.py new file mode 100644 index 00000000..48f11a83 --- /dev/null +++ b/src/utils/outgoingemailworker.py @@ -0,0 +1,28 @@ +from .models import OutgoingEmail +from .email import _send_email +import logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger('bornhack.%s' % __name__) + + +def do_work(): + """ + The outgoing email worker sends emails added to the OutgoingEmail + queue. + """ + not_processed_email = OutgoingEmail.objects.filter(processed=False) + + for email in not_processed_email: + if ',' in email.recipient: + recipient = email.recipient.split(',') + else: + recipient = [email.recipient] + + _send_email( + text_template=email.text_template, + recipient=recipient, + subject=email.subject, + html_template=email.html_template, + attachment=email.attachment, + attachment_filename=email.attachment_filename + )