fix: relay raw SMTP bytes without decoding
Build and publish container / build (pull_request) Successful in 9m6s
Build and publish container / build (pull_request) Successful in 9m6s
send_message decoded the message body with utf-8/errors="replace", corrupting 8-bit content before forwarding. Pass the raw bytes straight to smtp.sendmail so the message is relayed unchanged. Fixes #4 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-2
@@ -416,7 +416,6 @@ class SMTPProxyHandler:
|
|||||||
|
|
||||||
def send_message(self, sender, recipients, data):
|
def send_message(self, sender, recipients, data):
|
||||||
"""Forward a complete SMTP message to the backend SMTP server."""
|
"""Forward a complete SMTP message to the backend SMTP server."""
|
||||||
message = data.decode("utf-8", errors="replace")
|
|
||||||
if Settings.BACKEND_SMTP_USE_SSL:
|
if Settings.BACKEND_SMTP_USE_SSL:
|
||||||
smtp = smtplib.SMTP_SSL(Settings.BACKEND_SMTP_HOST, Settings.BACKEND_SMTP_PORT, timeout=30)
|
smtp = smtplib.SMTP_SSL(Settings.BACKEND_SMTP_HOST, Settings.BACKEND_SMTP_PORT, timeout=30)
|
||||||
else:
|
else:
|
||||||
@@ -426,7 +425,7 @@ class SMTPProxyHandler:
|
|||||||
try:
|
try:
|
||||||
if Settings.BACKEND_SMTP_USER and Settings.BACKEND_SMTP_PASS:
|
if Settings.BACKEND_SMTP_USER and Settings.BACKEND_SMTP_PASS:
|
||||||
smtp.login(Settings.BACKEND_SMTP_USER, Settings.BACKEND_SMTP_PASS)
|
smtp.login(Settings.BACKEND_SMTP_USER, Settings.BACKEND_SMTP_PASS)
|
||||||
smtp.sendmail(sender, recipients, message)
|
smtp.sendmail(sender, recipients, data)
|
||||||
finally:
|
finally:
|
||||||
smtp.quit()
|
smtp.quit()
|
||||||
|
|
||||||
|
|||||||
@@ -126,14 +126,17 @@ def test_smtp_proxy_handler_forwards_message_over_ssl(monkeypatch):
|
|||||||
Settings.BACKEND_SMTP_USER = "smtp-user"
|
Settings.BACKEND_SMTP_USER = "smtp-user"
|
||||||
Settings.BACKEND_SMTP_PASS = "smtp-pass"
|
Settings.BACKEND_SMTP_PASS = "smtp-pass"
|
||||||
|
|
||||||
|
# Include an 8-bit byte that would be mangled by a utf-8 decode.
|
||||||
|
raw = b"Subject: Test\r\n\r\nBody \x80\r\n"
|
||||||
handler = SMTPProxyHandler()
|
handler = SMTPProxyHandler()
|
||||||
handler.send_message("from@example.com", ["to@example.com"], b"Subject: Test\r\n\r\nBody\r\n")
|
handler.send_message("from@example.com", ["to@example.com"], raw)
|
||||||
|
|
||||||
assert captured["instance"].host == Settings.BACKEND_SMTP_HOST
|
assert captured["instance"].host == Settings.BACKEND_SMTP_HOST
|
||||||
assert captured["instance"].logged_in is True
|
assert captured["instance"].logged_in is True
|
||||||
assert captured["instance"].sent[0] == "from@example.com"
|
assert captured["instance"].sent[0] == "from@example.com"
|
||||||
assert captured["instance"].sent[1] == ["to@example.com"]
|
assert captured["instance"].sent[1] == ["to@example.com"]
|
||||||
assert "Subject: Test" in captured["instance"].sent[2]
|
# Raw bytes must be forwarded unchanged, not decoded.
|
||||||
|
assert captured["instance"].sent[2] == raw
|
||||||
|
|
||||||
Settings.BACKEND_SMTP_USE_SSL = previous_ssl
|
Settings.BACKEND_SMTP_USE_SSL = previous_ssl
|
||||||
Settings.BACKEND_SMTP_USER = previous_user
|
Settings.BACKEND_SMTP_USER = previous_user
|
||||||
|
|||||||
Reference in New Issue
Block a user