From 9c2c0886f49976b4166c39446e52753955c143e3 Mon Sep 17 00:00:00 2001 From: Fernando Celmer Date: Sun, 17 May 2026 18:14:50 -0300 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=AA=B2=20BUG-#68:=20Avoid=20mutating?= =?UTF-8?q?=20caller=20EmailMessage=20when=20adding=20From=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- email_profile/clients/smtp/sender.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/email_profile/clients/smtp/sender.py b/email_profile/clients/smtp/sender.py index 3d62439..70ddf3b 100644 --- a/email_profile/clients/smtp/sender.py +++ b/email_profile/clients/smtp/sender.py @@ -3,6 +3,7 @@ from __future__ import annotations import contextlib +import copy import logging from typing import TYPE_CHECKING, Optional, Union @@ -79,6 +80,7 @@ def send_message( ) -> None: """Send a pre-built EmailMessage.""" if not message.get("From"): + message = copy.deepcopy(message) message["From"] = self._session.user to = message.get("To", "") From e2c3d77c7bfb8e89b48da43e354d16000566b894 Mon Sep 17 00:00:00 2001 From: Fernando Celmer Date: Sun, 17 May 2026 18:14:55 -0300 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9D=A4=EF=B8=8F=20TEST-#68:=20Add=20test?= =?UTF-8?q?s=20for=20Sender.send=5Fmessage=20non-mutation=20and=20retry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/clients/smtp/test_send.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/clients/smtp/test_send.py b/tests/clients/smtp/test_send.py index 3298cd7..f0e4478 100644 --- a/tests/clients/smtp/test_send.py +++ b/tests/clients/smtp/test_send.py @@ -86,6 +86,31 @@ def test_send_sets_from_when_missing(self): sent = self.smtp.send_message.call_args[0][0] self.assertEqual(sent["From"], "u@x.com") + def test_send_message_does_not_mutate_caller_message(self): + from email.message import EmailMessage + + msg = EmailMessage() + msg["To"] = "bob@x" + msg["Subject"] = "t" + msg.set_content("body") + + self.app.send_message(msg, save_to_sent=False) + self.assertIsNone(msg.get("From")) + + def test_send_message_twice_does_not_duplicate_from(self): + from email.message import EmailMessage + + msg = EmailMessage() + msg["To"] = "bob@x" + msg["Subject"] = "t" + msg.set_content("body") + + self.app.send_message(msg, save_to_sent=False) + self.app.send_message(msg, save_to_sent=False) + + sent = self.smtp.send_message.call_args[0][0] + self.assertEqual(sent.get_all("From"), ["u@x.com"]) + class TestReply(_SendTest): def test_reply_preserves_threading(self):