import datetime
import pytz
from six import string_types
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.urls.base import reverse
from django.utils import timezone
from events.models import Event, Category, Service, ServiceInstance
EMAIL_KEY_START_END = settings.EMAIL_KEY_START_END
EMAIL_TARGET_START_END = settings.EMAIL_TARGET_START_END
DEFAULT_TO_ADDR = settings.DEFAULT_TO_ADDR
[docs]def send_survey_if_necessary(event):
"""
Check to see if a post-event survey should be sent for a particular event. If so, send an email to the client.
:param event: The event
"""
now = timezone.now()
if now < event.datetime_end or event.datetime_end < (now - datetime.timedelta(days=30)) or not event.approved \
or event.cancelled or event.survey_sent or not event.send_survey or event.contact is None:
return
email = SurveyEmailGenerator(event=event, subject='Post-event survey for {}'.format(event.event_name),
to_emails=event.contact.email)
email.send()
# set_revision_comment('Post-event survey sent.')
event.survey_sent = True
event.save()
[docs]def generate_web_service_email(details):
"""
Generate a generic email message with the Webmaster listed as the reply address
:param details: A dictionary - {'subject': <str>, 'message': <str>, 'email_to': <str>}
:returns: A generic LNL email object
"""
subject = details["subject"]
body = details["message"]
from_email = settings.DEFAULT_FROM_ADDR
reply_to_email = [settings.EMAIL_TARGET_W]
to_email = details["email_to"]
email = GenericEmailGenerator(subject=subject, to_emails=to_email, bcc=reply_to_email, from_email=from_email,
reply_to=reply_to_email, body=body, context={'mrkdwn': True})
return email
[docs]def generate_sms_email(data):
"""
Generate a plain SMS text message for delivery via email
:param data: A dictionary - {'message': <str>, 'user': <User>}
:returns: A basic (non-HTML) email object
"""
body = data["message"]
user = data["user"]
if user.carrier is None or user.carrier == "" or user.phone is None:
return None
to_email = ''.join(e for e in user.phone if e.isalnum()) + "@" + user.carrier
email = BasicEmailGenerator(to_emails=to_email, body=body)
return email
[docs]def generate_notice_email(notice):
"""
Generate a meeting notice email
:param notice: A MeetingNoticeMail object
:returns: An email object
"""
subject = notice.subject
from_email = settings.DEFAULT_FROM_ADDR
reply_to_email = settings.EMAIL_TARGET_S
to_email = notice.email_to.email
context = {'object': notice}
cont_html = render_to_string('emails/email_notice.html', context)
cont_text = render_to_string('emails/email_notice.txt', context)
email = EmailMultiAlternatives(subject, cont_text, from_email, [to_email], reply_to=[reply_to_email])
email.attach_alternative(cont_html, "text/html")
return email
[docs]def generate_notice_cc_email(notice):
"""
Generate a meeting notice email
:param notice: A MeetingNoticeMail object
:returns: An email object
"""
subject = notice.subject
from_email = settings.DEFAULT_FROM_ADDR
to_email = notice.email_to.email
context = {'object': notice}
cont_html = render_to_string('emails/email_notice_cc.html', context)
cont_text = render_to_string('emails/email_notice_cc.txt', context)
email = EmailMultiAlternatives(subject, cont_text, from_email, [to_email])
email.attach_alternative(cont_html, "text/html")
return email
[docs]def generate_transfer_email(orgtransfer):
"""
Generate an organization transfer email notification
:param orgtransfer: An OrganizationTransfer object
:returns: An email object
"""
subject = "LNL Organization Control Transfer for %s" % orgtransfer.org.name
from_email = settings.DEFAULT_FROM_ADDR
to_emails = [orgtransfer.old_user_in_charge.email, orgtransfer.org.exec_email]
to_emails = [e for e in to_emails if e is not None]
bcc = [settings.EMAIL_TARGET_W]
context = {'object': orgtransfer}
cont_html = render_to_string('emails/email_transfer.html', context)
cont_text = render_to_string('emails/email_transfer.txt', context)
email = EmailMultiAlternatives(subject, cont_text, from_email, to_emails, bcc=bcc)
email.attach_alternative(cont_html, "text/html")
return email
[docs]def generate_event_start_end_emails():
""" Send an email for events starting or ending now """
subj_start = "Events Starting Now"
subj_end = "Events Ending Now"
# get the time
unstripped = datetime.datetime.now(pytz.utc)
# get rids of the zeroes
now = unstripped.replace(second=0, microsecond=0)
# set the headers for majordomo, may need a : after the Approved
if EMAIL_KEY_START_END:
headers = {'Approved': EMAIL_KEY_START_END}
else:
headers = None
# for the start
starting = Event.objects.filter(approved=True, datetime_start=now)
ending = Event.objects.filter(approved=True, datetime_end=now)
from_email = settings.DEFAULT_FROM_ADDR
if starting:
context_start = {'events': starting, 'string': "Events Starting Now", 'stringtwo': ""}
content_start_txt = render_to_string('emails/email_start_end.txt', context_start)
content_start_html = render_to_string('emails/email_start_end.html', context_start)
email = EmailMultiAlternatives(subj_start, content_start_txt, from_email, [EMAIL_TARGET_START_END],
headers=headers)
email.attach_alternative(content_start_html, "text/html")
email.send()
elif ending:
context_end = {'events': ending, 'string': "Events Ending Now", 'stringtwo': "Please help Strike!"}
content_end_txt = render_to_string('emails/email_start_end.txt', context_end)
content_end_html = render_to_string('emails/email_start_end.html', context_end)
email = EmailMultiAlternatives(subj_end, content_end_txt, from_email, [EMAIL_TARGET_START_END], headers=headers)
email.attach_alternative(content_end_html, "text/html")
email.send()
# Cron Example
# * * * * * ~/bin/python ~/lnldb/manage.py send_start_end
# Self Service Emails
# Self service org email
[docs]def generate_selfservice_notice_email(context):
"""
Generate an email notification when a new client submits a self-service request
:param context: Self-service form data
:returns: An email object
"""
subject = "Self Service Form Submission"
from_email = settings.DEFAULT_FROM_ADDR
to_email = [settings.EMAIL_TARGET_W, settings.EMAIL_TARGET_VP]
cont_html = render_to_string('emails/email_selfservice.html', context)
cont_text = render_to_string('emails/email_selfservice.txt', context)
email = EmailMultiAlternatives(subject, cont_text, from_email, to_email)
email.attach_alternative(cont_html, "text/html")
return email
# Self service member email (deprecated)
# def generate_selfmember_notice_email(context):
# subject = "Self Service Member Request Submission"
# from_email = settings.DEFAULT_FROM_ADDR
# to_email = settings.EMAIL_TARGET_S
#
# cont_html = render_to_string('emails/email_selfmember.html', context)
# cont_text = render_to_string('emails/email_selfmember.txt', context)
#
# email = EmailMultiAlternatives(subject, cont_text, from_email, [to_email])
# email.attach_alternative(cont_html, "text/html")
#
# return email
[docs]def generate_poke_cc_email_content(services, message):
"""
Generate the body of a "Poke for CC" email notification
:param services: An array or queryset of services crew chiefs are needed for
:param message: Additional message to display above the event details (Optional, but highly recommended)
:returns: HTML formatted string
"""
event_details = ""
events = []
for service in services:
service = ServiceInstance.objects.get(pk=service)
if service.event not in events:
events.append(service.event)
for event in events:
categories = Category.objects.filter(service__serviceinstance__in=services,
service__serviceinstance__event=event).distinct()
details = Service.objects.filter(serviceinstance__in=services, serviceinstance__event=event)
ccs_needed = []
service_details = []
for category in categories:
ccs_needed.append(category.name)
for service in details:
service_details.append(service.longname)
ccs_needed = ', '.join(ccs_needed)
service_details = ', '.join(service_details)
link = "http://" + settings.ALLOWED_HOSTS[0] + reverse("events:detail", args=[event.id])
start = timezone.localtime(event.datetime_start)
end = timezone.localtime(event.datetime_end)
if start.date() == end.date():
when = start.strftime("%A (%-m/%-d) %-I:%M %p - ") + end.strftime("%-I:%M %p")
else:
when = start.strftime("%A (%-m/%-d) %-I:%M %p to ") + end.strftime("%A (%-m/%-d) %-I:%M %p")
setup = timezone.localtime(event.datetime_setup_complete).strftime("%A (%-m/%-d) %-I:%M %p")
event_details += "<strong>CC's needed:</strong> %s\n<strong>Services:</strong> %s\n<strong>What:</strong> " \
"<a href='%s'>%s</a>\n<strong>When:</strong> %s\n<strong>Setup by:</strong> %s\n" \
"<strong>Where:</strong> %s\n<strong>Description:</strong> %s\n\n" % \
(ccs_needed, service_details, link, event.event_name, when, setup, event.location.name,
event.description)
body = message + "<hr>" + event_details
return body
[docs]class DefaultLNLEmailGenerator(object): # yay classes
def __init__(self,
subject="LNL Notice",
to_emails=settings.DEFAULT_TO_ADDR,
cc=None,
bcc=None,
from_email=settings.DEFAULT_FROM_ADDR,
reply_to=None,
context=None,
template_basename="emails/email_generic",
build_html=True,
body=None,
attachments=None):
if isinstance(to_emails, string_types):
to_emails = [to_emails]
if context is None:
context = {}
if attachments is None:
attachments = []
context['subject'] = subject
if body:
context['body'] = body
template_txt = "%s.txt" % template_basename
content_txt = render_to_string(template_txt, context)
self.email = EmailMultiAlternatives(subject, content_txt, from_email, to_emails, bcc=bcc, cc=cc,
reply_to=reply_to)
for a in attachments:
if a['file_handle']:
self.email.attach(a['name'], a['file_handle'], "application/pdf")
else:
self.email.attach(a)
if build_html:
template_html = "%s.html" % template_basename
content_html = render_to_string(template_html, context)
self.email.attach_alternative(content_html, "text/html")
[docs] def send(self):
self.email.send()
[docs]class EventEmailGenerator(DefaultLNLEmailGenerator):
def __init__(self,
event=None,
subject="LNL Event",
to_emails=settings.DEFAULT_TO_ADDR,
cc=None,
bcc=None,
from_email=settings.DEFAULT_FROM_ADDR,
reply_to=None,
context=None,
template_basename="emails/email_event",
build_html=True,
body=None,
attachments=None):
if context is None:
context = {}
context['event'] = event
super(EventEmailGenerator, self).__init__(
subject=subject,
to_emails=to_emails,
cc=cc,
bcc=bcc,
from_email=from_email,
reply_to=reply_to,
context=context,
template_basename=template_basename,
build_html=build_html,
body=body,
attachments=attachments)
[docs]class CcAddEmailGenerator(DefaultLNLEmailGenerator):
def __init__(self,
ccinstance=None,
subject="Crew Chief Add Notification",
to_emails=None,
cc=None,
bcc=None,
from_email=settings.DEFAULT_FROM_ADDR,
reply_to=None,
context=None,
template_basename="emails/email_ccadd",
build_html=True,
attachments=None):
if to_emails is None:
to_emails = [ccinstance.crew_chief.email]
if context is None:
context = {}
context['ccinstance'] = ccinstance
super(CcAddEmailGenerator, self).__init__(
subject=subject,
to_emails=to_emails,
cc=cc,
bcc=bcc,
from_email=from_email,
reply_to=reply_to,
context=context,
template_basename=template_basename,
build_html=build_html,
body=None,
attachments=attachments)
[docs]class ReportReminderEmailGenerator(DefaultLNLEmailGenerator):
def __init__(self,
reminder=None,
subject="LNL Crew Chief Report Reminder Email",
to_emails=None,
cc=None,
bcc=None,
from_email=settings.DEFAULT_FROM_ADDR,
reply_to=None,
context=None,
template_basename="emails/email_reportreminder",
build_html=True,
attachments=None):
if to_emails is None:
to_emails = [reminder.crew_chief.email]
if context is None:
context = {}
context['reminder'] = reminder
super(ReportReminderEmailGenerator, self).__init__(
subject=subject,
to_emails=to_emails,
cc=cc,
bcc=bcc,
from_email=from_email,
reply_to=reply_to,
context=context,
template_basename=template_basename,
build_html=build_html,
body=None,
attachments=attachments)
[docs]class BillingEmailGenerator(DefaultLNLEmailGenerator):
def __init__(self,
event=None,
subject="Invoice for LNL Services",
to_emails=settings.DEFAULT_TO_ADDR,
cc=None,
bcc=[settings.EMAIL_TARGET_T],
from_email=settings.DEFAULT_FROM_ADDR,
reply_to=[settings.EMAIL_TARGET_T],
context=None,
template_basename="emails/email_billing",
build_html=True,
body=None,
attachments=None):
if context is None:
context = {}
context['event'] = event
super(BillingEmailGenerator, self).__init__(
subject=subject,
to_emails=to_emails,
cc=cc,
bcc=bcc,
from_email=from_email,
reply_to=reply_to,
context=context,
template_basename=template_basename,
build_html=build_html,
body=body,
attachments=attachments)
[docs]class SurveyEmailGenerator(DefaultLNLEmailGenerator):
def __init__(self,
event=None,
subject="Post-event survey for your recent event",
to_emails=settings.DEFAULT_TO_ADDR,
cc=None,
bcc=[settings.EMAIL_TARGET_VP_DB],
from_email=settings.DEFAULT_FROM_ADDR,
reply_to=None,
context=None,
template_basename="emails/email_survey",
build_html=True,
attachments=None):
if context is None:
context = {}
context['event'] = event
super(SurveyEmailGenerator, self).__init__(
subject=subject,
to_emails=to_emails,
cc=cc,
bcc=bcc,
from_email=from_email,
reply_to=reply_to,
context=context,
template_basename=template_basename,
build_html=build_html,
body=None,
attachments=attachments)
[docs]class GenericEmailGenerator(DefaultLNLEmailGenerator):
def __init__(self,
subject=None,
to_emails=settings.DEFAULT_TO_ADDR,
cc=None,
bcc=None,
from_email=settings.DEFAULT_FROM_ADDR,
reply_to=None,
context=None,
build_html=True,
body=None,
attachments=None):
if context is None:
context = {}
super(GenericEmailGenerator, self).__init__(
subject=subject,
to_emails=to_emails,
cc=cc,
bcc=bcc,
from_email=from_email,
reply_to=reply_to,
context=context,
template_basename="emails/email_generic",
build_html=build_html,
body=body,
attachments=attachments
)
[docs]class BasicEmailGenerator(object):
""" Non-HTML email with no LNL branding or formatting. Uses no-reply address by default. """
def __init__(self, to_emails=settings.DEFAULT_TO_ADDR, from_email=settings.EMAIL_FROM_NOREPLY, reply_to=None,
bcc=None, context=None, template_basename="emails/email_basic", body=None):
if isinstance(to_emails, string_types):
to_emails = [to_emails]
if context is None:
context = {}
if body:
context['body'] = body
template_txt = "%s.txt" % template_basename
content_txt = render_to_string(template_txt, context)
subject = ""
self.email = EmailMultiAlternatives(subject, content_txt, from_email, to_emails, bcc=bcc, reply_to=reply_to)
[docs] def send(self):
self.email.send()