from smtplib import SMTPRecipientsRefused from typing import Optional import structlog from django.conf import settings from django.core import mail from django.template.context import Context from django_q.tasks import async_task from greg.models import InvitationLink, Sponsor from gregui.models import EmailTemplate logger = structlog.getLogger(__name__) class InviteGuest: def make_registration_url(self, token: str) -> str: return "{base}/invite#{token}".format( base=settings.BASE_URL, token=token, ) def get_template(self): return EmailTemplate.objects.get( template_key=EmailTemplate.EmailType.GUEST_REGISTRATION ) def get_notice_template(self): return EmailTemplate.objects.get( template_key=EmailTemplate.EmailType.INVALID_EMAIL ) def send_bad_email_notice( self, guest_name: str, guest_mail: str, sponsor_mail: str ): template = self.get_notice_template() context = Context( { "guest_name": guest_name, "guest_email": guest_mail, } ) mail.send_mail( subject=template.get_subject(context), message=template.get_body(context), from_email=template.from_email or None, recipient_list=[sponsor_mail], ) def queue_mail(self, link: InvitationLink) -> Optional[str]: guest = link.invitation.role.person email_address = guest.private_email if not email_address: logger.warning( "No e-mail address found for invitation link with ID: {%s}", link.id ) return None sponsor = link.invitation.role.sponsor return async_task( "gregui.mailutils.invite_guest.try_send_registration_mail", **{ "guest_name": f"{guest.first_name} {guest.last_name}", "guest_mail": email_address.value, "sponsor_id": sponsor.id, "sponsor_name": f"{sponsor.first_name} {sponsor.last_name}", "token": link.uuid, }, ) def try_send_registration_mail( guest_name: str, guest_mail: str, sponsor_id: int, sponsor_name: str, token: str, ): ig = InviteGuest() template = ig.get_template() context = Context( { "institution": settings.INSTANCE_NAME, "sponsor": sponsor_name, "registration_link": ig.make_registration_url(token), } ) try: mail.send_mail( subject=template.get_subject(context), message=template.get_body(context), from_email=template.from_email or None, recipient_list=[guest_mail], ) except SMTPRecipientsRefused: sp = Sponsor.objects.get(pk=sponsor_id) # TODO: Mark the invite in the frontend as bad if sp.work_email: ig.send_bad_email_notice( guest_name=guest_name, guest_mail=guest_mail, sponsor_mail=sp.work_email, )