2626from Mailman .Logging .Syslog import syslog
2727from Mailman .Handlers .CookHeaders import change_header
2828
29- scre = re .compile ('did not reach the following recipient' )
30- ecre = re .compile ('MSEXCH:' )
29+ # Patterns for different Exchange/Office 365 bounce formats
30+ scre = re .compile ('did not reach the following recipient|Your message to .* couldn\' t be delivered' )
31+ ecre = re .compile ('MSEXCH:|Action Required' )
3132a1cre = re .compile ('SMTP=(?P<addr>[^;]+); on ' )
3233a2cre = re .compile ('(?P<addr>[^ ]+) on ' )
34+ a3cre = re .compile ('Your message to (?P<addr>[^ ]+) couldn\' t be delivered' )
35+ a4cre = re .compile ('(?P<addr>[^ ]+) wasn\' t found at ' )
3336
3437
3538def process (msg ):
@@ -45,9 +48,18 @@ def process(msg):
4548 for line in it :
4649 if ecre .search (line ):
4750 break
48- mo = a1cre .search (line )
49- if not mo :
50- mo = a2cre .search (line )
51- if mo :
52- addrs [mo .group ('addr' )] = 1
51+ # Try all patterns
52+ for pattern in [a1cre , a2cre , a3cre , a4cre ]:
53+ mo = pattern .search (line )
54+ if mo :
55+ addr = mo .group ('addr' )
56+ # Clean up the address if needed
57+ if '@' not in addr and 'at' in line :
58+ # Handle cases where domain is on next line
59+ next_line = next (it , '' )
60+ if 'at' in next_line :
61+ domain = next_line .split ('at' )[- 1 ].strip ()
62+ addr = f"{ addr } @{ domain } "
63+ addrs [addr ] = 1
64+ break
5365 return list (addrs .keys ())
0 commit comments