summaryrefslogtreecommitdiff
path: root/modules/mm_utils.py
diff options
context:
space:
mode:
authormailman1998-03-26 05:33:21 +0000
committermailman1998-03-26 05:33:21 +0000
commitd44266ead5d0daacc77c50dc38795f0442e67a02 (patch)
tree3b3d3d364e8c4d5aaa13835a77b5cb906ad55447 /modules/mm_utils.py
parentfb9f168857b88c8d75baea989a6d8542a3e8022e (diff)
downloadmailman-d44266ead5d0daacc77c50dc38795f0442e67a02.tar.gz
mailman-d44266ead5d0daacc77c50dc38795f0442e67a02.tar.zst
mailman-d44266ead5d0daacc77c50dc38795f0442e67a02.zip
Simpliefied FindMatchineAddress - it now only recognizes similarity
when the domain side of the at sign of one address properly contains the domain in the other example. Wrap DeliverToUser body in a os.fork, to prevent a deadlock which can happen when, eg, a message bounces before message aceptance in sendmail. Message bouncing early on in message acceptance by sendmail means reporting to list admin address, which is itself actually a mailman program, which uses the instantiated list as a agent, and which requires the same lock that the invoking process is holding - ie, deadlock Sendmail's deliver-in-background option would be great for this, except that the error processing for immediately recognized delivery problems turns out to be handled in the foreground, regardless of the bg delivery option.
Diffstat (limited to 'modules/mm_utils.py')
-rw-r--r--modules/mm_utils.py59
1 files changed, 34 insertions, 25 deletions
diff --git a/modules/mm_utils.py b/modules/mm_utils.py
index c2ed49f79..a112daeeb 100644
--- a/modules/mm_utils.py
+++ b/modules/mm_utils.py
@@ -47,21 +47,33 @@ def SendTextToUser(subject, text, recipient, sender, errorsto=None):
msg.SetBody(QuotePeriods(text))
DeliverToUser(msg, recipient, errorsto=errorsto)
-# This method assumes the sender is the one given by the message.
def DeliverToUser(msg, recipient, errorsto=None):
- file = os.popen(mm_cfg.SENDMAIL_CMD % (msg.GetSender(), recipient),
- 'w')
+ """Use sendmail to deliver message."""
+
+ # We fork to ensure no deadlock. Otherwise, even if sendmail is
+ # invoked in forking mode, if it eg detects a bad address before
+ # forking, then it will try deliver to the errorsto addr *in the
+ # foreground*. If the errorsto happens to be the list owner for a list
+ # that is doing the send - and holding a lock - then the delivery will
+ # hang pending release of the lock - deadlock.
+ if os.fork():
+ return
try:
- msg.headers.remove('\n')
- except ValueError:
- pass
- if not msg.getheader('to'):
- msg.headers.append('To: %s\n' % recipient)
- if errorsto:
- msg.headers.append('Errors-To: %s\n' % errorsto)
- file.write(string.join(msg.headers, '')+ '\n')
- file.write(QuotePeriods(msg.body))
- file.close()
+ file = os.popen(mm_cfg.SENDMAIL_CMD % (msg.GetSender(), recipient),
+ 'w')
+ try:
+ msg.headers.remove('\n')
+ except ValueError:
+ pass
+ if not msg.getheader('to'):
+ msg.headers.append('To: %s\n' % recipient)
+ if errorsto:
+ msg.headers.append('Errors-To: %s\n' % errorsto)
+ file.write(string.join(msg.headers, '')+ '\n')
+ file.write(QuotePeriods(msg.body))
+ file.close()
+ finally:
+ os._exit(0)
def QuotePeriods(text):
return string.join(string.split(text, '\n.\n'), '\n .\n')
@@ -142,22 +154,19 @@ def ParseEmail(email):
# There's password protection anyway.
def AddressesMatch(addr1, addr2):
+ "True when username matches and host addr of one addr contains other's."
user1, domain1 = ParseEmail(addr1)
user2, domain2 = ParseEmail(addr2)
- if user1 <> user2:
+ if user1 != user2:
return 0
if domain1 == domain2:
- return 1
- if not (domain1 and domain2):
- return 0
- l = max(len(domain1), len(domain2)) - 1
- if l < 2:
- return 0
- for i in range(l):
- if domain1[-(i+1)] <> domain2[-(i+1)]:
- return 0
- return 1
- return 0
+ return 1
+ for i in range(-1 * min(len(domain1), len(domain2)), 0):
+ # By going from most specific component of host part we're likely
+ # to hit a difference sooner.
+ if domain1[i] != domain2[i]:
+ return 0
+ return 1
def FindMatchingAddresses(name, array):