Skip to content

Commit

Permalink
add get_mailbox_bounce_info()
Browse files Browse the repository at this point in the history
  • Loading branch information
Son committed Oct 14, 2021
1 parent e5a7aeb commit 3bdeda3
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 8 deletions.
45 changes: 38 additions & 7 deletions app/email_utils.py
Expand Up @@ -598,22 +598,53 @@ def mailbox_already_used(email: str, user) -> bool:
return False


def get_orig_message_from_bounce(msg: Message) -> Message:
def get_orig_message_from_bounce(bounce_report: Message) -> Optional[Message]:
"""parse the original email from Bounce"""
i = 0
for part in msg.walk():
for part in bounce_report.walk():
i += 1

# the original message is the 4th part
# 1st part is the root part, multipart/report
# 2nd is text/plain, Postfix log
# 1st part is the container (bounce report)
# 2nd part is the report from our own Postfix
# 3rd is report from other mailbox
# 4th is the container of the original message
# ...
# 7th is original message
if i == 7:
return part


def get_orig_message_from_hotmail_complaint(msg: Message) -> Message:
def get_mailbox_bounce_info(bounce_report: Message) -> Optional[Message]:
"""
Return the bounce info from the bounce report
An example of bounce info:
Final-Recipient: rfc822; not-existing@gmail.com
Original-Recipient: rfc822;not-existing@gmail.com
Action: failed
Status: 5.1.1
Remote-MTA: dns; gmail-smtp-in.l.google.com
Diagnostic-Code: smtp;
550-5.1.1 The email account that you tried to reach does
not exist. Please try 550-5.1.1 double-checking the recipient's email
address for typos or 550-5.1.1 unnecessary spaces. Learn more at 550 5.1.1
https://support.google.com/mail/?p=NoSuchUser z127si6173191wmc.132 - gsmtp
"""
i = 0
for part in bounce_report.walk():
i += 1

# 1st part is the container (bounce report)
# 2nd part is the report from our own Postfix
# 3rd is report from other mailbox
# 4th is the container of the original message
# 5th is a child of 3rd that contains more info about the bounce
if i == 5:
return part


def get_orig_message_from_hotmail_complaint(msg: Message) -> Optional[Message]:
i = 0
for part in msg.walk():
i += 1
Expand All @@ -625,7 +656,7 @@ def get_orig_message_from_hotmail_complaint(msg: Message) -> Message:
return part


def get_orig_message_from_yahoo_complaint(msg: Message) -> Message:
def get_orig_message_from_yahoo_complaint(msg: Message) -> Optional[Message]:
i = 0
for part in msg.walk():
i += 1
Expand Down
102 changes: 102 additions & 0 deletions local_data/email_tests/bounce.eml
@@ -0,0 +1,102 @@
Received: by mx1.sl.co (Postfix)
id F09806333D; Thu, 14 Oct 2021 09:14:44 +0000 (UTC)
Date: Thu, 14 Oct 2021 09:14:44 +0000 (UTC)
From: mailer-daemon@bounce.sl.co (Mail Delivery System)
Subject: Undelivered Mail Returned to Sender
To: bounce+5352+@sl.co
Auto-Submitted: auto-replied
MIME-Version: 1.0
Content-Type: multipart/report; report-type=delivery-status;
boundary="8A32A6333B.1634202884/mx1.sl.co"
Content-Transfer-Encoding: 8bit
Message-Id: <20211014091444.F09806333D@mx1.sl.co>

This is a MIME-encapsulated message.

