Merge pull request #963 from simple-login/ac-complaints
Handle complaints that have multiple recipients
This commit is contained in:
commit
2adcbf52be
|
@ -105,6 +105,15 @@ We cannot use the local database to generate migration script as the local datab
|
||||||
It is created via `db.create_all()` (cf `fake_data()` method). This is convenient for development and
|
It is created via `db.create_all()` (cf `fake_data()` method). This is convenient for development and
|
||||||
unit tests as we don't have to wait for the migration.
|
unit tests as we don't have to wait for the migration.
|
||||||
|
|
||||||
|
## Reset database
|
||||||
|
|
||||||
|
There are two scripts to reset your local db to an empty state:
|
||||||
|
|
||||||
|
- `scripts/reset_local_db.sh` will reset your development db to the latest migration version and add the development data needed to run the
|
||||||
|
server.py locally.
|
||||||
|
- `scripts/reset_test_db.sh` will reset your test db to the latest migration without adding the dev server data to prevent interferring with
|
||||||
|
the tests.
|
||||||
|
|
||||||
## Code structure
|
## Code structure
|
||||||
|
|
||||||
The repo consists of the three following entry points:
|
The repo consists of the three following entry points:
|
||||||
|
|
|
@ -19,6 +19,7 @@ DKIM_SIGNATURE = "DKIM-Signature"
|
||||||
X_SPAM_STATUS = "X-Spam-Status"
|
X_SPAM_STATUS = "X-Spam-Status"
|
||||||
LIST_UNSUBSCRIBE = "List-Unsubscribe"
|
LIST_UNSUBSCRIBE = "List-Unsubscribe"
|
||||||
LIST_UNSUBSCRIBE_POST = "List-Unsubscribe-Post"
|
LIST_UNSUBSCRIBE_POST = "List-Unsubscribe-Post"
|
||||||
|
RETURN_PATH = "Return-Path"
|
||||||
|
|
||||||
# headers used to DKIM sign in order of preference
|
# headers used to DKIM sign in order of preference
|
||||||
DKIM_HEADERS = [
|
DKIM_HEADERS = [
|
||||||
|
@ -50,3 +51,6 @@ MIME_HEADERS = [h.lower() for h in MIME_HEADERS]
|
||||||
# according to https://datatracker.ietf.org/doc/html/rfc3834#section-3.1.7, this header should be set to "auto-replied"
|
# according to https://datatracker.ietf.org/doc/html/rfc3834#section-3.1.7, this header should be set to "auto-replied"
|
||||||
# however on hotmail, this is set to "auto-generated"
|
# however on hotmail, this is set to "auto-generated"
|
||||||
AUTO_SUBMITTED = "Auto-Submitted"
|
AUTO_SUBMITTED = "Auto-Submitted"
|
||||||
|
|
||||||
|
# Yahoo complaint specific header
|
||||||
|
YAHOO_ORIGINAL_RECIPIENT = "original-rcpt-to"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import base64
|
import base64
|
||||||
|
import binascii
|
||||||
import enum
|
import enum
|
||||||
import hmac
|
import hmac
|
||||||
import json
|
import json
|
||||||
|
@ -1322,6 +1323,20 @@ def should_ignore_bounce(mail_from: str) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def parse_address_list(address_list: str) -> List[Tuple[str, str]]:
|
||||||
|
"""
|
||||||
|
Parse a list of email addresses from a header in the form "ab <ab@sd.com>, cd <cd@cd.com>"
|
||||||
|
and return a list [("ab", "ab@sd.com"),("cd", "cd@cd.com")]
|
||||||
|
"""
|
||||||
|
processed_addresses = []
|
||||||
|
for split_address in address_list.split(","):
|
||||||
|
split_address = split_address.strip()
|
||||||
|
if not split_address:
|
||||||
|
continue
|
||||||
|
processed_addresses.append(parse_full_address(split_address))
|
||||||
|
return processed_addresses
|
||||||
|
|
||||||
|
|
||||||
def parse_full_address(full_address) -> (str, str):
|
def parse_full_address(full_address) -> (str, str):
|
||||||
"""
|
"""
|
||||||
parse the email address full format and return the display name and address
|
parse the email address full format and return the display name and address
|
||||||
|
@ -1414,10 +1429,15 @@ def get_verp_info_from_email(email: str) -> Optional[Tuple[VerpType, int]]:
|
||||||
fields = username.split(".")
|
fields = username.split(".")
|
||||||
if len(fields) != 3 or fields[0] != VERP_PREFIX:
|
if len(fields) != 3 or fields[0] != VERP_PREFIX:
|
||||||
return None
|
return None
|
||||||
|
try:
|
||||||
padding = (8 - (len(fields[1]) % 8)) % 8
|
padding = (8 - (len(fields[1]) % 8)) % 8
|
||||||
payload = base64.b32decode(fields[1].encode("utf-8").upper() + (b"=" * padding))
|
payload = base64.b32decode(fields[1].encode("utf-8").upper() + (b"=" * padding))
|
||||||
padding = (8 - (len(fields[2]) % 8)) % 8
|
padding = (8 - (len(fields[2]) % 8)) % 8
|
||||||
signature = base64.b32decode(fields[2].encode("utf-8").upper() + (b"=" * padding))
|
signature = base64.b32decode(
|
||||||
|
fields[2].encode("utf-8").upper() + (b"=" * padding)
|
||||||
|
)
|
||||||
|
except binascii.Error:
|
||||||
|
return None
|
||||||
expected_signature = hmac.new(
|
expected_signature = hmac.new(
|
||||||
VERP_EMAIL_SECRET.encode("utf-8"), payload, VERP_HMAC_ALGO
|
VERP_EMAIL_SECRET.encode("utf-8"), payload, VERP_HMAC_ALGO
|
||||||
).digest()[:8]
|
).digest()[:8]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import uuid
|
import uuid
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
from dataclasses import dataclass
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from mailbox import Message
|
from mailbox import Message
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
@ -12,12 +13,14 @@ from app.config import (
|
||||||
)
|
)
|
||||||
from app.email import headers
|
from app.email import headers
|
||||||
from app.email_utils import (
|
from app.email_utils import (
|
||||||
get_header_unicode,
|
|
||||||
parse_full_address,
|
parse_full_address,
|
||||||
save_email_for_debugging,
|
save_email_for_debugging,
|
||||||
to_bytes,
|
to_bytes,
|
||||||
render,
|
render,
|
||||||
send_email_with_rate_control,
|
send_email_with_rate_control,
|
||||||
|
parse_address_list,
|
||||||
|
get_header_unicode,
|
||||||
|
get_verp_info_from_email,
|
||||||
)
|
)
|
||||||
from app.log import LOG
|
from app.log import LOG
|
||||||
from app.models import (
|
from app.models import (
|
||||||
|
@ -30,15 +33,72 @@ from app.models import (
|
||||||
Phase,
|
Phase,
|
||||||
ProviderComplaintState,
|
ProviderComplaintState,
|
||||||
RefusedEmail,
|
RefusedEmail,
|
||||||
|
VerpType,
|
||||||
|
EmailLog,
|
||||||
|
Mailbox,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class OriginalMessageInformation:
|
||||||
|
sender_address: str
|
||||||
|
rcpt_address: str
|
||||||
|
mailbox_address: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
class ProviderComplaintOrigin(ABC):
|
class ProviderComplaintOrigin(ABC):
|
||||||
@classmethod
|
@classmethod
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_original_message(cls, message: Message) -> Optional[Message]:
|
def get_original_addresses(
|
||||||
|
cls, message: Message
|
||||||
|
) -> Optional[OriginalMessageInformation]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_mailbox_id(cls, return_path: Optional[str]) -> Optional[Mailbox]:
|
||||||
|
if not return_path:
|
||||||
|
return None
|
||||||
|
_, return_path = parse_full_address(get_header_unicode(return_path))
|
||||||
|
verp_type, email_log_id = get_verp_info_from_email(return_path)
|
||||||
|
if verp_type == VerpType.transactional:
|
||||||
|
return None
|
||||||
|
email_log = EmailLog.get_by(id=email_log_id)
|
||||||
|
if email_log:
|
||||||
|
return email_log.mailbox.email
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sanitize_addresses_and_extract_mailbox_id(
|
||||||
|
cls, rcpt_header: Optional[str], message: Message
|
||||||
|
) -> Optional[OriginalMessageInformation]:
|
||||||
|
"""
|
||||||
|
If the rcpt_header is not None, use it as the valid rcpt address, otherwise try to extract it from the To header
|
||||||
|
of the original message, since in the original message there can be more than one recipients.
|
||||||
|
There can only be one sender so that one can safely be extracted from the message headers.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if not rcpt_header:
|
||||||
|
rcpt_header = message[headers.TO]
|
||||||
|
rcpt_list = parse_address_list(get_header_unicode(rcpt_header))
|
||||||
|
if not rcpt_list:
|
||||||
|
saved_file = save_email_for_debugging(message, "NoRecipientComplaint")
|
||||||
|
LOG.w(f"Cannot find rcpt. Saved to {saved_file or 'nowhere'}")
|
||||||
|
return None
|
||||||
|
rcpt_address = rcpt_list[0][1]
|
||||||
|
_, sender_address = parse_full_address(
|
||||||
|
get_header_unicode(message[headers.FROM])
|
||||||
|
)
|
||||||
|
|
||||||
|
return OriginalMessageInformation(
|
||||||
|
sender_address,
|
||||||
|
rcpt_address,
|
||||||
|
cls._get_mailbox_id(message[headers.RETURN_PATH]),
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
saved_file = save_email_for_debugging(message, "ComplaintOriginalAddress")
|
||||||
|
LOG.w(f"Cannot parse from header. Saved to {saved_file or 'nowhere'}")
|
||||||
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def name(cls):
|
def name(cls):
|
||||||
|
@ -58,6 +118,32 @@ class ProviderComplaintYahoo(ProviderComplaintOrigin):
|
||||||
return part
|
return part
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_feedback_report(cls, message: Message) -> Optional[Message]:
|
||||||
|
"""
|
||||||
|
Find a report that yahoo embeds in the complaint. It has content type 'message/feedback-report'
|
||||||
|
"""
|
||||||
|
for part in message.walk():
|
||||||
|
if part["content-type"] == "message/feedback-report":
|
||||||
|
content = part.get_payload()
|
||||||
|
if not content:
|
||||||
|
continue
|
||||||
|
return content[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_original_addresses(
|
||||||
|
cls, message: Message
|
||||||
|
) -> Optional[OriginalMessageInformation]:
|
||||||
|
"""
|
||||||
|
Try to get the proper recipient from the report that yahoo adds as a port of the complaint. If we cannot find
|
||||||
|
the rcpt in the report or we can't find the report, use the first address in the original message from
|
||||||
|
"""
|
||||||
|
report = cls.get_feedback_report(message)
|
||||||
|
original = cls.get_original_message(message)
|
||||||
|
rcpt_header = report[headers.YAHOO_ORIGINAL_RECIPIENT]
|
||||||
|
return cls.sanitize_addresses_and_extract_mailbox_id(rcpt_header, original)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def name(cls):
|
def name(cls):
|
||||||
return "yahoo"
|
return "yahoo"
|
||||||
|
@ -76,6 +162,17 @@ class ProviderComplaintHotmail(ProviderComplaintOrigin):
|
||||||
return part
|
return part
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_original_addresses(
|
||||||
|
cls, message: Message
|
||||||
|
) -> Optional[OriginalMessageInformation]:
|
||||||
|
"""
|
||||||
|
Try to get the proper recipient from original x-simplelogin-envelope-to header we add on delivery.
|
||||||
|
If we can't find the header, use the first address in the original message from"""
|
||||||
|
original = cls.get_original_message(message)
|
||||||
|
rcpt_header = original[headers.SL_ENVELOPE_TO]
|
||||||
|
return cls.sanitize_addresses_and_extract_mailbox_id(rcpt_header, original)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def name(cls):
|
def name(cls):
|
||||||
return "hotmail"
|
return "hotmail"
|
||||||
|
@ -98,60 +195,55 @@ def find_alias_with_address(address: str) -> Optional[Alias]:
|
||||||
|
|
||||||
|
|
||||||
def handle_complaint(message: Message, origin: ProviderComplaintOrigin) -> bool:
|
def handle_complaint(message: Message, origin: ProviderComplaintOrigin) -> bool:
|
||||||
original_message = origin.get_original_message(message)
|
msg_info = origin.get_original_addresses(message)
|
||||||
|
if not msg_info:
|
||||||
try:
|
|
||||||
_, to_address = parse_full_address(
|
|
||||||
get_header_unicode(original_message[headers.TO])
|
|
||||||
)
|
|
||||||
_, from_address = parse_full_address(
|
|
||||||
get_header_unicode(original_message[headers.FROM])
|
|
||||||
)
|
|
||||||
except ValueError:
|
|
||||||
saved_file = save_email_for_debugging(message, "FromParseFailed")
|
|
||||||
LOG.w(f"Cannot parse from header. Saved to {saved_file or 'nowhere'}")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
user = User.get_by(email=to_address)
|
user = User.get_by(email=msg_info.rcpt_address)
|
||||||
if user:
|
if user:
|
||||||
LOG.d(f"Handle provider {origin.name()} complaint for {user}")
|
LOG.d(f"Handle provider {origin.name()} complaint for {user}")
|
||||||
report_complaint_to_user_in_transactional_phase(user, origin)
|
report_complaint_to_user_in_transactional_phase(user, origin, msg_info)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
alias = find_alias_with_address(from_address)
|
alias = find_alias_with_address(msg_info.sender_address)
|
||||||
# the email is during a reply phase, from=alias and to=destination
|
# the email is during a reply phase, from=alias and to=destination
|
||||||
if alias:
|
if alias:
|
||||||
LOG.i(
|
LOG.i(
|
||||||
f"Complaint from {origin.name} during reply phase {alias} -> {to_address}, {user}"
|
f"Complaint from {origin.name} during reply phase {alias} -> {msg_info.rcpt_address}, {user}"
|
||||||
|
)
|
||||||
|
report_complaint_to_user_in_reply_phase(
|
||||||
|
alias, msg_info.rcpt_address, origin, msg_info
|
||||||
)
|
)
|
||||||
report_complaint_to_user_in_reply_phase(alias, to_address, origin)
|
|
||||||
store_provider_complaint(alias, message)
|
store_provider_complaint(alias, message)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
contact = Contact.get_by(reply_email=from_address)
|
contact = Contact.get_by(reply_email=msg_info.sender_address)
|
||||||
if contact:
|
if contact:
|
||||||
alias = contact.alias
|
alias = contact.alias
|
||||||
else:
|
else:
|
||||||
alias = find_alias_with_address(to_address)
|
alias = find_alias_with_address(msg_info.rcpt_address)
|
||||||
|
|
||||||
if not alias:
|
if not alias:
|
||||||
LOG.e(
|
LOG.e(
|
||||||
f"Cannot find alias from address {to_address} or contact with reply {from_address}"
|
f"Cannot find alias for address {msg_info.rcpt_address} or contact with reply {msg_info.sender_address}"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
report_complaint_to_user_in_forward_phase(alias, origin)
|
report_complaint_to_user_in_forward_phase(alias, origin, msg_info)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def report_complaint_to_user_in_reply_phase(
|
def report_complaint_to_user_in_reply_phase(
|
||||||
alias: Alias, to_address: str, origin: ProviderComplaintOrigin
|
alias: Alias,
|
||||||
|
to_address: str,
|
||||||
|
origin: ProviderComplaintOrigin,
|
||||||
|
msg_info: OriginalMessageInformation,
|
||||||
):
|
):
|
||||||
capitalized_name = origin.name().capitalize()
|
capitalized_name = origin.name().capitalize()
|
||||||
send_email_with_rate_control(
|
send_email_with_rate_control(
|
||||||
alias.user,
|
alias.user,
|
||||||
f"{ALERT_COMPLAINT_REPLY_PHASE}_{origin.name()}",
|
f"{ALERT_COMPLAINT_REPLY_PHASE}_{origin.name()}",
|
||||||
alias.user.email,
|
msg_info.mailbox_address or alias.mailbox.email,
|
||||||
f"Abuse report from {capitalized_name}",
|
f"Abuse report from {capitalized_name}",
|
||||||
render(
|
render(
|
||||||
"transactional/provider-complaint-reply-phase.txt.jinja2",
|
"transactional/provider-complaint-reply-phase.txt.jinja2",
|
||||||
|
@ -166,13 +258,13 @@ def report_complaint_to_user_in_reply_phase(
|
||||||
|
|
||||||
|
|
||||||
def report_complaint_to_user_in_transactional_phase(
|
def report_complaint_to_user_in_transactional_phase(
|
||||||
user: User, origin: ProviderComplaintOrigin
|
user: User, origin: ProviderComplaintOrigin, msg_info: OriginalMessageInformation
|
||||||
):
|
):
|
||||||
capitalized_name = origin.name().capitalize()
|
capitalized_name = origin.name().capitalize()
|
||||||
send_email_with_rate_control(
|
send_email_with_rate_control(
|
||||||
user,
|
user,
|
||||||
f"{ALERT_COMPLAINT_TRANSACTIONAL_PHASE}_{origin.name()}",
|
f"{ALERT_COMPLAINT_TRANSACTIONAL_PHASE}_{origin.name()}",
|
||||||
user.email,
|
msg_info.mailbox_address or user.email,
|
||||||
f"Abuse report from {capitalized_name}",
|
f"Abuse report from {capitalized_name}",
|
||||||
render(
|
render(
|
||||||
"transactional/provider-complaint-to-user.txt.jinja2",
|
"transactional/provider-complaint-to-user.txt.jinja2",
|
||||||
|
@ -190,23 +282,24 @@ def report_complaint_to_user_in_transactional_phase(
|
||||||
|
|
||||||
|
|
||||||
def report_complaint_to_user_in_forward_phase(
|
def report_complaint_to_user_in_forward_phase(
|
||||||
alias: Alias, origin: ProviderComplaintOrigin
|
alias: Alias, origin: ProviderComplaintOrigin, msg_info: OriginalMessageInformation
|
||||||
):
|
):
|
||||||
capitalized_name = origin.name().capitalize()
|
capitalized_name = origin.name().capitalize()
|
||||||
user = alias.user
|
user = alias.user
|
||||||
|
mailbox_email = msg_info.mailbox_address or alias.mailbox.email
|
||||||
send_email_with_rate_control(
|
send_email_with_rate_control(
|
||||||
user,
|
user,
|
||||||
f"{ALERT_COMPLAINT_FORWARD_PHASE}_{origin.name()}",
|
f"{ALERT_COMPLAINT_FORWARD_PHASE}_{origin.name()}",
|
||||||
user.email,
|
mailbox_email,
|
||||||
f"Abuse report from {capitalized_name}",
|
f"Abuse report from {capitalized_name}",
|
||||||
render(
|
render(
|
||||||
"transactional/provider-complaint-forward-phase.txt.jinja2",
|
"transactional/provider-complaint-forward-phase.txt.jinja2",
|
||||||
user=user,
|
email=mailbox_email,
|
||||||
provider=capitalized_name,
|
provider=capitalized_name,
|
||||||
),
|
),
|
||||||
render(
|
render(
|
||||||
"transactional/provider-complaint-forward-phase.html",
|
"transactional/provider-complaint-forward-phase.html",
|
||||||
user=user,
|
email=mailbox_email,
|
||||||
provider=capitalized_name,
|
provider=capitalized_name,
|
||||||
),
|
),
|
||||||
max_nb_alert=1,
|
max_nb_alert=1,
|
||||||
|
|
7
scripts/reset_local_db.sh
Executable file
7
scripts/reset_local_db.sh
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
export DB_URI=postgresql://myuser:mypassword@localhost:15432/simplelogin
|
||||||
|
echo 'drop schema public cascade; create schema public;' | psql $DB_URI
|
||||||
|
|
||||||
|
poetry run alembic upgrade head
|
||||||
|
poetry run flask dummy-data
|
6
scripts/reset_test_db.sh
Executable file
6
scripts/reset_test_db.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
export DB_URI=postgresql://myuser:mypassword@localhost:15432/test
|
||||||
|
echo 'drop schema public cascade; create schema public;' | psql $DB_URI
|
||||||
|
|
||||||
|
poetry run alembic upgrade head
|
|
@ -6,7 +6,7 @@
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
|
|
||||||
{% call text() %}
|
{% call text() %}
|
||||||
{{ provider }} has informed us about an email sent to <b>{{ user.email }}</b> that might have been considered as spam,
|
{{ provider }} has informed us about an email sent to <b>{{ email }}</b> that might have been considered as spam,
|
||||||
either by you or by {{ provider }} spam filter.
|
either by you or by {{ provider }} spam filter.
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ Hi,
|
||||||
|
|
||||||
This is SimpleLogin team.
|
This is SimpleLogin team.
|
||||||
|
|
||||||
{{ provider }} has informed us about an email sent to {{ user.email }} that might have been considered as spam,
|
{{ provider }} has informed us about an email sent to {{ email }} that might have been considered as spam,
|
||||||
either by you or by {{ provider }}.
|
either by you or by {{ provider }}.
|
||||||
|
|
||||||
Please note that explicitly marking a SimpleLogin's forwarded email as Spam
|
Please note that explicitly marking a SimpleLogin's forwarded email as Spam
|
||||||
|
|
258
tests/example_emls/hotmail_complaint.eml
Normal file
258
tests/example_emls/hotmail_complaint.eml
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
X-SimpleLogin-Client-IP: 40.92.66.13
|
||||||
|
Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=40.92.66.13;
|
||||||
|
helo=eur01-ve1-obe.outbound.protection.outlook.com;
|
||||||
|
envelope-from=staff@hotmail.com; receiver=<UNKNOWN>
|
||||||
|
Received: from EUR01-VE1-obe.outbound.protection.outlook.com
|
||||||
|
(mail-oln040092066013.outbound.protection.outlook.com [40.92.66.13])
|
||||||
|
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
|
||||||
|
(No client certificate requested)
|
||||||
|
by prod4.simplelogin.co (Postfix) with ESMTPS id 408E09C472
|
||||||
|
for <{{ postmaster }}>; Mon, 9 May 2022 13:11:34 +0000 (UTC)
|
||||||
|
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
|
||||||
|
b=V3N8KdYGgYrjs5KcjFUA0MgPUmOc+NV4ygLfSd7fehfiNemKdhe6Cpfj58zWFNzoG5qBoUCIm/BI7aCr7lqAU2hQJypTrJG+3zbSdnuCKMBVV5GHZxkE+XAeSU+4wt4xwl1ZiVx/2P//xUVWN/TVmiuKUgCn9n+WagU9LYGVT9z6wwOpXggpDf6ow9RnJDPJpkakHRh7rQPABbrOpVqEZnoJdAH5mgdTHJOeBumNym4i3GKnky+IfMlqwGcbTrzgrt/D3PpZdsMG4B+jEHtTo3FgB9JY+abjU9Bvn4rXwKr3RMF+1ZV3UsznQVwuT99PtfEcExV3zSsqEPDBy9QT9w==
|
||||||
|
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
|
||||||
|
s=arcselector9901;
|
||||||
|
h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
|
||||||
|
bh=Y37p6EaXY5hpBNgMr1ILYzy35GKdkqWXm69FR2RyQgA=;
|
||||||
|
b=aet1P4fpmUM9bqbLD3vtp/EWfUi2WfvWbOnnLg/YZ2vxoTF/eM5IHDBB/I7btdzZICric+KkhRih/kvaVURGy4jybYjn9FNfT+HShTJa75Pk30fp3in/5lL2x6Q0xM0Naf9YtTvGgqlLDrdgCmktxyByNAOFPo27fEWy3fk/00IPWyI8j77VvYsGn8rJCLbhDUBWwGzQ9P7SabIqn9Ybx6CKcw2FssJhSNAyOIx7EkrGxq8y/5dXeWSHLFBdHPu6F9w/DKyt9cv17rBSnHo4tx1Ese93vBHT5XIwTwnGisCa0++eqL/69GugKoe5odkAfsdRAlBjVTgXp2Lol4rrpg==
|
||||||
|
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none;
|
||||||
|
dkim=none; arc=none
|
||||||
|
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com;
|
||||||
|
s=selector1;
|
||||||
|
h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
|
||||||
|
bh=Y37p6EaXY5hpBNgMr1ILYzy35GKdkqWXm69FR2RyQgA=;
|
||||||
|
b=uMkd90Lx6ikNpk7RRBU3AfQ0jjbjRZAGQLnY3r+dQ3CNnhgfHxpNRudxGDydmf6GQ2AuylmOnLVATh8XMKTvCnVg8hjB9xrxd5qPpQ3k92U5VlgVe1o1Nwq8R6VCJugOZduDjSJdBXO2ACosUul6IQXKMBpSNq+bGJ9VHu63EGTphkWOOw1a4PArg8tQTSmkpkyh788nsfNXnVsh2fkL6we1LyvagQzTS4e1ynuSk1zAk+6U5KOuhRVr2Nh/AvyvswWpjA4pflOqFwyqsMYb3N6wnpRTct8CJUPlQwEx6chiJgKNGrAkdRbnWaEyeIEdyJB/NLwtPqZzKYFgv7f8wg==
|
||||||
|
Received: from AM6PR02CA0021.eurprd02.prod.outlook.com (2603:10a6:20b:6e::34)
|
||||||
|
by AM0PR02MB4563.eurprd02.prod.outlook.com (2603:10a6:208:ec::33) with
|
||||||
|
Microsoft SMTP Server (version=TLS1_2,
|
||||||
|
cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5227.22; Mon, 9 May
|
||||||
|
2022 13:11:32 +0000
|
||||||
|
Received: from AM6EUR05FT047.eop-eur05.prod.protection.outlook.com
|
||||||
|
(2603:10a6:20b:6e:cafe::26) by AM6PR02CA0021.outlook.office365.com
|
||||||
|
(2603:10a6:20b:6e::34) with Microsoft SMTP Server (version=TLS1_2,
|
||||||
|
cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5227.23 via Frontend
|
||||||
|
Transport; Mon, 9 May 2022 13:11:32 +0000
|
||||||
|
Received: from DM5SVC01SF077 (40.107.211.126) by
|
||||||
|
AM6EUR05FT047.mail.protection.outlook.com (10.233.241.167) with Microsoft
|
||||||
|
SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id
|
||||||
|
15.20.5227.15 via Frontend Transport; Mon, 9 May 2022 13:11:32 +0000
|
||||||
|
X-IncomingTopHeaderMarker:
|
||||||
|
OriginalChecksum:86053024C4DD515561A96BAF61AACB6F8A4DB30C8D14CAC5F2F7D189ACDCA109;UpperCasedChecksum:5323AB267D58619B82076460438A30DFDD8E7969870D76B723156F921928319B;SizeAsReceived:257;Count:6
|
||||||
|
Date: Mon, 9 May 2022 13:10:08 +0000
|
||||||
|
From: <staff@hotmail.com>
|
||||||
|
Subject: complaint about message from 176.119.200.162
|
||||||
|
To: {{ postmaster }}
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: multipart/mixed;
|
||||||
|
boundary="31A9507D-D0B3-4DCD-AFBB-413468892CFE"
|
||||||
|
X-IncomingHeaderCount: 6
|
||||||
|
Message-ID:
|
||||||
|
<1d63d9ee-8f3e-4876-955c-1807db5ad138@AM6EUR05FT047.eop-eur05.prod.protection.outlook.com>
|
||||||
|
X-EOPAttributedMessage: 0
|
||||||
|
X-MS-PublicTrafficType: Email
|
||||||
|
X-MS-Office365-Filtering-Correlation-Id: 44e9ec0b-6c5d-4cea-6417-08da31bd7000
|
||||||
|
X-MS-TrafficTypeDiagnostic: AM0PR02MB4563:EE_
|
||||||
|
X-Microsoft-Antispam: BCL:0;
|
||||||
|
X-Microsoft-Antispam-Message-Info:
|
||||||
|
lK5xD4UZS47NfR0tHc3wEp4HHOifZ4SDBb8aKx7H/vEW8Rg8rXXH12G4lWdpzr8qTsCmvzuhj5x6IAumOKQ8lWLj5Lp3jyml91wVnwCtUnk5cTXpQwDZd9QMgtEW07GoLdWjkbShAhLRDf+9Y4DxidHCacOAYxcNX42wo3vYZOEHDzVRUxSmY0c7Km60pDtiYzEk+P9AoE2YKYG2rDwDx0vgoLgqFspGqQ+2OeHD2ZAEyATHR/sQy6tf5S2d4wA3HcHrwrGMlz/4d9VbT5h9a5cqj9S59wpuc6g8nyYhmK3AHJkB5nXmpBZBihTw5X/Qh5PZqUYwPxkwpq3WlaEuXvzaKFiwJFvtuRGX+mEioClCxiwPROb7sI9ZHWPw48AHysF+whYGBfleRy4c2SuW6e1D5uewGry+lXVljxg7qKo=
|
||||||
|
X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-ab7de.templateTenant
|
||||||
|
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 May 2022 13:11:32.0875
|
||||||
|
(UTC)
|
||||||
|
X-MS-Exchange-CrossTenant-Network-Message-Id:
|
||||||
|
44e9ec0b-6c5d-4cea-6417-08da31bd7000
|
||||||
|
X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa
|
||||||
|
X-MS-Exchange-CrossTenant-AuthSource:
|
||||||
|
AM6EUR05FT047.eop-eur05.prod.protection.outlook.com
|
||||||
|
X-MS-Exchange-CrossTenant-AuthAs: Anonymous
|
||||||
|
X-MS-Exchange-CrossTenant-FromEntityHeader: Internet
|
||||||
|
X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg:
|
||||||
|
00000000-0000-0000-0000-000000000000
|
||||||
|
X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR02MB4563
|
||||||
|
X-Spamd-Result: default: False [-1.75 / 13.00];
|
||||||
|
ARC_ALLOW(-1.00)[microsoft.com:s=arcselector9901:i=1];
|
||||||
|
DMARC_POLICY_ALLOW(-0.50)[hotmail.com,none];
|
||||||
|
R_SPF_ALLOW(-0.20)[+ip4:40.92.0.0/15];
|
||||||
|
MIME_HTML_ONLY(0.20)[];
|
||||||
|
R_DKIM_ALLOW(-0.20)[hotmail.com:s=selector1];
|
||||||
|
MIME_GOOD(-0.10)[multipart/mixed,multipart/related];
|
||||||
|
MANY_INVISIBLE_PARTS(0.05)[1];
|
||||||
|
NEURAL_HAM(-0.00)[-0.996];
|
||||||
|
FROM_EQ_ENVFROM(0.00)[];
|
||||||
|
FREEMAIL_ENVFROM(0.00)[hotmail.com];
|
||||||
|
MIME_TRACE(0.00)[0:+,1:~,2:+,3:+,4:~];
|
||||||
|
ASN(0.00)[asn:8075, ipnet:40.80.0.0/12, country:US];
|
||||||
|
RCVD_IN_DNSWL_NONE(0.00)[40.92.66.13:from];
|
||||||
|
DKIM_TRACE(0.00)[hotmail.com:+];
|
||||||
|
RCVD_TLS_LAST(0.00)[];
|
||||||
|
TO_MATCH_ENVRCPT_ALL(0.00)[];
|
||||||
|
FREEMAIL_FROM(0.00)[hotmail.com];
|
||||||
|
FROM_NO_DN(0.00)[];
|
||||||
|
TO_DN_NONE(0.00)[];
|
||||||
|
RCVD_COUNT_THREE(0.00)[4];
|
||||||
|
RCPT_COUNT_ONE(0.00)[1];
|
||||||
|
DWL_DNSWL_NONE(0.00)[hotmail.com:dkim]
|
||||||
|
X-Rspamd-Queue-Id: 408E09C472
|
||||||
|
X-Rspamd-Server: prod4
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
--31A9507D-D0B3-4DCD-AFBB-413468892CFE
|
||||||
|
Content-Type: message/rfc822
|
||||||
|
Content-Disposition: inline
|
||||||
|
|
||||||
|
X-HmXmrOriginalRecipient: <jan.bailey2934@outlook.com>
|
||||||
|
X-MS-Exchange-EOPDirect: true
|
||||||
|
Received: from SJ0PR11MB4958.namprd11.prod.outlook.com (2603:10b6:a03:2ae::24)
|
||||||
|
by SA0PR11MB4525.namprd11.prod.outlook.com with HTTPS; Mon, 9 May 2022
|
||||||
|
04:30:48 +0000
|
||||||
|
Received: from BN9PR03CA0117.namprd03.prod.outlook.com (2603:10b6:408:fd::32)
|
||||||
|
by SJ0PR11MB4958.namprd11.prod.outlook.com (2603:10b6:a03:2ae::24) with
|
||||||
|
Microsoft SMTP Server (version=TLS1_2,
|
||||||
|
cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5227.20; Mon, 9 May
|
||||||
|
2022 04:30:45 +0000
|
||||||
|
Received: from BN8NAM11FT053.eop-nam11.prod.protection.outlook.com
|
||||||
|
(2603:10b6:408:fd:cafe::d0) by BN9PR03CA0117.outlook.office365.com
|
||||||
|
(2603:10b6:408:fd::32) with Microsoft SMTP Server (version=TLS1_2,
|
||||||
|
cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5227.20 via Frontend
|
||||||
|
Transport; Mon, 9 May 2022 04:30:45 +0000
|
||||||
|
Authentication-Results: spf=pass (sender IP is 176.119.200.162)
|
||||||
|
smtp.mailfrom=simplelogin.co; dkim=pass (signature was verified)
|
||||||
|
header.d=simplelogin.co;dmarc=pass action=none
|
||||||
|
header.from=simplelogin.co;compauth=pass reason=100
|
||||||
|
Received-SPF: Pass (protection.outlook.com: domain of simplelogin.co
|
||||||
|
designates 176.119.200.162 as permitted sender)
|
||||||
|
receiver=protection.outlook.com; client-ip=176.119.200.162;
|
||||||
|
helo=mail-200162.simplelogin.co;
|
||||||
|
Received: from mail-200162.simplelogin.co (176.119.200.162) by
|
||||||
|
BN8NAM11FT053.mail.protection.outlook.com (10.13.177.209) with Microsoft SMTP
|
||||||
|
Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
|
||||||
|
15.20.5227.15 via Frontend Transport; Mon, 9 May 2022 04:30:44 +0000
|
||||||
|
X-IncomingTopHeaderMarker:
|
||||||
|
OriginalChecksum:5EBD8C309CA888838EDC898C63E28E1EC00EF74772276A54C08DA83D658756F4;UpperCasedChecksum:E102374CD208D4ACB2034F1A17F76DA6345BD176395C6D4EADEC3B47BFF41ECC;SizeAsReceived:1262;Count:15
|
||||||
|
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=simplelogin.co;
|
||||||
|
s=dkim; t=1652070640; h=From:To:Subject:Message-ID:Date;
|
||||||
|
bh=Tu2Q0oO5GuGw4CVxDAdixtRKr6jqMWjpH9zEf50uKwg=;
|
||||||
|
b=o6I0Ij1CahU9EUj/9uwWJpsDjfi/2gQIXT0KJT6IAK9hOoJ5bVqPsqtyGTfIoqYhhtD/ic
|
||||||
|
5NybKJmB6B6KL5hl5LG3KzCdaWfe3dAAhD4e2gIU80dal596dlzluyvLR1k+6rdM4JvlGq
|
||||||
|
OVWLR42Oj4anrnOqLCUkL44ILIhLpAE=
|
||||||
|
Date: Mon, 9 May 2022 00:30:38 -0400 (EDT)
|
||||||
|
Message-ID:
|
||||||
|
<10627474.1041327707.1652070638478.JavaMail.cloud@p2-mta-0301.p2.messagegears.net>
|
||||||
|
Subject: Original Subject
|
||||||
|
Content-Type: multipart/mixed;
|
||||||
|
boundary="----=_Part_1041327705_575167926.1652070638478"
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
X-SimpleLogin-Type: Forward
|
||||||
|
X-SimpleLogin-EmailLog-ID: 832832
|
||||||
|
X-SimpleLogin-Envelope-To: {{ rcpt }}
|
||||||
|
From: {{ sender }}
|
||||||
|
Reply-To: {{ sender }}
|
||||||
|
To: {{ rcpt_comma_list }}
|
||||||
|
List-Unsubscribe: <mailto:unsubscribe@simplelogin.co?subject=3134388=>
|
||||||
|
X-SimpleLogin-Want-Signing: yes
|
||||||
|
X-IncomingHeaderCount: 15
|
||||||
|
Return-Path: {{ return_path }}
|
||||||
|
X-MS-Exchange-Organization-ExpirationStartTime: 09 May 2022 04:30:45.1195
|
||||||
|
(UTC)
|
||||||
|
X-MS-Exchange-Organization-ExpirationStartTimeReason: OriginalSubmit
|
||||||
|
X-MS-Exchange-Organization-ExpirationInterval: 1:00:00:00.0000000
|
||||||
|
X-MS-Exchange-Organization-ExpirationIntervalReason: OriginalSubmit
|
||||||
|
X-MS-Exchange-Organization-Network-Message-Id:
|
||||||
|
ede92e41-5acb-4474-c5be-08da3174af2b
|
||||||
|
X-EOPAttributedMessage: 0
|
||||||
|
X-EOPTenantAttributedMessage: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa:0
|
||||||
|
X-MS-Exchange-Organization-MessageDirectionality: Incoming
|
||||||
|
X-MS-PublicTrafficType: Email
|
||||||
|
X-MS-Exchange-Organization-AuthSource:
|
||||||
|
BN8NAM11FT053.eop-nam11.prod.protection.outlook.com
|
||||||
|
X-MS-Exchange-Organization-AuthAs: Anonymous
|
||||||
|
X-MS-UserLastLogonTime: 5/9/2022 3:30:52 AM
|
||||||
|
X-MS-Office365-Filtering-Correlation-Id: ede92e41-5acb-4474-c5be-08da3174af2b
|
||||||
|
X-MS-TrafficTypeDiagnostic: SJ0PR11MB4958:EE_
|
||||||
|
X-MS-Exchange-EOPDirect: true
|
||||||
|
X-Sender-IP: 176.119.200.162
|
||||||
|
X-SID-PRA: PHWNQHFTTLQNZJXKMLHZCSKLLLJXMGEJOEOWW@SIMPLELOGIN.CO
|
||||||
|
X-SID-Result: PASS
|
||||||
|
X-MS-Exchange-Organization-PCL: 2
|
||||||
|
X-MS-Exchange-Organization-SCL: 1
|
||||||
|
X-Microsoft-Antispam: BCL:0;
|
||||||
|
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 May 2022 04:30:44.9945
|
||||||
|
(UTC)
|
||||||
|
X-MS-Exchange-CrossTenant-Network-Message-Id:
|
||||||
|
ede92e41-5acb-4474-c5be-08da3174af2b
|
||||||
|
X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa
|
||||||
|
X-MS-Exchange-CrossTenant-AuthSource:
|
||||||
|
BN8NAM11FT053.eop-nam11.prod.protection.outlook.com
|
||||||
|
X-MS-Exchange-CrossTenant-AuthAs: Anonymous
|
||||||
|
X-MS-Exchange-CrossTenant-FromEntityHeader: Internet
|
||||||
|
X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg:
|
||||||
|
00000000-0000-0000-0000-000000000000
|
||||||
|
X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR11MB4958
|
||||||
|
X-MS-Exchange-Transport-EndToEndLatency: 00:00:03.3271765
|
||||||
|
X-MS-Exchange-Processed-By-BccFoldering: 15.20.5227.023
|
||||||
|
X-Microsoft-Antispam-Mailbox-Delivery:
|
||||||
|
abwl:0;wl:0;pcwl:0;kl:0;iwl:0;ijl:0;dwl:0;dkl:0;rwl:0;ucf:0;jmr:0;ex:0;auth:1;dest:I;ENG:(5062000285)(90000117)(90005022)(91005020)(91035115)(5061607266)(5061608174)(9050020)(9100338)(2008001134)(2008000189)(2008120399)(2008019284)(2008021020)(8390246)(8377080)(8386120)(4810004)(4910013)(9910022)(9510006)(10110021)(9320005);
|
||||||
|
X-Message-Info:
|
||||||
|
5vMbyqxGkdcvoPRAk5ACFywqndfpuBMcVz6K/12RtMALmdfGi+GpgO+lXQe3PiGwHtV5wXFRStQwg29XySZZo6tOyvshTSJ1uafhX53S93r5MaqDxJrR0UNGr2VYdKiAm1jYIYQm84v/mEbSAGjjBwEgS1PHlzM72I96JadXzfV9Fmsd5pHlfoLxEqXe6hBJAAQS99CcpwPDnaVA9UZUHA==
|
||||||
|
X-Message-Delivery: Vj0xLjE7dXM9MDtsPTA7YT0wO0Q9MTtHRD0xO1NDTD0tMQ==
|
||||||
|
X-Microsoft-Antispam-Message-Info:
|
||||||
|
=?utf-8?B?VjZIQkpKR05oRUo1Vzc0YTBDUW52S0lsYkJSMGRzY0hJMnRMOWdyRGowcGpk?=
|
||||||
|
=?utf-8?B?SUJLSDRPaStzakpJUHlaWVFnNWpBSGRsZ1Z4aEFmaXJOR1ZMUWxTTnQ1SXg1?=
|
||||||
|
=?utf-8?B?anhFNTJ5RGU2YjRiTWhWK3FvWXBJU29YSWdqM3VvUkZpY21aaW5lSkJ5WWph?=
|
||||||
|
=?utf-8?B?L2pxclptbVBGdm02emlHT3ZBQ1BHZTcrM0c3NmJ5alJLSGlaYVMvK0hwVmJV?=
|
||||||
|
=?utf-8?B?eHlTU2grSElBTVY5cXF2d250OXBmQ2pzeEVUWTlSZ1hCc1dEdStXMzFGcWlO?=
|
||||||
|
=?utf-8?B?VytUeEgyRWl5a2U1Y09VKyt3am9ZQVYrRm1LUkhRRGdKbkFTaHc4RTErQ1c0?=
|
||||||
|
=?utf-8?B?RjBNVllEVW9UakJIQm5FWWVYd2RuaENZTVJIUkI4RmlheWsyajZmanFCUlpt?=
|
||||||
|
=?utf-8?B?ZTJYZlg1RGxkbEVlRk0zallRWStiU1Z1QmJlTmtKS3J5MmZuOFk2blRHemEw?=
|
||||||
|
=?utf-8?B?OVhkUUhWWTAzV2dySnMra1pKMGo1Zy8xSFNuemx4Slg1ckhDcitmVGRHSDBW?=
|
||||||
|
=?utf-8?B?MFlOMDFtNmRPTDVSL3BGU0VNNWRObGVkUUlRcG9MSUJFeVBFcGtlVENSZmIr?=
|
||||||
|
=?utf-8?B?V3F6by8vOHBROWplTi9JdWtEVDFwUVZsdVk5djBtN0wzbk04RG56RjRsM1ZH?=
|
||||||
|
=?utf-8?B?cytsajBZNUNwUXk5SVRFZXhMejN3anYweGpCWkltQ2lwQnA3V1B6UUt0VUw1?=
|
||||||
|
=?utf-8?B?dXpLQ3hxemNQNWRGWmpqZi9BY2EzOTAwQ3h5RlF2RHQyVG1McWp6N1JXUWRY?=
|
||||||
|
=?utf-8?B?TjlCRWFmNFhQSitwSTk2cEhPK1N3ZVQxbktlMWFwa05hNGllOVpCc2Q3MUEy?=
|
||||||
|
=?utf-8?B?TlBHVE9YUE8xRUk3dndyNkFQVlhhN3JIMnUxL25pZ3JaM1hFS0VUOXNqT2NF?=
|
||||||
|
=?utf-8?B?Y3lFcUM0dDVuOGhTdmJ1RjJJK2sxZGViOUU2SE1DTUZ1c0pSSlNsazdPWHJ5?=
|
||||||
|
=?utf-8?B?TXo0dUUrZEhqaVpGTHNTUnNUTUl2L2hZeFhoNUVtcmJPQ0lXYnV5Yy8rSXBq?=
|
||||||
|
=?utf-8?B?bjYwVlBET0ErZkQ4KzJsQmM5b0hUTXJSSWlhdXlNeTZ2a0xlaHp5ZTZRQnox?=
|
||||||
|
=?utf-8?B?T2h2NkZKNmpLcDg4TCs5ckdoU3d5aEc1Q1FYUFdTOXhxcFJsaTdtZkVuNG1W?=
|
||||||
|
=?utf-8?B?SkVsN2llT3FpTnB6Q3lMbDR4ZzVzblhLVWw3VkpJblRQQVA4cDd1aGdtbll4?=
|
||||||
|
=?utf-8?B?U2RWQXplZjRreWhJRnQwWGhWT2pnVmxwTW9hdUxwRE9VaTJqd1lqenh3T2pK?=
|
||||||
|
=?utf-8?B?R2ZMaDJmNm1lS25TNU56ODFBcnc1TUZQbi9pZ0hnampKNUl0MzVQRG5wenZH?=
|
||||||
|
=?utf-8?B?dTdrcTA4VXUwZmdNaXBKMnVsY1phOEtLUEZWMzNnUlVxYXhrRDFUN3FFN0lZ?=
|
||||||
|
=?utf-8?B?MnVzbmhVQ2kvQVkzZ3NBQnNGL0NCNlZTbmV5ZW9FVWg5dUJTbmtaQnNZemRT?=
|
||||||
|
=?utf-8?B?cDFKUnRPU2VpNnNwM3V5eXJxMy9YbFhPYTRFSkEyTUZjSVlNaFV0UE5RbjhK?=
|
||||||
|
=?utf-8?B?NjJmckpva2xuaGhYT2Jkb2g1U1NEaFJmQWc5bVhheGZYMXY1b2toaVRPOXNT?=
|
||||||
|
=?utf-8?B?Y2ZhVjYyY0pnbmw4N3VneVR6bXFoRTlndE9lTzlac0JTRWFKc1BMTmNrNFMx?=
|
||||||
|
=?utf-8?B?M0lwTXI3STZXcFNmbytNcFB2VzJFSFpLSWFpbjlzcVlVRHk3RTFIUUQzOUlB?=
|
||||||
|
=?utf-8?B?YnR1eC9jUnVNWlhadktVKzM5MmdmR1pBTXVxK2xzUXZ4MzNUWW5rQXZ4SXMv?=
|
||||||
|
=?utf-8?B?RnBLUmcwT3FUWENucWtuTWhBQnl5VWFpczNGUnBkQ0ltM2ttMDM1RnFScXFa?=
|
||||||
|
=?utf-8?B?dEtNNnF4Q1FDS2RqRTRuRkNRUC9JVTdZZ216c3hycC9ZalptbDZNZ25ydWFp?=
|
||||||
|
=?utf-8?B?Z25qMGFLK1FQYm0vUU40OSt1SVJBTmdPTVNRN2JTVmxLTlRJMkZDeldKYWNx?=
|
||||||
|
=?utf-8?B?VEJEVHE5ZE9QNWsxZkxrb0pFOEU5cUJvT3ArOUFDMXlZM2N4Smk5ay9qQXEv?=
|
||||||
|
=?utf-8?B?ZXc3ZjVHMjdkcjBkN1Rodmdyd1JldkFBeDlVblRVbkxrY0xhZkIwVzBpTlNM?=
|
||||||
|
=?utf-8?B?THAvZ01hS3NVK0dHblFFQ0h6VXYydW1QaUwzM29zcjRYRFJRTU9NZWYxQ2Nw?=
|
||||||
|
=?utf-8?B?N1liQ3g2ZUtveTdTaW1ZSGovLzNWbWh2bDd6ZXRUR3B3eEYwakVCOS95aEs0?=
|
||||||
|
=?utf-8?B?NkkzL1dQREVlVHFXWmE4RktDUHFENVQwYW9YWE9LS2hrMzAyVWFXTDZFVkx5?=
|
||||||
|
=?utf-8?B?cU1nZDkzOTR1dk40SHFIcHRDSVRPajMvSVAyd0JQNDJnaVoxNmhNOFEzdzlj?=
|
||||||
|
=?utf-8?B?ODdUNXRIVkQvTHYzMytWY2o3UHZkdUNTR1pvSVJvclVCN01EZW5pVXdRUDgx?=
|
||||||
|
=?utf-8?B?Vmg2aUdlOUJzdXlPdXFlL01raHZSbkRONncyRlFLcGpLUFR4bm9BQXVJMHJC?=
|
||||||
|
=?utf-8?B?cWdJSFJwZEVkZjZkOTJqZG1FNHdZRWpGdUR6R2hjdHRoMTg1Z2lpeGpnZzlH?=
|
||||||
|
=?utf-8?B?Um5WOEJINFBFM3Evdmt4VVRCQnAwd2xBRGVralpwRnV0eUhJNTluQzFLQXI2?=
|
||||||
|
=?utf-8?B?NXI4amV3c0ZRZEZLRjE1ZEQ3aW90Y1I0K3NPN3ZoVyt1UVdzWUpQUGh1b25N?=
|
||||||
|
=?utf-8?Q?amuRKzTLQzIrlx9Vmv+SjIosxogY=3D?=
|
||||||
|
MIME-Version: 1.0
|
||||||
|
|
||||||
|
------=_Part_1041327705_575167926.1652070638478
|
||||||
|
Content-Type: multipart/related;
|
||||||
|
boundary="----=_Part_1041327706_445426653.1652070638478"
|
||||||
|
|
||||||
|
------=_Part_1041327706_445426653.1652070638478
|
||||||
|
Content-Type: text/html;charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
|
||||||
|
Here goes the original email content
|
||||||
|
|
||||||
|
------=_Part_1041327706_445426653.1652070638478--
|
||||||
|
|
||||||
|
------=_Part_1041327705_575167926.1652070638478--
|
||||||
|
|
||||||
|
--31A9507D-D0B3-4DCD-AFBB-413468892CFE--
|
157
tests/example_emls/yahoo_complaint.eml
Normal file
157
tests/example_emls/yahoo_complaint.eml
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
X-SimpleLogin-Client-IP: 66.163.186.21
|
||||||
|
Received-SPF: None (mailfrom) identity=mailfrom; client-ip=66.163.186.21;
|
||||||
|
helo=sonic326-46.consmr.mail.ne1.yahoo.com;
|
||||||
|
envelope-from=feedback@arf.mail.yahoo.com; receiver=<UNKNOWN>
|
||||||
|
Received: from sonic326-46.consmr.mail.ne1.yahoo.com
|
||||||
|
(sonic326-46.consmr.mail.ne1.yahoo.com [66.163.186.21])
|
||||||
|
(using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)
|
||||||
|
key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits)
|
||||||
|
server-digest SHA256)
|
||||||
|
(No client certificate requested)
|
||||||
|
by prod4.simplelogin.co (Postfix) with ESMTPS id 160E19C47C
|
||||||
|
for <{{ postmaster }}>; Sun, 8 May 2022 13:31:32 +0000 (UTC)
|
||||||
|
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arf.mail.yahoo.com;
|
||||||
|
s=arf; t=1652016690; bh=y3TXlG8d2nUmz+Mm6gBEX1p1y2rwlM+LRC89Bp+HwGo=;
|
||||||
|
h=Date:From:To:Subject:From:Subject:Reply-To;
|
||||||
|
b=HyuY58LSzfkdH9FynjNWEl6QJeeImKRbIzrnR64sY/ggFD6fF9w1/fpXDmJ8RHpB/72llGb8nkVJkn/TK+adBCZvw4Y0SC2m8qbn6BdaC5kvAWkN6VUxvQWFMWTptAmeX+UUxY2hjEXLZQwNUd4nvvhZkbdyzw5wFSpYX0hnxAA=
|
||||||
|
X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048;
|
||||||
|
t=1652016690; bh=0SlXAOx+1D8SxkBJpASrTwUGjphtzchFZOSJr0X+U2m=;
|
||||||
|
h=X-Sonic-MF:Date:From:To:Subject:From:Subject;
|
||||||
|
b=smqcDrz5jxsmGycWk9tNncLBjcQIqBnZmsQzkJ6g8fyhQw2e30y05iTnsOBTr0S9qTPK3I2JBv0P73TH7vDAnZAnaewzj9Dymw7Z+UxXKdrPBf/tD8RGw9cX6C0eb7GUjHvbvXS03IkSGnvOPPCXLsTDXYOTflcU7A0A2L+cS9ogEBl/4AFwBf/z+lcMH20h2dZ6+wPtqPCgRY1Hf45cv4gfHrFG0a18n3BBq0doCA4cRTXeeuv06fqsUCk2GF6z0mm3YWu+umcUs16QmgjHKhy4SJHvTZfx4zFBxQEOM3hvBzriL5g0D3Rg71CdkI8TVqsyXS1YWVSQFakAw0hM+A==
|
||||||
|
X-Sonic-MF: feedback@arf.mail.yahoo.com
|
||||||
|
Received: from sonic.gate.mail.ne1.yahoo.com by
|
||||||
|
sonic326.consmr.mail.ne1.yahoo.com with HTTP; Sun, 8 May 2022 13:31:30 +0000
|
||||||
|
Date: Sun, 8 May 2022 13:31:28 +0000 (UTC)
|
||||||
|
From: Yahoo! Mail AntiSpam Feedback <feedback@arf.mail.yahoo.com>
|
||||||
|
To: {{ postmaster }}
|
||||||
|
Message-ID:
|
||||||
|
<1486688083.18136997.1652016688605@chakraconsumer2.asd.mail.ne1.yahoo.com>
|
||||||
|
Subject: Original subject
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: multipart/report; report-type=feedback-report;
|
||||||
|
boundary="----=_Part_18136996_1734597748.1652016688604"
|
||||||
|
X-Yahoo-Newman-Property: cfl
|
||||||
|
X-Yahoo-Newman-Id: cfl-test
|
||||||
|
X-Spamd-Result: default: False [-0.65 / 13.00];
|
||||||
|
DMARC_POLICY_ALLOW(-0.50)[yahoo.com,reject];
|
||||||
|
R_DKIM_ALLOW(-0.20)[arf.mail.yahoo.com:s=arf];
|
||||||
|
SUBJ_ALL_CAPS(0.15)[2];
|
||||||
|
MIME_GOOD(-0.10)[text/plain,multipart/alternative];
|
||||||
|
R_SPF_NA(0.00)[no SPF record];
|
||||||
|
FROM_EQ_ENVFROM(0.00)[];
|
||||||
|
MIME_TRACE(0.00)[0:~,1:+,2:~,3:+,4:~,5:+,6:+,7:~];
|
||||||
|
RCVD_TLS_LAST(0.00)[];
|
||||||
|
RCVD_IN_DNSWL_NONE(0.00)[66.163.186.21:from];
|
||||||
|
ASN(0.00)[asn:36646, ipnet:66.163.184.0/21, country:US];
|
||||||
|
ARC_NA(0.00)[];
|
||||||
|
DKIM_TRACE(0.00)[arf.mail.yahoo.com:+];
|
||||||
|
MID_RHS_MATCH_FROMTLD(0.00)[];
|
||||||
|
TO_MATCH_ENVRCPT_ALL(0.00)[];
|
||||||
|
FROM_HAS_DN(0.00)[];
|
||||||
|
RCVD_COUNT_TWO(0.00)[2];
|
||||||
|
TO_DN_NONE(0.00)[];
|
||||||
|
RCPT_COUNT_ONE(0.00)[1];
|
||||||
|
NEURAL_SPAM(0.00)[0.429];
|
||||||
|
DWL_DNSWL_NONE(0.00)[yahoo.com:dkim]
|
||||||
|
X-Rspamd-Queue-Id: 160E19C47C
|
||||||
|
X-Rspamd-Server: prod4
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
------=_Part_18136996_1734597748.1652016688604
|
||||||
|
Content-Type: text/plain; charset=us-ascii
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
Content-Disposition: inline
|
||||||
|
|
||||||
|
This is an email abuse report for an email message from simplelogin.co on Sun, 8 May 2022 11:12:35 +0000
|
||||||
|
|
||||||
|
------=_Part_18136996_1734597748.1652016688604
|
||||||
|
Content-Type: message/feedback-report
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
Content-Disposition: inline
|
||||||
|
|
||||||
|
Feedback-Type: abuse
|
||||||
|
User-Agent: Yahoo!-Mail-Feedback/2.0
|
||||||
|
Version: 0.1
|
||||||
|
Original-Mail-From:
|
||||||
|
<{{ return_path }}>
|
||||||
|
Original-Rcpt-To: {{ rcpt }}
|
||||||
|
Received-Date: Sun, 8 May 2022 11:12:35 +0000
|
||||||
|
Reported-Domain: simplelogin.co
|
||||||
|
Authentication-Results: authentication result string is not available
|
||||||
|
|
||||||
|
|
||||||
|
------=_Part_18136996_1734597748.1652016688604
|
||||||
|
Content-Type: message/rfc822
|
||||||
|
Content-Disposition: inline
|
||||||
|
|
||||||
|
Received: from 10.217.151.74
|
||||||
|
by atlas316.free.mail.ne1.yahoo.com with HTTPS;
|
||||||
|
Sun, 8 May 2022 11:12:34 +0000
|
||||||
|
Return-Path:
|
||||||
|
<{{ return_path }}>
|
||||||
|
X-Originating-Ip: [176.129.238.160]
|
||||||
|
Received-SPF: pass (domain of simplelogin.co designates 176.119.200.160 as
|
||||||
|
permitted sender)
|
||||||
|
Authentication-Results: atlas316.free.mail.ne1.yahoo.com;
|
||||||
|
dkim=pass header.i=@simplelogin.co header.s=dkim;
|
||||||
|
spf=pass smtp.mailfrom=simplelogin.co;
|
||||||
|
dmarc=pass(p=QUARANTINE) header.from=simplelogin.co;
|
||||||
|
X-Apparently-To: syn_flood91@yahoo.com; Sun, 8 May 2022 11:12:35 +0000
|
||||||
|
X-YMailISG: 5XbMksQWLDvXV9CBjagtqIT6OTC44ku5XiuZJQp_W6hhWfR.
|
||||||
|
.wUIhFV6vRR_JeMUxC0ZAvugteAP2pe.bqk06ovvYnhJMg_HTvcmfVltbWxQ
|
||||||
|
tK7xNSs8D2PWQdyDDzB3rdFdIIfSrQnDTGjP2xpTAqLQk3IXSuUBX7s4f8uA
|
||||||
|
WUELPWj36_Xtqrwyj.ya4Ezw_ePzPhZGmMdCsbz2H5Jh45TLbk5HhL.TDDbH
|
||||||
|
9Dz__HKLUC8acH0hu1vrPvo1ljzwbl_0cqlj10qMIChpB51XVDtyNA_WgWvE
|
||||||
|
QL1hFHS0tScfRT0xATM8w8FJv1eA0ODjakDtTRgmaWBTphzeoR.FyTBj14y5
|
||||||
|
burx6lkUqipfP7UZpNmcNDYHQdTEmdGa8JDZMX.lpM5IMOhkByIQuoTN4.Cx
|
||||||
|
8qz9kb.o0DqxqNRgn4_fRRAoSn1xejDbzZMu.SWSvJ1KJwAfLtep37ISqNKl
|
||||||
|
yeBeDJFMnHUjRD8B2wBB46zq4ngHFWjBGkAGQVBssLzj594FXg13aO.TnJU7
|
||||||
|
WJ_cUSzoaH9HjgYDTi4.1x68jVxpZIEdhDe7pjLCUL2ugWdar9S7pFlyKWfa
|
||||||
|
iTH8yQ10NXtLCwGpJ.0kgZH2WXJgyJmrq0a3j63skib7WJYtKOXfsbHV8b9e
|
||||||
|
WxClOETCe03PtdD6G2sjEJSNFyTH_Qzzq6_21PO6kjmnEnBbibAnkiJbGhIJ
|
||||||
|
kOSqyp_vFqstpd38vtt7iLI8L3PkyZDQXS0hB1ZCOsZqBDGJXAoWFRBtxMSd
|
||||||
|
rMVkdvB6r8xJtn.1JrV1hpX4yRbCuEnCCPcwtGamlpyq5LG6YanKUVB868KF
|
||||||
|
UuZ4AHFwi.m_FYHalwtfCaArtWzYybl2nQQLjPbnXxqNvfwKt3ATKFEO40ZV
|
||||||
|
w1Ri7y.cO__09.eQHKIUNgMNeWgt.luD3thsEl0yz_ThzrCEkXDB1xAPNnLV
|
||||||
|
tb03RulEB0xNauYTuWgKR8WJzkO4LuXMlzNAAYBQLQy_t0GoezAs7Z4oq.CH
|
||||||
|
EfTK88cDJ7j7dXcXBi7q6g1NBZT3tyd9Bfn2DVdFaWAjWV9Lb8tir6J43MDP
|
||||||
|
byTrZ_zJxTWKgafhOxL0gZbd5xIEZ1eHHeQO5pVZlN6FR1awozFgS4NcZu5u
|
||||||
|
5qRtn6zHo3zNe9ORwwxqlHAEJR_5I09WYSdmTxh2QkkDQLjSlwUNV4K8jxdH
|
||||||
|
L4ePIzNCQCt_bsGoG3uPXl8jtPD4sUWGY1lCeKAm.AHgZ.pSXXypMUpq4y14
|
||||||
|
NihY89H61y5ZXo4Zd77shda_
|
||||||
|
Received: from 176.119.200.160 (EHLO mail-200160.simplelogin.co)
|
||||||
|
by 10.217.151.74 with SMTPs
|
||||||
|
(version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256);
|
||||||
|
Sun, 08 May 2022 11:12:34 +0000
|
||||||
|
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=simplelogin.co;
|
||||||
|
s=dkim; t=1652008349; h=From:To:Subject:Message-ID:Date;
|
||||||
|
bh=9HnrBUpZUe8OSXqTw1qF667IwLtHI8DqiyD0yAovIO4=;
|
||||||
|
b=PsxiMydvEQveb20xgUvvq3DhxlLyqqoPW7sC8d/pAm8tj7T2O+7z5xxR6vVbgz823Bglzc
|
||||||
|
djb3pRvNLgHnTozC+FiFOF8nVlWGybosn5oRfmNGkF9bhr0bJmfcDhiuC/tOaZKkod2lbf
|
||||||
|
jQ8bqMZhCsN/xVpkMqJdNJefdkj3dP4=
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Date: Sun, 8 May 2022 04:11:42 -0700
|
||||||
|
Message-ID:
|
||||||
|
<CAKGh96GHg2kuwvm4biQ-PF-4-8SPZ6JyPj-=GpoYZ6njctoRtg@mail.gmail.com>
|
||||||
|
Subject: MF
|
||||||
|
Content-Type: multipart/alternative; boundary="0000000000006dd95f05de7e2a70"
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
X-SimpleLogin-Type: Forward
|
||||||
|
X-SimpleLogin-EmailLog-ID: 41263490
|
||||||
|
X-SimpleLogin-Envelope-From: {{ sender }}
|
||||||
|
X-SimpleLogin-Envelope-To: {{ rcpt }}
|
||||||
|
From: {{ sender }}
|
||||||
|
To: {{ rcpt_comma_list }}
|
||||||
|
List-Unsubscribe: <mailto:unsubscribe@simplelogin.co?subject=1231546=>
|
||||||
|
X-SimpleLogin-Want-Signing: yes
|
||||||
|
Content-Length: 473
|
||||||
|
|
||||||
|
--0000000000006dd95f05de7e2a70
|
||||||
|
Content-Type: text/plain; charset="UTF-8"
|
||||||
|
|
||||||
|
Here goes the original email content
|
||||||
|
|
||||||
|
--0000000000006dd95f05de7e2a70--
|
||||||
|
|
||||||
|
|
||||||
|
------=_Part_18136996_1734597748.1652016688604--
|
|
@ -1,51 +1,70 @@
|
||||||
import email
|
|
||||||
from email.message import Message
|
from email.message import Message
|
||||||
from email.mime.multipart import MIMEMultipart
|
|
||||||
from email.mime.text import MIMEText
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from app.config import (
|
from app.config import (
|
||||||
ALERT_COMPLAINT_FORWARD_PHASE,
|
ALERT_COMPLAINT_FORWARD_PHASE,
|
||||||
ALERT_COMPLAINT_REPLY_PHASE,
|
ALERT_COMPLAINT_REPLY_PHASE,
|
||||||
ALERT_COMPLAINT_TRANSACTIONAL_PHASE,
|
ALERT_COMPLAINT_TRANSACTIONAL_PHASE,
|
||||||
|
POSTMASTER,
|
||||||
)
|
)
|
||||||
from app.db import Session
|
from app.db import Session
|
||||||
from app.email import headers
|
from app.email_utils import generate_verp_email
|
||||||
from app.handler.provider_complaint import (
|
from app.handler.provider_complaint import (
|
||||||
handle_hotmail_complaint,
|
handle_hotmail_complaint,
|
||||||
handle_yahoo_complaint,
|
handle_yahoo_complaint,
|
||||||
)
|
)
|
||||||
from app.models import Alias, ProviderComplaint, SentAlert
|
from app.models import (
|
||||||
from tests.utils import create_new_user
|
Alias,
|
||||||
|
ProviderComplaint,
|
||||||
|
SentAlert,
|
||||||
|
EmailLog,
|
||||||
|
VerpType,
|
||||||
|
Contact,
|
||||||
|
)
|
||||||
|
from tests.utils import create_new_user, load_eml_file
|
||||||
|
|
||||||
origins = [
|
origins = [
|
||||||
[handle_yahoo_complaint, "yahoo", 6],
|
[handle_yahoo_complaint, "yahoo"],
|
||||||
[handle_hotmail_complaint, "hotmail", 3],
|
[handle_hotmail_complaint, "hotmail"],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def prepare_complaint(message: Message, part_num: int) -> Message:
|
def prepare_complaint(
|
||||||
complaint = MIMEMultipart("related")
|
provider_name: str, alias: Alias, rcpt_address: str, sender_address: str
|
||||||
# When walking, part 0 is the full message so we -1, and we want to be part N so -1 again
|
) -> Message:
|
||||||
for i in range(part_num - 2):
|
contact = Contact.create(
|
||||||
document = MIMEText("text", "plain")
|
user_id=alias.user.id,
|
||||||
document.set_payload(f"Part {i}")
|
alias_id=alias.id,
|
||||||
complaint.attach(document)
|
website_email="a@b.c",
|
||||||
complaint.attach(message)
|
reply_email="d@e.f",
|
||||||
|
commit=True,
|
||||||
return email.message_from_bytes(complaint.as_bytes())
|
)
|
||||||
|
elog = EmailLog.create(
|
||||||
|
user_id=alias.user.id,
|
||||||
|
mailbox_id=alias.user.default_mailbox_id,
|
||||||
|
contact_id=contact.id,
|
||||||
|
commit=True,
|
||||||
|
bounced=True,
|
||||||
|
)
|
||||||
|
return_path = generate_verp_email(VerpType.bounce_forward, elog.id)
|
||||||
|
return load_eml_file(
|
||||||
|
f"{provider_name}_complaint.eml",
|
||||||
|
{
|
||||||
|
"postmaster": POSTMASTER,
|
||||||
|
"return_path": return_path,
|
||||||
|
"rcpt": rcpt_address,
|
||||||
|
"sender": sender_address,
|
||||||
|
"rcpt_comma_list": f"{rcpt_address},other_rcpt@somwhere.net",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("handle_ftor,provider,part_num", origins)
|
@pytest.mark.parametrize("handle_ftor,provider", origins)
|
||||||
def test_provider_to_user(flask_client, handle_ftor, provider, part_num):
|
def test_provider_to_user(flask_client, handle_ftor, provider):
|
||||||
user = create_new_user()
|
user = create_new_user()
|
||||||
original_message = Message()
|
alias = Alias.create_new_random(user)
|
||||||
original_message[headers.TO] = user.email
|
Session.commit()
|
||||||
original_message[headers.FROM] = "nobody@nowhere.net"
|
complaint = prepare_complaint(provider, alias, user.email, "nobody@nowhere.net")
|
||||||
original_message.set_payload("Contents")
|
|
||||||
|
|
||||||
complaint = prepare_complaint(original_message, part_num)
|
|
||||||
assert handle_ftor(complaint)
|
assert handle_ftor(complaint)
|
||||||
found = ProviderComplaint.filter_by(user_id=user.id).all()
|
found = ProviderComplaint.filter_by(user_id=user.id).all()
|
||||||
assert len(found) == 0
|
assert len(found) == 0
|
||||||
|
@ -54,17 +73,12 @@ def test_provider_to_user(flask_client, handle_ftor, provider, part_num):
|
||||||
assert alerts[0].alert_type == f"{ALERT_COMPLAINT_TRANSACTIONAL_PHASE}_{provider}"
|
assert alerts[0].alert_type == f"{ALERT_COMPLAINT_TRANSACTIONAL_PHASE}_{provider}"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("handle_ftor,provider,part_num", origins)
|
@pytest.mark.parametrize("handle_ftor,provider", origins)
|
||||||
def test_provider_forward_phase(flask_client, handle_ftor, provider, part_num):
|
def test_provider_forward_phase(flask_client, handle_ftor, provider):
|
||||||
user = create_new_user()
|
user = create_new_user()
|
||||||
alias = Alias.create_new_random(user)
|
alias = Alias.create_new_random(user)
|
||||||
Session.commit()
|
Session.commit()
|
||||||
original_message = Message()
|
complaint = prepare_complaint(provider, alias, "nobody@nowhere.net", alias.email)
|
||||||
original_message[headers.TO] = "nobody@nowhere.net"
|
|
||||||
original_message[headers.FROM] = alias.email
|
|
||||||
original_message.set_payload("Contents")
|
|
||||||
|
|
||||||
complaint = prepare_complaint(original_message, part_num)
|
|
||||||
assert handle_ftor(complaint)
|
assert handle_ftor(complaint)
|
||||||
found = ProviderComplaint.filter_by(user_id=user.id).all()
|
found = ProviderComplaint.filter_by(user_id=user.id).all()
|
||||||
assert len(found) == 1
|
assert len(found) == 1
|
||||||
|
@ -73,17 +87,12 @@ def test_provider_forward_phase(flask_client, handle_ftor, provider, part_num):
|
||||||
assert alerts[0].alert_type == f"{ALERT_COMPLAINT_REPLY_PHASE}_{provider}"
|
assert alerts[0].alert_type == f"{ALERT_COMPLAINT_REPLY_PHASE}_{provider}"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("handle_ftor,provider,part_num", origins)
|
@pytest.mark.parametrize("handle_ftor,provider", origins)
|
||||||
def test_provider_reply_phase(flask_client, handle_ftor, provider, part_num):
|
def test_provider_reply_phase(flask_client, handle_ftor, provider):
|
||||||
user = create_new_user()
|
user = create_new_user()
|
||||||
alias = Alias.create_new_random(user)
|
alias = Alias.create_new_random(user)
|
||||||
Session.commit()
|
Session.commit()
|
||||||
original_message = Message()
|
complaint = prepare_complaint(provider, alias, alias.email, "no@no.no")
|
||||||
original_message[headers.TO] = alias.email
|
|
||||||
original_message[headers.FROM] = "no@no.no"
|
|
||||||
original_message.set_payload("Contents")
|
|
||||||
|
|
||||||
complaint = prepare_complaint(original_message, part_num)
|
|
||||||
assert handle_ftor(complaint)
|
assert handle_ftor(complaint)
|
||||||
found = ProviderComplaint.filter_by(user_id=user.id).all()
|
found = ProviderComplaint.filter_by(user_id=user.id).all()
|
||||||
assert len(found) == 0
|
assert len(found) == 0
|
||||||
|
|
|
@ -60,3 +60,5 @@ DMARC_CHECK_ENABLED=true
|
||||||
PROTON_CLIENT_ID=to_fill
|
PROTON_CLIENT_ID=to_fill
|
||||||
PROTON_CLIENT_SECRET=to_fill
|
PROTON_CLIENT_SECRET=to_fill
|
||||||
PROTON_BASE_URL=https://localhost/api
|
PROTON_BASE_URL=https://localhost/api
|
||||||
|
|
||||||
|
POSTMASTER=postmaster@test.domain
|
Loading…
Reference in a new issue