From 5d560365d0bd7f3d7aae879ecb614baead4049e0 Mon Sep 17 00:00:00 2001 From: Dan Mahoney Date: Wed, 20 May 2026 18:20:57 -0700 Subject: [PATCH] Fix unclosed file ResourceWarnings in FileRecips and ToDigest FileRecips.py: use 'with fp:' to ensure members.txt is closed after reading. ToDigest.py: Mailbox (mailbox.mbox subclass) opens its own file descriptor internally. Two instances were never closed: - process(): wrap Mailbox.AppendMessage() in try/finally to call close() - send_i18n_digests(): extract body into _send_i18n_digests() and close the Mailbox in a finally block to handle the early-return path On FreeBSD Python 3.11, Mailbox does not support the context manager protocol, so try/finally is used rather than a with-statement. --- Mailman/Handlers/FileRecips.py | 3 ++- Mailman/Handlers/ToDigest.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Mailman/Handlers/FileRecips.py b/Mailman/Handlers/FileRecips.py index 9cd7eab7..fd3cecba 100644 --- a/Mailman/Handlers/FileRecips.py +++ b/Mailman/Handlers/FileRecips.py @@ -37,7 +37,8 @@ def process(mlist, msg, msgdata): msgdata['recips'] = [] return # Read all the lines out of the file, and strip them of the trailing nl - addrs = [line.strip() for line in fp.readlines()] + with fp: + addrs = [line.strip() for line in fp.readlines()] # If the sender is in that list, remove him sender = msg.get_sender() if mlist.isMember(sender): diff --git a/Mailman/Handlers/ToDigest.py b/Mailman/Handlers/ToDigest.py index 8ae5fa17..e33f8813 100644 --- a/Mailman/Handlers/ToDigest.py +++ b/Mailman/Handlers/ToDigest.py @@ -81,7 +81,10 @@ def process(mlist, msg, msgdata): try: with open(mboxfile, 'a+b') as mboxfp: mbox = Mailbox(mboxfp.name) - mbox.AppendMessage(msg) + try: + mbox.AppendMessage(msg) + finally: + mbox.close() # Calculate the current size of the accumulation file. This will not tell # us exactly how big the MIME, rfc1153, or any other generated digest # message will be, but it's the most easily available metric to decide @@ -155,6 +158,13 @@ def send_digests(mlist, mboxfp): def send_i18n_digests(mlist, mboxfp): mbox = Mailbox(mboxfp) + try: + _send_i18n_digests(mlist, mbox) + finally: + mbox.close() + + +def _send_i18n_digests(mlist, mbox): # Prepare common information (first lang/charset) lang = mlist.preferred_language lcset = Utils.GetCharSet(lang)