"""Recognizes simple heuristically delimited bounces."""
import re
import email.Iterators
def _c(pattern):
return re.compile(pattern, re.IGNORECASE)
PATTERNS = [
(_c('here is your list of failed recipients'),
_c('here is your returned mail'),
_c(r'<(?P<addr>[^>]*)>')),
(_c('the following addresses had'),
_c('transcript of session follows'),
_c(r'<(?P<fulladdr>[^>]*)>|\(expanded from: <?(?P<addr>[^>)]*)>?\)')),
(_c('this message was created automatically by mail delivery software'),
_c('original message follows'),
_c('rcpt to:\s*<(?P<addr>[^>]*)>')),
(_c('message from interscan e-mail viruswall nt'),
_c('end of message'),
_c('rcpt to:\s*<(?P<addr>[^>]*)>')),
(_c('failed addresses follow:'),
_c('message text follows:'),
_c(r'\s*(?P<addr>\S+@\S+)')),
(_c('This is the machine generated message from mail service.'),
_c('--- Below the next line is a copy of the message.'),
_c('<(?P<addr>[^>]*)>')),
(_c('The following addresses did NOT receive a copy of your message:'),
_c('--- Session Transcript ---'),
_c('[>]\s*(?P<addr>.*)$')),
(_c('Intended recipient:\s*(?P<addr>.*)$'),
_c('--------RETURNED MAIL FOLLOWS--------'),
_c('Intended recipient:\s*(?P<addr>.*)$')),
(_c('Undeliverable Address:\s*(?P<addr>.*)$'),
_c('Original message attached'),
_c('Undeliverable Address:\s*(?P<addr>.*)$')),
(_c('This message was created automatically by mail delivery'),
_c('^---- START OF RETURNED MESSAGE ----'),
_c("addressed to '(?P<addr>[^']*)'")),
(_c("User's mailbox is full:"),
_c('Unable to deliver mail.'),
_c("User's mailbox is full:\s*<(?P<addr>[^>]*)>")),
(_c('The email below could not be delivered to the following user:'),
_c('Old message:'),
_c('<(?P<addr>[^>]*)>')),
(_c('Unable to deliver message to the following address\(es\)\.'),
_c('--- Original message follows\.'),
_c('<(?P<addr>[^>]*)>:')),
(_c('A message that you sent could not be delivered'),
_c('^---'),
_c('<(?P<addr>[^>]*)>')),
(_c('A message that you sent could not be delivered'),
_c('^---'),
_c('^(?P<addr>[^\s@]+@[^\s@:]+):')),
(_c('Delivery to the following recipients failed'),
_c("Bogus - there actually isn't anything"),
_c('^\s*(?P<addr>[^\s@]+@[^\s@]+)\s*$')),
(_c('^Your message\s*$'),
_c('^because:'),
_c('^\s*(?P<addr>[^\s@]+@[^\s@]+)\s*$')),
(_c('^Unable to deliver message to'),
_c(r'\*+\s+End of message\s+\*+'),
_c('<(?P<addr>[^>]*)>')),
(_c('^Sorry, unable to deliver your message to'),
_c('^A copy of the original message'),
_c('\s*(?P<addr>[^\s@]+@[^\s@]+)\s+')),
(_c('^A message could not be delivered to:'),
_c('^Subject:'),
_c('^\s*(?P<addr>[^\s@]+@[^\s@]+)\s*$')),
(_c('^Invalid final delivery userid:'),
_c('^Original message follows.'),
_c('\s*(?P<addr>[^\s@]+@[^\s@]+)\s*$')),
(_c('------ Failed Recipients ------'),
_c('-------- Returned Mail --------'),
_c('<(?P<addr>[^>]*)>')),
(_c('A message that you sent could not be delivered'),
_c('^---'),
_c('(?P<addr>[^\s@]+@[^\s@)]+)')),
]
def process(msg, patterns=None):
if patterns is None:
patterns = PATTERNS
addrs = {}
for scre, ecre, acre in patterns:
state = 0
for line in email.Iterators.body_line_iterator(msg):
if state == 0:
if scre.search(line):
state = 1
if state == 1:
mo = acre.search(line)
if mo:
addr = mo.group('addr')
if addr:
addrs[mo.group('addr')] = 1
elif ecre.search(line):
break
if addrs:
break
return addrs.keys()