From 0d7d56c0ea92aef8c16e37b1fb221d500deb4ccb Mon Sep 17 00:00:00 2001 From: Son Date: Fri, 25 Mar 2022 17:25:35 +0100 Subject: [PATCH] send email when an email is put to quarantine --- app/config.py | 2 ++ app/models.py | 3 ++ email_handler.py | 35 ++++++++++++++++--- .../message-quarantine-dmarc.html | 28 +++++++++++++++ .../message-quarantine-dmarc.txt.jinja2 | 8 +++++ .../notification/message-quarantine.html | 14 ++++++-- 6 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 templates/emails/transactional/message-quarantine-dmarc.html create mode 100644 templates/emails/transactional/message-quarantine-dmarc.txt.jinja2 diff --git a/app/config.py b/app/config.py index a21c8dfb..4a83f985 100644 --- a/app/config.py +++ b/app/config.py @@ -340,6 +340,8 @@ ALERT_HOTMAIL_COMPLAINT_REPLY_PHASE = "alert_hotmail_complaint_reply_phase" ALERT_HOTMAIL_COMPLAINT_TRANSACTIONAL = "alert_hotmail_complaint_transactional" ALERT_YAHOO_COMPLAINT = "alert_yahoo_complaint" +ALERT_QUARANTINE_DMARC = "alert_quarantine_dmarc" + # <<<<< END ALERT EMAIL >>>> # Disable onboarding emails diff --git a/app/models.py b/app/models.py index 66bfff5f..96b303c5 100644 --- a/app/models.py +++ b/app/models.py @@ -1819,6 +1819,9 @@ class EmailLog(Base, ModelMixin): else: return "forward" + def get_dashboard_url(self): + return f"{URL}/dashboard/refused_email?highlight_id={self.id}" + def __repr__(self): return f"" diff --git a/email_handler.py b/email_handler.py index 10297345..82c2c2bf 100644 --- a/email_handler.py +++ b/email_handler.py @@ -88,6 +88,7 @@ from app.config import ( ALERT_FROM_ADDRESS_IS_REVERSE_ALIAS, ALERT_TO_NOREPLY, DMARC_CHECK_ENABLED, + ALERT_QUARANTINE_DMARC, ) from app.db import Session from app.email import status, headers @@ -540,7 +541,7 @@ def handle_email_sent_to_ourself(alias, from_addr: str, msg: Message, user): def apply_dmarc_policy( - alias: Alias, contact: Contact, envelope: Envelope, msg: Message + alias: Alias, contact: Contact, envelope: Envelope, msg: Message, from_header ) -> Optional[str]: dmarc_result = get_dmarc_status(msg) if dmarc_result: @@ -560,7 +561,7 @@ def apply_dmarc_policy( f"put email from {contact} to {alias} to quarantine. {dmarc_result}, " f"mail_from:{envelope.mail_from}, from_header: {msg[headers.FROM]}" ) - quarantine_dmarc_failed_email(alias, contact, envelope, msg) + email_log = quarantine_dmarc_failed_email(alias, contact, envelope, msg) Notification.create( user_id=alias.user_id, title=f"{alias.email} has a new mail in quarantine", @@ -569,12 +570,33 @@ def apply_dmarc_policy( ), commit=True, ) + user = alias.user + send_email_with_rate_control( + user, + ALERT_QUARANTINE_DMARC, + user.email, + f"An email sent to {alias.email} has been quarantined", + render( + "transactional/message-quarantine-dmarc.txt.jinja2", + from_header=from_header, + alias=alias, + refused_email_url=email_log.get_dashboard_url(), + ), + render( + "transactional/message-quarantine-dmarc.html", + from_header=from_header, + alias=alias, + refused_email_url=email_log.get_dashboard_url(), + ), + max_nb_alert=10, + ignore_smtp_error=True, + ) return status.E215 return None -def quarantine_dmarc_failed_email(alias, contact, envelope, msg): +def quarantine_dmarc_failed_email(alias, contact, envelope, msg) -> EmailLog: add_or_replace_header(msg, headers.SL_DIRECTION, "Forward") msg[headers.SL_ENVELOPE_TO] = alias.email msg[headers.SL_ENVELOPE_FROM] = envelope.mail_from @@ -586,6 +608,7 @@ def quarantine_dmarc_failed_email(alias, contact, envelope, msg): except CannotCreateContactForReverseAlias: Session.commit() raise + random_name = str(uuid.uuid4()) s3_report_path = f"refused-emails/full-{random_name}.eml" s3.upload_email_from_bytesio( @@ -594,7 +617,7 @@ def quarantine_dmarc_failed_email(alias, contact, envelope, msg): refused_email = RefusedEmail.create( full_report_path=s3_report_path, user_id=alias.user_id, flush=True ) - EmailLog.create( + return EmailLog.create( user_id=alias.user_id, mailbox_id=alias.mailbox_id, contact_id=contact.id, @@ -688,7 +711,9 @@ def handle_forward(envelope, msg: Message, rcpt_to: str) -> List[Tuple[bool, str return [(True, res_status)] # Check if we need to reject or quarantine based on dmarc - dmarc_delivery_status = apply_dmarc_policy(alias, contact, envelope, msg) + dmarc_delivery_status = apply_dmarc_policy( + alias, contact, envelope, msg, from_header + ) if dmarc_delivery_status is not None: return [(False, dmarc_delivery_status)] diff --git a/templates/emails/transactional/message-quarantine-dmarc.html b/templates/emails/transactional/message-quarantine-dmarc.html new file mode 100644 index 00000000..2953db12 --- /dev/null +++ b/templates/emails/transactional/message-quarantine-dmarc.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} + +{% block content %} + {% call text() %} +

+ An email from {{ from_header }} to {{ alias.email }} is put into Quarantine +

+ {% endcall %} + + {% call text() %} + An email from {{ from_header }} to {{ alias.email }} is put into Quarantine as it fails DMARC check. + DMARC is an email authentication protocol designed for detecting phishing. + {% endcall %} + + {{ render_button("View the original email", refused_email_url) }} + + {% call text() %} + This email is automatically deleted in 7 days. + {% endcall %} + + {% call text() %} + Best,
+ SimpleLogin Team. + {% endcall %} + +{% endblock %} + + diff --git a/templates/emails/transactional/message-quarantine-dmarc.txt.jinja2 b/templates/emails/transactional/message-quarantine-dmarc.txt.jinja2 new file mode 100644 index 00000000..96b540d9 --- /dev/null +++ b/templates/emails/transactional/message-quarantine-dmarc.txt.jinja2 @@ -0,0 +1,8 @@ +{% extends "base.txt.jinja2" %} + +{% block content %} + An email from {{ from_header }} to {{ alias.email }} is put into Quarantine as it fails DMARC check. + + You can view the email at {{ refused_email_url }}. + This email is automatically deleted in 7 days. +{% endblock %} diff --git a/templates/notification/message-quarantine.html b/templates/notification/message-quarantine.html index 84c033f5..ed28781d 100644 --- a/templates/notification/message-quarantine.html +++ b/templates/notification/message-quarantine.html @@ -1,5 +1,15 @@
- There is a new quarantined message for {{ alias.email }}. - Please go to your quarantined emails to review it. + An email from {{ from_header }} to {{ alias.email }} is put into Quarantine as it fails DMARC check. +
+ DMARC is an email authentication protocol designed for detecting + phishing. When an email fails DMARC, it can be considered as suspicious. +
+ + + View quarantined emails + + +
+ The email is automatically deleted in 7 days.