Skip to content

Commit c2cfced

Browse files
daxtensstephenfin
authored andcommitted
parse(mail|archive): handle early fail within email module
Certain really messed up email messages can cause a failure within the email module (at least on py3). Catch this. Signed-off-by: Daniel Axtens <dja@axtens.net> Signed-off-by: Stephen Finucane <stephen@that.guru>
1 parent ee4f7b9 commit c2cfced

2 files changed

Lines changed: 35 additions & 13 deletions

File tree

patchwork/management/commands/parsearchive.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,23 @@ def handle(self, *args, **options):
7777

7878
count = len(mbox)
7979

80+
# Iterate through the mbox. This will pick up exceptions that are only
81+
# thrown when a broken email is found part way through. Without this
82+
# block, we'd get the exception thrown in enumerate(mbox) below, which
83+
# is harder to catch. This is due to a bug in the Python 'email'
84+
# library, as described here:
85+
#
86+
# https://lists.ozlabs.org/pipermail/patchwork/2017-July/004486.html
87+
#
88+
# The alternative is converting the mbox to a list of messages, but
89+
# that requires holding the entire thing in memory, which is wateful.
90+
try:
91+
for m in mbox:
92+
pass
93+
except AttributeError:
94+
logger.warning('Broken mbox/Maildir, aborting')
95+
return
96+
8097
logger.info('Parsing %d mails', count)
8198
for i, msg in enumerate(mbox):
8299
try:

patchwork/management/commands/parsemail.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,25 @@ def add_arguments(self, parser):
5858
def handle(self, *args, **options):
5959
infile = args[0] if args else options['infile']
6060

61-
if infile:
62-
logger.info('Parsing mail loaded by filename')
63-
if six.PY3:
64-
with open(infile, 'rb') as file_:
65-
mail = email.message_from_binary_file(file_)
66-
else:
67-
with open(infile) as file_:
68-
mail = email.message_from_file(file_)
69-
else:
70-
logger.info('Parsing mail loaded from stdin')
71-
if six.PY3:
72-
mail = email.message_from_binary_file(sys.stdin.buffer)
61+
try:
62+
if infile:
63+
logger.info('Parsing mail loaded by filename')
64+
if six.PY3:
65+
with open(infile, 'rb') as file_:
66+
mail = email.message_from_binary_file(file_)
67+
else:
68+
with open(infile) as file_:
69+
mail = email.message_from_file(file_)
7370
else:
74-
mail = email.message_from_file(sys.stdin)
71+
logger.info('Parsing mail loaded from stdin')
72+
if six.PY3:
73+
mail = email.message_from_binary_file(sys.stdin.buffer)
74+
else:
75+
mail = email.message_from_file(sys.stdin)
76+
except AttributeError:
77+
logger.warning("Broken email ignored")
78+
return
79+
7580
try:
7681
result = parse_mail(mail, options['list_id'])
7782
if result:

0 commit comments

Comments
 (0)