From e46e8ff1bed4c20d4b1a3ce56d6ef66779e8889a Mon Sep 17 00:00:00 2001 From: zaihuaji Date: Thu, 24 Sep 2026 13:07:25 -0500 Subject: [PATCH] pg_log.py: fix email header stripping, empty bodies and cc leaking; bump version to 3.0.18 send_customized_email() stripped its header lines with a global replace(), so a To:/Subject: line quoted in the message body was deleted too, and it passed an empty body straight to send_python_email(), which substitutes and clears the buffered PGLOG['EMLMSG'] - mailing an unrelated message to that recipient. send_python_email() also treated an explicitly empty cc as 'no cc given' and carbon copied the sender into the process global CCDADDR, which then rode along on every later email of the same process. Co-Authored-By: Claude Opus 4.6 --- README.md | 2 +- pyproject.toml | 2 +- src/rda_python_common/__init__.py | 2 +- src/rda_python_common/pg_log.py | 18 +++++++++++++----- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bc12b52..93bc659 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ PgLOG.pglog("hello", PgLOG.LOGWRN) python -c "import rda_python_common; print(rda_python_common.__version__)" ``` -You should see the installed version (currently `3.0.17`). If the import +You should see the installed version (currently `3.0.18`). If the import fails, double-check that the active Python environment is the one where you ran `pip install`. diff --git a/pyproject.toml b/pyproject.toml index 0b5a259..7d6b86f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "rda_python_common" -version = "3.0.17" +version = "3.0.18" authors = [ { name="Zaihua Ji", email="zji@ucar.edu" }, ] diff --git a/src/rda_python_common/__init__.py b/src/rda_python_common/__init__.py index 7d398ce..30843dc 100644 --- a/src/rda_python_common/__init__.py +++ b/src/rda_python_common/__init__.py @@ -22,7 +22,7 @@ from . import PgLOG, PgUtil, PgDBI, PgFile, PgLock, PgCMD, PgSIG, PgOPT, PgSplit -__version__ = "3.0.17" +__version__ = "3.0.18" __all__ = [ "PgLOG", diff --git a/src/rda_python_common/pg_log.py b/src/rda_python_common/pg_log.py index e6e878b..cbfdac3 100644 --- a/src/rda_python_common/pg_log.py +++ b/src/rda_python_common/pg_log.py @@ -320,13 +320,18 @@ def send_customized_email(self, logmsg, emlmsg, logact=None): msg = emlmsg for ekey in entries: entry = entries[ekey][0] - ms = re.search(r'(^|\n)({}: *(.*)\n)'.format(entry), emlmsg, re.I) + ms = re.search(r'(^|\n)({}: *(.*)\n)'.format(entry), msg, re.I) if ms: - vals = ms.groups() - msg = msg.replace(vals[1], '') - if vals[2]: entries[ekey][2] = vals[2] + # cut out this header line only; a replace() of the matched text would also + # strip an identical line from anywhere in the message body + msg = msg[:ms.start(2)] + msg[ms.end(2):] + if ms.group(3): entries[ekey][2] = ms.group(3) elif entries[ekey][1]: return self.pglog("{}Missing Entry '{}' for sending email".format(logmsg, entry), logact|self.ERRLOG) + if not msg.strip(): + # send_python_email() mails the buffered EMLMSG when it is given no body, which + # would send an unrelated message to this recipient and empty the buffer + return self.pglog("{}Empty message body for sending email".format(logmsg), logact|self.ERRLOG) ret = self.send_python_email(entries['sb'][2], entries['to'][2], msg, entries['fr'][2], entries['cc'][2], logact) if ret == self.SUCCESS or not self.PGLOG['EMLSEND']: return ret # try commandline sendmail @@ -386,7 +391,10 @@ def send_python_email(self, subject=None, receiver=None, msg=None, sender=None, self.PGLOG['EMLMSG'] = '' else: return '' - docc = False if cc else True + # only an omitted cc means 'use CCDADDR and carbon copy the sender'; an explicitly + # empty cc suppresses the Cc entirely, and used to leak the sender into the global + # CCDADDR anyway, carbon copying it on every later email of the same process + docc = True if cc is None else False if not sender: sender = self.PGLOG['CURUID'] if sender != self.PGLOG['COMMONUSER']: docc = False