--8A32A6333B.1634202884/mx1.sl.co
Content-Description: Notification
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
This is the mail system at host mx1.sl.co.
I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.
For further assistance, please send mail to <postmaster@sl.co>
If you do so, please include this problem report. You can
delete your own text from the attached returned message.
The mail system
<not-existing@gmail.com>: host
gmail-smtp-in.l.google.com[142.251.5.27] said: 550-5.1.1 The email account
that you tried to reach does not exist. Please try 550-5.1.1
double-checking the recipient's email address for typos or 550-5.1.1
unnecessary spaces. Learn more at 550 5.1.1
https://support.google.com/mail/?p=NoSuchUser z127si6173191wmc.132 - gsmtp
(in reply to RCPT TO command)
--8A32A6333B.1634202884/mx1.sl.co
Content-Description: Delivery report
Content-Type: message/delivery-status
Reporting-MTA: dns; mx1.sl.co
X-Postfix-Queue-ID: 8A32A6333B
X-Postfix-Sender: rfc822; bounce+5352+@sl.co
Arrival-Date: Thu, 14 Oct 2021 09:14:44 +0000 (UTC)
Final-Recipient: rfc822; not-existing@gmail.com
Original-Recipient: rfc822;not-existing@gmail.com
Action: failed
Status: 5.1.1
Remote-MTA: dns; gmail-smtp-in.l.google.com
Diagnostic-Code: smtp;
550-5.1.1 The email account that you tried to reach does
not exist. Please try 550-5.1.1 double-checking the recipient's email
address for typos or 550-5.1.1 unnecessary spaces. Learn more at 550 5.1.1
https://support.google.com/mail/?p=NoSuchUser z127si6173191wmc.132 - gsmtp
--8A32A6333B.1634202884/mx1.sl.co
Content-Description: Undelivered Message
Content-Type: message/rfc822
Content-Transfer-Encoding: 8bit
Return-Path: <bounce+5352+@sl.co>
X-SimpleLogin-Client-IP: 90.127.20.84
Received: from 2a01cb00008c9c001a3eeffffec79eea.ipv6.abo.wanadoo.fr
(lfbn-idf1-1-2034-84.w90-127.abo.wanadoo.fr [90.127.20.84])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
(No client certificate requested)
by mx1.sl.co (Postfix) with ESMTPS id 8A32A6333B
for <not-existing@gmail.com>;
Thu, 14 Oct 2021 09:14:44 +0000 (UTC)
Content-Type: text/plain;
charset=us-ascii
Content-Transfer-Encoding: 7bit
Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.13\))
Subject: bounce 5
Message-Id: <F2EFE3CE-3967-49EC-8639-9A5900230F2E@gmail.com>
X-SimpleLogin-Type: Forward
X-SimpleLogin-EmailLog-ID: 5352
X-SimpleLogin-Envelope-From: sender@gmail.com
X-SimpleLogin-Envelope-To: heyheyalo@sl.co
date: Thu, 14 Oct 2021 09:14:44 -0000
From: "First Last - sender at gmail.com"
<ra+sender.at.gmail.com+bsppvaap@sl.co>
To: heyheyalo@sl.co
List-Unsubscribe: <mailto:unsubsribe@sl.co?subject=26561=>
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=sl.co;
i=@sl.co; q=dns/txt; s=dkim; t=1634202884;
h=message-id : date : subject : from : to;
bh=ktjzaMYZHA8J5baAHC3QyOmFwAAv/MvNtIz1dvmI3V0=;
b=mzf2ZDIVshKSSjw4AQnrOttgRRjzYzZ+49PaPRobt0xFH0E02a2C9Rl/qLEshLHA7amba
8iNTzdTkp9UJquzjk3NwM9GCakmSzd9DmFsalkgeErDAKWNo2O2c7aYDHZlK/sp2vgsIcSO
1w6sp8sVIRr2JrnFPxFOfsOSkSabeOA=
Alo quoi
--8A32A6333B.1634202884/mx1.sl.co--
23 changes: 22 additions & 1 deletion tests/test_email_utils.py
@@ -1,9 +1,10 @@
import email
import os
from email.message import EmailMessage

import arrow

from app.config import MAX_ALERT_24H, EMAIL_DOMAIN, BOUNCE_EMAIL
from app.config import MAX_ALERT_24H, EMAIL_DOMAIN, BOUNCE_EMAIL, ROOT_DIR
from app.db import Session
from app.email_utils import (
get_email_domain_part,
Expand Down Expand Up @@ -31,6 +32,8 @@
should_ignore_bounce,
get_header_unicode,
parse_full_address,
get_orig_message_from_bounce,
get_mailbox_bounce_info,
)
from app.models import User, CustomDomain, Alias, Contact, EmailLog, IgnoreBounceSender

Expand Down Expand Up @@ -748,3 +751,21 @@ def test_should_ignore_bounce(flask_client):
def test_get_header_unicode():
assert get_header_unicode("ab@cd.com") == "ab@cd.com"
assert get_header_unicode("=?utf-8?B?w6nDqQ==?=@example.com") == "éé@example.com"


def test_get_orig_message_from_bounce():
with open(os.path.join(ROOT_DIR, "local_data", "email_tests", "bounce.eml")) as f:
bounce_report = email.message_from_file(f)

orig_msg = get_orig_message_from_bounce(bounce_report)
assert orig_msg["X-SimpleLogin-Type"] == "Forward"
assert orig_msg["X-SimpleLogin-Envelope-From"] == "sender@gmail.com"


def test_get_mailbox_bounce_info():
with open(os.path.join(ROOT_DIR, "local_data", "email_tests", "bounce.eml")) as f:
bounce_report = email.message_from_file(f)

orig_msg = get_mailbox_bounce_info(bounce_report)
assert orig_msg["Final-Recipient"] == "rfc822; not-existing@gmail.com"
assert orig_msg["Original-Recipient"] == "rfc822;not-existing@gmail.com"

0 comments on commit 3bdeda3

Please sign in to comment.