def send_external_join_confirmation(group_pk, email, **kwargs): try: group = SupportGroup.objects.get(pk=group_pk) except SupportGroup.DoesNotExist: return subscription_token = subscription_confirmation_token_generator.make_token( email=email, **kwargs) confirm_subscription_url = front_url("external_join_group", args=[group_pk], auto_login=False) query_args = {"email": email, **kwargs, "token": subscription_token} confirm_subscription_url += "?" + urlencode(query_args) bindings = { "GROUP_NAME": group.name, "JOIN_LINK": confirm_subscription_url } send_mosaico_email( code="GROUP_EXTERNAL_JOIN_OPTIN", subject=_(f"Confirmez que vous souhaitez rejoindre « {group.name} »"), from_email=settings.EMAIL_FROM, recipients=[email], bindings=bindings, )
def send_joined_notification_email(membership_pk): membership = Membership.objects.select_related( "person", "supportgroup").get(pk=membership_pk) person_information = str(membership.person) recipients = Person.objects.filter( notification_subscriptions__membership__supportgroup=membership. supportgroup, notification_subscriptions__membership__membership_type__gte=Membership .MEMBERSHIP_TYPE_MANAGER, notification_subscriptions__type=Subscription.SUBSCRIPTION_EMAIL, notification_subscriptions__activity_type=Activity.TYPE_NEW_MEMBER, ) if len(recipients) == 0: return bindings = { "GROUP_NAME": membership.supportgroup.name, "PERSON_INFORMATION": person_information, "MANAGE_GROUP_LINK": front_url("manage_group", kwargs={"pk": membership.supportgroup.pk}), } send_mosaico_email( code="GROUP_SOMEONE_JOINED_NOTIFICATION", subject="Un nouveau membre dans votre groupe", from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, )
def send_post_event_required_documents_reminder_email(event_pk): event = Event.objects.select_related("subtype").get(pk=event_pk) organizers = event.organizers.all() document_deadline = event.end_time + timedelta(days=15) bindings = { "EVENT_NAME": event.name, "DOCUMENTS_LINK": front_url("event_project", auto_login=False, kwargs={"pk": event.pk}), "DOCUMENT_DEADLINE": document_deadline.strftime("%d/%m"), "REQUIRED_DOCUMENT_TYPES": event.subtype.required_documents, "NEEDS_DOCUMENTS": len(event.subtype.required_documents) > 0, } send_mosaico_email( code="POST_EVENT_REQUIRED_DOCUMENTS_REMINDER", subject=_("Rappel : envoyez les justificatifs de l'événement d'hier"), from_email=settings.EMAIL_FROM, recipients=[organizer for organizer in organizers], bindings=bindings, )
def send_someone_joined_notification(membership_pk): try: membership = Membership.objects.select_related( "person", "supportgroup").get(pk=membership_pk) except Membership.DoesNotExist: return person_information = str(membership.person) managers_filter = (Q( membership_type__gte=Membership.MEMBERSHIP_TYPE_MANAGER)) & Q( notifications_enabled=True) managing_membership = ( membership.supportgroup.memberships.filter(managers_filter). select_related("person").prefetch_related("person__emails")) recipients = [membership.person for membership in managing_membership] bindings = { "GROUP_NAME": membership.supportgroup.name, "PERSON_INFORMATION": person_information, "MANAGE_GROUP_LINK": front_url("manage_group", kwargs={"pk": membership.supportgroup.pk}), } send_mosaico_email( code="GROUP_SOMEONE_JOINED_NOTIFICATION", subject=_("Un nouveau membre dans votre groupe d'action"), from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, )
def send_event_report(event_pk): event = Event.objects.get(pk=event_pk) if event.report_summary_sent: return recipients = event.attendees.filter( notification_subscriptions__type=Subscription.SUBSCRIPTION_EMAIL, notification_subscriptions__activity_type=Activity.TYPE_NEW_REPORT, notification_subscriptions__membership__supportgroup__in=event. organizers_groups.all(), ) if len(recipients) == 0: return bindings = { "EVENT_NAME": event.name, "EVENT_REPORT_SUMMARY": sanitize_html(str_summary(event.report_content, length_max=500)), "EVENT_REPORT_LINK": front_url("view_event", kwargs={"pk": event_pk}), } send_mosaico_email( code="EVENT_REPORT", subject=f"Compte-rendu de l'événement {event.name}", from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, ) event.report_summary_sent = True event.save()
def send_cancellation_notification(event_pk): event = Event.objects.get(pk=event_pk) # check it is indeed cancelled if event.visibility != Event.VISIBILITY_ADMIN: return event_name = event.name recipients = [ rsvp.person for rsvp in event.rsvps.prefetch_related("person__emails") ] bindings = {"EVENT_NAME": event_name} send_mosaico_email( code="EVENT_CANCELLATION", subject=_("Un événement auquel vous participiez a été annulé"), from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, ) Activity.objects.bulk_create( [ Activity( type=Activity.TYPE_CANCELLED_EVENT, recipient=r, event=event, ) for r in recipients ], send_post_save_signal=True, )
def send_support_group_creation_notification(membership_pk): try: membership = Membership.objects.select_related("supportgroup", "person").get( pk=membership_pk ) except Membership.DoesNotExist: return group = membership.supportgroup referent = membership.person bindings = { "group_name": group.name, "GROUP_LINK": front_url( "view_group", auto_login=False, kwargs={"pk": group.pk} ), "MANAGE_GROUP_LINK": front_url("manage_group", kwargs={"pk": group.pk}), } send_mosaico_email( code="GROUP_CREATION", subject="Les informations de votre " + ("nouvelle équipe" if group.is_2022 else "nouveau groupe"), from_email=settings.EMAIL_FROM, recipients=[referent], bindings=bindings, )
def send_secretariat_notification(event_pk, person_pk, complete=True): try: event = Event.objects.get(pk=event_pk) person = Person.objects.get(pk=person_pk) except (Event.DoesNotExist, Person.DoesNotExist): return from agir.events.admin import EventAdmin bindings = { "EVENT_NAME": event.name, "EVENT_SCHEDULE": event.get_display_date(), "CONTACT_NAME": event.contact_name, "CONTACT_EMAIL": event.contact_email, "CONTACT_PHONE": event.contact_phone, "LOCATION_NAME": event.location_name, "LOCATION_ADDRESS": event.short_address, "EVENT_LINK": front_url("view_event", args=[event.pk]), "LEGAL_INFORMATIONS": EventAdmin.legal_informations(event), } send_mosaico_email( code="EVENT_SECRETARIAT_NOTIFICATION", subject=_( f"Événement {'complété' if complete else 'en attente'} : {str(event)}" ), from_email=settings.EMAIL_FROM, reply_to=[person.email], recipients=[settings.EMAIL_SECRETARIAT], bindings=bindings, )
def send_donation_email(person_pk, payment_type): person = Person.objects.prefetch_related("emails").get(pk=person_pk) template_code = "DONATION_MESSAGE" email_from = settings.EMAIL_FROM if ( payment_type in PAYMENT_TYPES and hasattr(PAYMENT_TYPES[payment_type], "email_from") and PAYMENT_TYPES[payment_type].email_from ): email_from = PAYMENT_TYPES[payment_type].email_from if ( payment_type in PAYMENT_TYPES and hasattr(PAYMENT_TYPES[payment_type], "email_template_code") and PAYMENT_TYPES[payment_type].email_template_code ): template_code = PAYMENT_TYPES[payment_type].email_template_code send_mosaico_email( code=template_code, subject="Merci d'avoir donné !", from_email=email_from, bindings={"PROFILE_LINK": front_url("personal_information")}, recipients=[person], )
def send_contract_confirmation_email(payment_id): payment = Payment.objects.get(id=payment_id) person = payment.person if "contract_path" not in payment.meta: raise RuntimeError( "Contrat non généré pour le paiement {}".format(repr(payment)) ) full_name = f'{payment.meta["first_name"]} {payment.meta["last_name"]}' with open( Path(settings.MEDIA_ROOT) / payment.meta["contract_path"], mode="rb" ) as contract: send_mosaico_email( code="CONTRACT_CONFIRMATION", subject="Votre contrat de prêt", from_email=settings.EMAIL_FROM, bindings={ "CHER_PRETEUR": SUBSTITUTIONS["cher_preteur"][payment.meta["gender"]] }, recipients=[person], attachments=[ { "filename": f"contrat_pret_{slugify(full_name, only_ascii=True)}.pdf", "content": contract.read(), "mimetype": "application/pdf", } ], )
def send_joined_notification_email(membership_pk): try: membership = Membership.objects.select_related("person", "supportgroup").get( pk=membership_pk ) except Membership.DoesNotExist: return person_information = str(membership.person) bindings = { "GROUP_NAME": membership.supportgroup.name, "PERSON_INFORMATION": person_information, "MANAGE_GROUP_LINK": front_url( "manage_group", kwargs={"pk": membership.supportgroup.pk} ), } send_mosaico_email( code="GROUP_SOMEONE_JOINED_NOTIFICATION", subject="Un nouveau membre dans votre " + ("équipe" if membership.supportgroup.is_2022 else "groupe"), from_email=settings.EMAIL_FROM, recipients=membership.supportgroup.managers, bindings=bindings, )
def send_no_account_email(email): send_mosaico_email( code="LOGIN_SIGN_UP_MESSAGE", subject="Vous n'avez pas encore de compte sur la plateforme", from_email=settings.EMAIL_FROM, recipients=[email], )
def send_confirmation_change_email(new_email, user_pk, **kwargs): try: Person.objects.get(pk=user_pk) except Person.DoesNotExist: return subscription_token = add_email_confirmation_token_generator.make_token( new_email=new_email, user=user_pk) query_args = { "new_email": new_email, "user": user_pk, "token": subscription_token, **kwargs, } confirm_change_mail_url = front_url("confirm_change_mail", query=query_args, auto_login=False) send_mosaico_email( code="CHANGE_MAIL_CONFIRMATION", subject="Confirmez votre changement d'adresse", from_email=settings.EMAIL_FROM, recipients=[new_email], bindings={"CONFIRMATION_URL": confirm_change_mail_url}, )
def send_monthly_donation_confirmation_email( email, confirmation_view_name="monthly_donation_confirm", **kwargs ): query_params = { "email": email, **{k: v for k, v in kwargs.items() if v is not None}, } query_params["token"] = monthly_donation_confirmation_token_generator.make_token( **query_params ) confirmation_link = front_url(confirmation_view_name, query=query_params) from_email = "La France insoumise <*****@*****.**>" template_email = "CONFIRM_SUBSCRIPTION_LFI" if ( "payment_mode" in query_params and query_params["payment_mode"] is not None and "2022" in query_params["payment_mode"] ): from_email = "Mélenchon 2022 <*****@*****.**>" template_email = "CONFIRM_SUBSCRIPTION_2022" send_mosaico_email( code=template_email, subject="Finalisez votre don mensuel", from_email=from_email, bindings={"CONFIRM_SUBSCRIPTION_LINK": confirmation_link}, recipients=[email], )
def send_refused_group_coorganization_invitation_notification( invitation_id, recipient_ids): invitation = Invitation.objects.get(pk=invitation_id) event = invitation.event group = invitation.group # Notify current event referents recipients = event.organizers.filter(pk__in=recipient_ids) subject = f"{group.name} a refusé de co-organiser {event.name}" bindings = { "TITLE": subject, "EVENT_NAME": event.name, "GROUP_NAME": group.name, "DATE": now(), } send_mosaico_email( code="EVENT_GROUP_COORGANIZATION_REFUSED", subject=subject, from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, )
def send_message_notification_email(message_pk): message = SupportGroupMessage.objects.get(pk=message_pk) memberships = message.supportgroup.memberships.filter( membership_type__gte=message.required_membership_type) recipients = Person.objects.filter( id__in=memberships.values_list("person_id", flat=True)) recipients_id = [recipient.id for recipient in recipients] recipients = Person.objects.exclude(id=message.author.id).filter( id__in=recipients_id, notification_subscriptions__membership__supportgroup=message. supportgroup, notification_subscriptions__type=Subscription.SUBSCRIPTION_EMAIL, notification_subscriptions__activity_type=Activity.TYPE_NEW_MESSAGE, ) if len(recipients) == 0: return # Get membership to display author status membership_type = None membership = Membership.objects.filter(person=message.author, supportgroup=message.supportgroup) if membership.exists(): membership_type = membership.first().membership_type author_status = genrer_membership(message.author.gender, membership_type) bindings = { "MESSAGE_HTML": format_html_join("", "<p>{}</p>", ((p, ) for p in message.text.split("\n"))), "DISPLAY_NAME": message.author.display_name, "MESSAGE_LINK": front_url("user_message_details", kwargs={"pk": message_pk}), "AUTHOR_STATUS": format_html( '{} de <a href="{}">{}</a>', author_status, front_url("view_group", args=[message.supportgroup.pk]), message.supportgroup.name, ), } if message.subject: subject = message.subject else: subject = f"Nouveau message de {message.author.display_name}" subject = clean_subject_email(subject) send_mosaico_email( code="NEW_MESSAGE", subject=subject, from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, )
def send_membership_transfer_alert(bindings, recipient_pk): recipient = Person.objects.get(pk=recipient_pk) send_mosaico_email( code="TRANSFER_ALERT", subject=f"Notification de changement de groupe", from_email=settings.EMAIL_FROM, recipients=[recipient], bindings=bindings, )
def send_membership_transfer_sender_confirmation(bindings, recipients_pks): recipients = Person.objects.filter(pk__in=recipients_pks) send_mosaico_email( code="TRANSFER_SENDER", subject=f"{bindings['MEMBER_COUNT']} membres ont bien été transférés", from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, )
def send_membership_transfer_receiver_confirmation(bindings, recipients_pks): recipients = Person.objects.filter(pk__in=recipients_pks) send_mosaico_email( code="TRANSFER_RECEIVER", subject=f"De nouveaux membres ont été transferés dans {bindings['GROUP_DESTINATION']}", from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, )
def invite_to_group(group_id, invited_email, inviter_id): try: group = SupportGroup.objects.get(pk=group_id) except SupportGroup.DoesNotExist: return try: person = Person.objects.get_by_natural_key(invited_email) except Person.DoesNotExist: person = None group_name = group.name report_url = make_abusive_invitation_report_link(group_id, inviter_id) invitation_token = make_subscription_token(email=invited_email, group_id=group_id) join_url = front_url( "invitation_with_subscription_confirmation", query={ "email": invited_email, "group_id": group_id, "token": invitation_token, }, ) if person: Activity.objects.create( type=Activity.TYPE_GROUP_INVITATION, recipient=person, supportgroup=group, meta={"joinUrl": join_url}, ) else: invitation_token = make_subscription_token( email=invited_email, group_id=group_id ) join_url = front_url( "invitation_with_subscription_confirmation", query={ "email": invited_email, "group_id": group_id, "token": invitation_token, }, ) send_mosaico_email( code="GROUP_INVITATION_WITH_SUBSCRIPTION_MESSAGE", subject="Vous avez été invité⋅e à rejoindre la France insoumise", from_email=settings.EMAIL_FROM, recipients=[invited_email], bindings={ "GROUP_NAME": group_name, "CONFIRMATION_URL": join_url, "REPORT_URL": report_url, }, )
def send_welcome_mail(person_pk, type): person = Person.objects.prefetch_related("emails").get(pk=person_pk) message_info = SUBSCRIPTIONS_EMAILS[type].get("welcome") if message_info: send_mosaico_email( code=message_info.code, subject=message_info.subject, from_email=message_info.from_email, bindings={"PROFILE_LINK": front_url("personal_information")}, recipients=[person], )
def send_support_group_changed_notification(support_group_pk, changed_data): try: group = SupportGroup.objects.get(pk=support_group_pk, published=True) except SupportGroup.DoesNotExist: return changed_categories = { NOTIFIED_CHANGES[f] for f in changed_data if f in NOTIFIED_CHANGES } if not changed_categories: return for r in group.members.all(): Activity.objects.create( type=Activity.TYPE_GROUP_INFO_UPDATE, recipient=r, supportgroup=group, meta={"changed_data": [f for f in changed_data if f in NOTIFIED_CHANGES]}, ) change_descriptions = [ desc for id, desc in CHANGE_DESCRIPTION.items() if id in changed_categories ] change_fragment = render_to_string( template_name="lib/list_fragment.html", context={"items": change_descriptions} ) bindings = { "GROUP_NAME": group.name, "GROUP_CHANGES": change_fragment, "GROUP_LINK": front_url("view_group", kwargs={"pk": support_group_pk}), } notifications_enabled = Q(notifications_enabled=True) & Q( person__group_notifications=True ) recipients = [ membership.person for membership in group.memberships.filter( notifications_enabled ).prefetch_related("person__emails") ] send_mosaico_email( code="GROUP_CHANGED", subject=_("Les informations de votre groupe d'action ont été changées"), from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, )
def send_unsubscribe_email(person_pk): person = Person.objects.prefetch_related("emails").get(pk=person_pk) bindings = {"MANAGE_SUBSCRIPTIONS_LINK": front_url("contact")} send_mosaico_email( code="UNSUBSCRIBE_CONFIRMATION", subject=_( "Vous avez été désabonné⋅e des emails de la France insoumise"), from_email=settings.EMAIL_FROM, recipients=[person], bindings=bindings, )
def send_donation_email(person_pk, template_code="DONATION_MESSAGE"): try: person = Person.objects.prefetch_related("emails").get(pk=person_pk) except Person.DoesNotExist: return send_mosaico_email( code=template_code, subject="Merci d'avoir donné !", from_email=settings.EMAIL_FROM, bindings={"PROFILE_LINK": front_url("personal_information")}, recipients=[person], )
def send_event_creation_notification(organizer_config_pk): organizer_config = OrganizerConfig.objects.select_related( "event", "person").get(pk=organizer_config_pk) event = organizer_config.event organizer = organizer_config.person document_deadline = event.end_time + timedelta(days=15) bindings = { "EVENT_NAME": event.name, "EVENT_SCHEDULE": event.get_display_date(), "LOCATION_NAME": event.location_name, "LOCATION_ADDRESS": event.short_address, "EVENT_LINK": front_url("view_event", auto_login=False, kwargs={"pk": event.pk}), "MANAGE_EVENT_LINK": front_url("manage_event", auto_login=False, kwargs={"pk": event.pk}), "DOCUMENTS_LINK": front_url("event_project", auto_login=False, kwargs={"pk": event.pk}), "EVENT_NAME_ENCODED": event.name, "EVENT_LINK_ENCODED": front_url("view_event", auto_login=False, kwargs={"pk": event.pk}), "DOCUMENT_DEADLINE": document_deadline.strftime("%d/%m"), "REQUIRED_DOCUMENT_TYPES": event.subtype.required_documents, "NEEDS_DOCUMENTS": len(event.subtype.required_documents) > 0, } send_mosaico_email( code="EVENT_CREATION", subject=_("Les informations de votre nouvel événement"), from_email=settings.EMAIL_FROM, recipients=[organizer], bindings=bindings, attachments=({ "filename": "event.ics", "content": str(ics.Calendar(events=[event.to_ics( text_only_description=True)])), "mimetype": "text/calendar", }, ), )
def send_accepted_group_coorganization_invitation_notification( invitation_id, recipient_ids): invitation = Invitation.objects.get(pk=invitation_id) event = invitation.event group = invitation.group # Notify current event referents recipients = event.organizers.filter(pk__in=recipient_ids) # Add activity to current organizers Activity.objects.bulk_create( [ Activity( type=Activity.TYPE_GROUP_COORGANIZATION_ACCEPTED_FROM, recipient=r, event=event, supportgroup=group, ) for r in recipients ], send_post_save_signal=True, ) # Add activity to new organizers of group invited (group referents) Activity.objects.bulk_create( [ Activity( type=Activity.TYPE_GROUP_COORGANIZATION_ACCEPTED_TO, recipient=r, event=event, supportgroup=group, ) for r in group.referents ], send_post_save_signal=True, ) subject = f"{group.name} a accepté de co-organiser {event.name}" bindings = { "TITLE": subject, "EVENT_NAME": event.name, "GROUP_NAME": group.name, "DATE": now(), } send_mosaico_email( code="EVENT_GROUP_COORGANIZATION_ACCEPTED", subject=subject, from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, )
def send_event_changed_notification(event_pk, changed_data): event = Event.objects.get(pk=event_pk) changed_data = [f for f in changed_data if f in NOTIFIED_CHANGES] recipients = [ r.person for r in event.rsvps.prefetch_related("person__emails").filter( person__notification_subscriptions__type=Subscription. SUBSCRIPTION_EMAIL, person__notification_subscriptions__activity_type=Activity. TYPE_EVENT_UPDATE, ) ] if len(recipients) == 0: return changed_categories = {NOTIFIED_CHANGES[f] for f in changed_data} change_descriptions = [ desc for id, desc in CHANGE_DESCRIPTION.items() if id in changed_categories ] change_fragment = render_to_string(template_name="lib/list_fragment.html", context={"items": change_descriptions}) bindings = { "EVENT_NAME": event.name, "EVENT_CHANGES": change_fragment, "EVENT_LINK": front_url("view_event", kwargs={"pk": event_pk}), "EVENT_QUIT_LINK": front_url("quit_event", kwargs={"pk": event_pk}), } send_mosaico_email( code="EVENT_CHANGED", subject= _("Les informations d'un événement auquel vous participez ont été changées" ), from_email=settings.EMAIL_FROM, recipients=recipients, bindings=bindings, attachments=({ "filename": "event.ics", "content": str(ics.Calendar(events=[event.to_ics( text_only_description=True)])), "mimetype": "text/calendar", }, ), )
def send_person_form_confirmation(submission_pk): submission = PersonFormSubmission.objects.get(pk=submission_pk) person = submission.person form = submission.form bindings = {"CONFIRMATION_NOTE": mark_safe(form.confirmation_note)} send_mosaico_email( code="FORM_CONFIRMATION", subject=_("Confirmation"), from_email=settings.EMAIL_FROM, recipients=[person], bindings=bindings, )
def send_event_suggestion_email(event_pk, recipient_pk): try: event = Event.objects.get(pk=event_pk) except Event.DoesNotExist: return subscription = Subscription.objects.filter( person_id=recipient_pk, type=Subscription.SUBSCRIPTION_EMAIL, activity_type=Activity.TYPE_EVENT_SUGGESTION, ) if not subscription.exists(): return group = event.organizers_groups.first() if group is not None: subject = f"Participez à l'action de {group.name.capitalize()} !" else: subject = "Participez à cette action !" start_time = event.local_start_time simple_date = _date(start_time, "l j F").capitalize() bindings = { "TITLE": subject, "EVENT_NAME": event.name.capitalize(), "EVENT_SCHEDULE": f"{simple_date} à {_date(start_time, 'G:i')}", "LOCATION_NAME": event.location_name, "LOCATION_ZIP": event.location_zip, "EVENT_LINK": event.get_absolute_url(), } send_mosaico_email( code="EVENT_SUGGESTION", subject=subject, from_email=settings.EMAIL_FROM, recipients=[subscription.first().person], bindings=bindings, attachments=({ "filename": "event.ics", "content": str(ics.Calendar(events=[event.to_ics( text_only_description=True)])), "mimetype": "text/calendar", }, ), )
def send_check_information(check_id, force=False): check = CheckPayment.objects.get(id=check_id) mail_sent = check.meta.get("information_email_sent") if mail_sent and not force: return check_mode = PAYMENT_MODES[check.mode] if check_mode.warnings: warning_list = [ f"<li>{conditional_escape(warning)}</li>" for warning in check_mode.warnings ] warnings = mark_safe( f"<p>Prenez bien garde aux points suivants :</p><ul>{''.join(warning_list)}</ul>" ) else: warnings = "" bindings = { "TITLE": check_mode.title, "ORDER": check_mode.order, "AMOUNT": check.get_price_display(), "PAYMENT_ID": str(check.id), "ADDRESS": mark_safe("<br>".join( conditional_escape(part) for part in check_mode.address)), "ADDITIONAL_INFORMATION": check_mode.additional_information, "WARNINGS": warnings, } send_mosaico_email( code="CHECK_INFORMATION", subject=check_mode.title, from_email=settings.EMAIL_FROM, recipients=[check.person or check.email], bindings=bindings, ) check.meta["information_email_sent"] = True check.save()