diff --git a/app/config.py b/app/config.py
index c49109e8..1b3c869b 100644
--- a/app/config.py
+++ b/app/config.py
@@ -333,6 +333,8 @@ AlERT_WRONG_MX_RECORD_CUSTOM_DOMAIN = "custom_domain_mx_record_issue"
# alert when a new alias is about to be created on a disabled directory
ALERT_DIRECTORY_DISABLED_ALIAS_CREATION = "alert_directory_disabled_alias_creation"
+ALERT_HOTMAIL_COMPLAINT = "alert_hotmail_complaint"
+
# <<<<< END ALERT EMAIL >>>>
# Disable onboarding emails
@@ -393,3 +395,5 @@ except Exception:
HIBP_API_KEYS = sl_getenv("HIBP_API_KEYS", list) or []
NEWRELIC_CONFIG_PATH = os.environ.get("NEWRELIC_CONFIG_PATH")
+
+POSTMASTER = os.environ.get("POSTMASTER")
\ No newline at end of file
diff --git a/app/email/status.py b/app/email/status.py
index 7811c937..28e95ae7 100644
--- a/app/email/status.py
+++ b/app/email/status.py
@@ -11,6 +11,8 @@ E206 = "250 SL E206 Out of office"
# if mail_from is a IgnoreBounceSender, no need to send back a bounce report
E207 = "250 SL E207 No bounce report"
+E208 = "250 SL E208 Hotmail complaint handled"
+
# 4** errors
# E401 = "421 SL E401 Retry later"
E402 = "421 SL E402 Encryption failed - Retry later"
diff --git a/app/email_utils.py b/app/email_utils.py
index 6109dd3e..8f34b121 100644
--- a/app/email_utils.py
+++ b/app/email_utils.py
@@ -567,6 +567,19 @@ def get_orig_message_from_bounce(msg: Message) -> Message:
return part
+def get_orig_message_from_outlook_complaint(msg: Message) -> Message:
+ """parse the original email from Bounce"""
+ i = 0
+ for part in msg.walk():
+ i += 1
+
+ # 1st part is the container
+ # 2nd part is the empty body
+ # 3rd is original message
+ if i == 3:
+ return part
+
+
def get_header_from_bounce(msg: Message, header: str) -> str:
"""using regex to get header value from bounce message
get_orig_message_from_bounce is better. This should be the last option
diff --git a/email_handler.py b/email_handler.py
index fed44266..08ef4d84 100644
--- a/email_handler.py
+++ b/email_handler.py
@@ -76,6 +76,8 @@ from app.config import (
ENABLE_SPAM_ASSASSIN,
BOUNCE_PREFIX_FOR_REPLY_PHASE,
NEWRELIC_CONFIG_PATH,
+ POSTMASTER,
+ ALERT_HOTMAIL_COMPLAINT,
)
from app.email import status
from app.email.rate_limit import rate_limited
@@ -112,6 +114,7 @@ from app.email_utils import (
sanitize_header,
get_queue_id,
should_ignore_bounce,
+ get_orig_message_from_outlook_complaint,
)
from app.extensions import db
from app.log import LOG, set_message_id
@@ -1279,6 +1282,37 @@ def handle_bounce_forward_phase(msg: Message, email_log: EmailLog):
)
+def handle_hotmail_complaint(msg: Message):
+ """
+ Handle hotmail complaint sent to postmaster
+ """
+ orig_msg = get_orig_message_from_outlook_complaint(msg)
+ alias_address = orig_msg["To"]
+ alias = Alias.get_by(email=alias_address)
+
+ if not alias:
+ LOG.d("No alias for %s", alias_address)
+
+ user = alias.user
+ LOG.e("Handle hotmail complaint for %s %s", alias, user)
+
+ send_email_with_rate_control(
+ user,
+ ALERT_HOTMAIL_COMPLAINT,
+ user.email,
+ f"Hotmail abuse report",
+ render(
+ "transactional/hotmail-complaint.txt.jinja2",
+ alias=alias,
+ ),
+ render(
+ "transactional/hotmail-complaint.html",
+ alias=alias,
+ ),
+ max_nb_alert=2,
+ )
+
+
def handle_bounce_reply_phase(envelope, msg: Message, email_log: EmailLog):
"""
Handle reply phase bounce
@@ -1687,6 +1721,15 @@ def handle(envelope: Envelope) -> str:
handle_transactional_bounce(envelope, rcpt_tos[0])
return status.E205
+ if (
+ len(rcpt_tos) == 1
+ and mail_from == "staff@hotmail.com"
+ and rcpt_tos[0] == POSTMASTER
+ ):
+ LOG.w("Handle hotmail complaint")
+ handle_hotmail_complaint(msg)
+ return status.E208
+
# Handle bounce
if (
len(rcpt_tos) == 1
diff --git a/templates/emails/transactional/hotmail-complaint.html b/templates/emails/transactional/hotmail-complaint.html
new file mode 100644
index 00000000..6c67c44e
--- /dev/null
+++ b/templates/emails/transactional/hotmail-complaint.html
@@ -0,0 +1,33 @@
+{% extends "base.html" %}
+
+{% block content %}
+ {% call text() %}
+ This is SimpleLogin team.
+ Hotmail has informed us about an email sent to {{ alias.email }} that might have been marked as spam.
+ {% endcall %}
+
+ {% call text() %}
+ Putting a forwarded email into Spam affects SimpleLogin email delivery, has a negative effect for all users and
+ is a violation of our terms and condition.
+ {% endcall %}
+
+ {% call text() %}
+ If that’s the case, please disable the alias instead if you don't want to receive the emails sent to this alias.
+ {% endcall %}
+
+ {% call text() %}
+ If SimpleLogin isn’t useful for you, please know that you can simply delete your account on the Settings page.
+ {% endcall %}
+
+ {% call text() %}
+ Looking to hear back from you.
+ {% endcall %}
+
+ {% call text() %}
+ Best,
+ SimpleLogin Team.
+ {% endcall %}
+
+{% endblock %}
+
+
diff --git a/templates/emails/transactional/hotmail-complaint.txt.jinja2 b/templates/emails/transactional/hotmail-complaint.txt.jinja2
new file mode 100644
index 00000000..1e8d611e
--- /dev/null
+++ b/templates/emails/transactional/hotmail-complaint.txt.jinja2
@@ -0,0 +1,17 @@
+Hi,
+
+This is SimpleLogin team.
+
+Hotmail has informed us about an email sent to {{ alias.email }} that might have been marked as spam.
+
+Putting a forwarded email into Spam affects SimpleLogin email delivery, has a negative effect for all users and
+ is a violation of our terms and condition.
+
+If that’s the case, please disable the alias instead if you don't want to receive the emails sent to this alias.
+
+If SimpleLogin isn’t useful for you, please know that you can simply delete your account on the Settings page.
+
+Looking to hear back from you.
+
+Best,
+SimpleLogin Team.
\ No newline at end of file