def send_team_invitation_email(team, email, organizer): """ Send email to new or existing facilitators """ """ organizer should be a User object """ user_qs = User.objects.filter(email__iexact=email) context = { "team": team, "organizer": organizer, } if user_qs.count() == 0: # invite user to join subject = render_to_string_ctx( 'studygroups/email/new_facilitator_invite-subject.txt', context).strip('\n') html_body = render_html_with_css( 'studygroups/email/new_facilitator_invite.html', context) text_body = render_to_string_ctx( 'studygroups/email/new_facilitator_invite.txt', context) else: context['user'] = user_qs.get() subject = render_to_string_ctx( 'studygroups/email/team_invite-subject.txt', context).strip('\n') html_body = render_html_with_css('studygroups/email/team_invite.html', context) text_body = render_to_string_ctx('studygroups/email/team_invite.txt', context) to = [email] from_ = organizer.email msg = EmailMultiAlternatives(subject, text_body, from_, to) msg.attach_alternative(html_body, 'text/html') msg.send()
def send_weekly_update(): today = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0) start_time = today - datetime.timedelta( days=today.weekday() + 7) #start of previous week end_time = start_time + datetime.timedelta(days=7) context = { 'start_time': start_time, 'end_time': end_time, 'email': True, } for team in Team.objects.all(): report_context = report_data(start_time, end_time, team) # If there wasn't any activity during this period discard the update if report_context['active'] is False: continue report_context.update(context) timezone.activate(pytz.timezone( settings.TIME_ZONE)) #TODO not sure what this influences anymore? translation.activate(settings.LANGUAGE_CODE) html_body = render_html_with_css( 'studygroups/email/weekly-update.html', report_context) text_body = html_body_to_text(html_body) timezone.deactivate() to = [ member.user.email for member in team.teammembership_set.active().filter( weekly_update_opt_in=True) ] staff = [o.email for o in User.objects.filter(is_staff=True)] update = EmailMultiAlternatives(_('Weekly team update for {}'.format( team.name)), text_body, settings.DEFAULT_FROM_EMAIL, cc=to, bcc=staff) update.attach_alternative(html_body, 'text/html') update.send() # send weekly update to staff report_context = report_data(start_time, end_time) report_context.update(context) timezone.activate(pytz.timezone(settings.TIME_ZONE)) translation.activate(settings.LANGUAGE_CODE) html_body = render_html_with_css('studygroups/email/weekly-update.html', report_context) text_body = html_body_to_text(html_body) timezone.deactivate() to = [o.email for o in User.objects.filter(is_staff=True)] update = EmailMultiAlternatives(_('Weekly learning circles update'), text_body, settings.DEFAULT_FROM_EMAIL, to) update.attach_alternative(html_body, 'text/html') update.send()
def send_optout_message(self): email = self.cleaned_data.get('email') mobile = self.cleaned_data.get('mobile') if email: for application in Application.objects.active().filter(email__iexact=email): # send opt-out email context = { 'application': application } subject = render_to_string_ctx('studygroups/email/optout_confirm-subject.txt', context).strip('\n') html_body = render_html_with_css('studygroups/email/optout_confirm.html', context) text_body = render_to_string_ctx('studygroups/email/optout_confirm.txt', context) notification = EmailMultiAlternatives(subject, text_body, settings.DEFAULT_FROM_EMAIL, [application.email]) notification.attach_alternative(html_body, 'text/html') notification.send() # Find all signups with mobile with email and delete if mobile: applications = Application.objects.active().filter(mobile=mobile) if email: # don't send text to applications with a valid email in opt out form applications = applications.exclude(email__iexact=email) for application in applications: # This remains for old signups without email address context = { 'application': application } message = render_to_string_ctx('studygroups/email/optout_confirm_text.txt', context) try: send_message(application.mobile, message) except twilio.TwilioRestException as e: logger.exception("Could not send text message to %s", to, exc_info=e) application.delete()
def handle_new_study_group_creation(sender, instance, created, **kwargs): if not created: return study_group = instance context = { 'study_group': study_group, } subject = render_to_string_ctx( 'studygroups/email/learning_circle_created-subject.txt', context).strip(' \n') html_body = render_html_with_css( 'studygroups/email/learning_circle_created.html', context) text_body = html_body_to_text(html_body) # on all learning circles, CC p2pu cc = [settings.TEAM_EMAIL] # if the user is part of a team, send to the organizer(s) cc += [o.email for o in get_study_group_organizers(study_group)] # if there is a question, send to the welcoming comitte if study_group.facilitator_concerns: cc += [settings.COMMUNITY_MANAGER] notification = EmailMultiAlternatives( subject, text_body, settings.DEFAULT_FROM_EMAIL, [study_group.facilitator.email], cc=cc, reply_to=[study_group.facilitator.email] + cc) notification.attach_alternative(html_body, 'text/html') notification.send()
def send_community_digest(start_date, end_date): context = community_digest_data(start_date, end_date) chart_data = { "meetings_chart": charts.LearningCircleMeetingsChart( end_date.date()).generate(output="png"), "countries_chart": charts.LearningCircleCountriesChart( start_date.date(), end_date.date()).generate(output="png"), "top_topics_chart": charts.TopTopicsChart( end_date.date(), context['studygroups_that_met']).generate(output="png"), } context.update(chart_data) subject = render_to_string_ctx( 'studygroups/email/community_digest-subject.txt', context) html_body = render_html_with_css('studygroups/email/community_digest.html', context) text_body = html_body_to_text(html_body) to = [settings.COMMUNITY_DIGEST_EMAIL] msg = EmailMultiAlternatives(subject, text_body, settings.DEFAULT_FROM_EMAIL, to) msg.attach_alternative(html_body, 'text/html') msg.send()
def send_email_confirm_email(user): context = { "user": user, "profile": user.profile, "uid": urlsafe_base64_encode(force_bytes(user.pk)), "token": generate_user_token(user), } subject_template = 'custom_registration/email_confirm-subject.txt' email_template = 'custom_registration/email_confirm.txt' html_email_template = 'custom_registration/email_confirm.html' subject = render_to_string_ctx(subject_template, context).strip(' \n') text_body = render_to_string_ctx(email_template, context) html_body = render_html_with_css(html_email_template, context) to = [user.email] email = EmailMultiAlternatives( subject, text_body, settings.DEFAULT_FROM_EMAIL, to, ) email.attach_alternative(html_body, 'text/html') email.send()
def generate_reminder(study_group): now = timezone.now() next_meeting = study_group.next_meeting() # TODO reminder generation code should be moved to models, only sending facilitator notification should be here if next_meeting and next_meeting.meeting_datetime( ) - now < datetime.timedelta(days=4): # check if a notifcation already exists for this meeting if not Reminder.objects.filter( study_group=study_group, study_group_meeting=next_meeting).exists(): reminder = Reminder() reminder.study_group = study_group reminder.study_group_meeting = next_meeting context = { 'facilitator': study_group.facilitator, 'study_group': study_group, 'next_meeting': next_meeting, 'reminder': reminder, } previous_meeting = study_group.meeting_set.filter( meeting_date__lt=next_meeting.meeting_date).order_by( 'meeting_date').last() if previous_meeting and previous_meeting.feedback_set.first(): context['feedback'] = previous_meeting.feedback_set.first() timezone.activate(pytz.timezone(study_group.timezone)) with use_language(study_group.language): reminder.email_subject = render_to_string_ctx( 'studygroups/email/reminder-subject.txt', context).strip('\n') reminder.email_body = render_to_string_ctx( 'studygroups/email/reminder.txt', context) reminder.sms_body = render_to_string_ctx( 'studygroups/email/sms.txt', context) # TODO - handle SMS reminders that are too long if len(reminder.sms_body) > 160: logger.error('SMS body too long: ' + reminder.sms_body) reminder.sms_body = reminder.sms_body[:160] reminder.save() with use_language(reminder.study_group.language): facilitator_notification_subject = _( 'A reminder for %(studygroup_name)s was generated' % {"studygroup_name": study_group.name}) facilitator_notification_html = render_html_with_css( 'studygroups/email/reminder_notification.html', context) facilitator_notification_txt = render_to_string_ctx( 'studygroups/email/reminder_notification.txt', context) timezone.deactivate() to = [study_group.facilitator.email] notification = EmailMultiAlternatives( facilitator_notification_subject, facilitator_notification_txt, settings.DEFAULT_FROM_EMAIL, to) notification.attach_alternative(facilitator_notification_html, 'text/html') notification.send()
def handle_new_application(sender, instance, created, **kwargs): """ Send welcome message to learner introducing them to their facilitator """ if not created: return application = instance # get a random piece of advice # TODO remove unused advice logic advice = None if application.study_group.language == 'en': advice = Advice.objects.order_by('?').first() # activate language and timezone for message reminder with use_language(application.study_group.language), timezone.override(pytz.timezone(application.study_group.timezone)): # Send welcome message to learner learner_signup_subject = render_to_string_ctx( 'studygroups/email/learner_signup-subject.txt', { 'application': application, 'advice': advice, } ).strip('\n') learner_signup_html = render_html_with_css( 'studygroups/email/learner_signup.html', { 'application': application, 'advice': advice, } ) learner_signup_body = html_body_to_text(learner_signup_html) to = [application.email] # CC facilitator and put in reply-to welcome_message = EmailMultiAlternatives( learner_signup_subject, learner_signup_body, settings.DEFAULT_FROM_EMAIL, to, cc=[application.study_group.facilitator.email], reply_to=[application.study_group.facilitator.email] ) welcome_message.attach_alternative(learner_signup_html, 'text/html') welcome_message.send()
def send_new_user_email(user): context = { "user": user, } subject_template = 'custom_registration/new_user_confirmed-subject.txt' html_email_template = 'custom_registration/new_user_confirmed.html' subject = render_to_string_ctx(subject_template, context).strip(' \n') html_body = render_html_with_css(html_email_template, context) text_body = html_body_to_text(html_body) to = [user.email] email = EmailMultiAlternatives( subject, text_body, settings.DEFAULT_FROM_EMAIL, to, ) email.attach_alternative(html_body, 'text/html') email.send()
def _send_learning_circle_insights(study_group): timezone.deactivate() goals_met_chart = charts.GoalsMetChart(study_group) report_path = reverse('studygroups_final_report', kwargs={'study_group_id': study_group.id}) recipients = study_group.application_set.active().values_list('email', flat=True) organizers = get_study_group_organizers(study_group) organizers_emails = [organizer.email for organizer in organizers] to = list(recipients) + organizers_emails to.append(study_group.facilitator.email) context = { 'study_group': study_group, 'report_path': report_path, 'facilitator_name': study_group.facilitator.first_name, 'registrations': study_group.application_set.active().count(), 'survey_responses': study_group.learnersurveyresponse_set.count(), 'goals_met_chart': goals_met_chart.generate(output="png"), 'learner_goals_chart': charts.goals_chart(study_group), } subject = render_to_string_ctx( 'studygroups/email/learning_circle_final_report-subject.txt', context).strip('\n') html = render_html_with_css( 'studygroups/email/learning_circle_final_report.html', context) txt = html_body_to_text(html) notification = EmailMultiAlternatives( subject, txt, settings.DEFAULT_FROM_EMAIL, bcc=to, reply_to=[study_group.facilitator.email]) notification.attach_alternative(html, 'text/html') notification.send()
def send_contact_form_inquiry(email, name, content, source, organization=None): context = { "email": email, "name": name, "content": content, "source": source, "organization": organization, } subject_template = 'contact/contact_email-subject.txt' html_email_template = 'contact/contact_email.html' subject = render_to_string_ctx(subject_template, context).strip(' \n') html_body = render_html_with_css(html_email_template, context) text_body = html_body_to_text(html_body) to = [settings.TEAM_EMAIL] email = EmailMultiAlternatives(subject, text_body, settings.DEFAULT_FROM_EMAIL, to, cc=[settings.SUPPORT_EMAIL], reply_to=[email, settings.SUPPORT_EMAIL]) email.attach_alternative(html_body, 'text/html') email.send()