refactor: remove import-time side effects
Импорт модулей больше не мутирует процесс:
- config.py: module-level load_dotenv(override=False) мутировал os.environ
при любом импорте. Вызов перенесён в Config.load_yaml() — точку явной
загрузки конфигурации, семантика override=False и путь по умолчанию
сохранены. --config PATH (load_dotenv(path, override=True)) не затронут.
- mailer.py: глобальная регистрация email.charset.add_charset('utf-8', ...)
меняла кодировку для всего процесса. Заменена на точечное применение
8bit UTF-8 к телу письма в _utf8_text_part() — payload в UTF-8
(surrogateescape) + Content-Transfer-Encoding: 8bit на конкретной части.
Проверено: сериализация в байты (BytesGenerator, как в send_message)
побайтово совпадает со старым поведением.
Тест test_env_var_takes_priority_over_dotenv адаптирован к новой точке
вызова load_dotenv; test_body_substitution переведён с as_string() на
декодированный payload (str-сериализация не-ASCII части без глобальной
мутации реестра теперь даёт base64; wire-формат 8bit сохранён и
зафиксирован test_wire_format_is_8bit_utf8).
Closes #64
This commit is contained in:
@@ -49,7 +49,37 @@ class TestBuildMessage:
|
||||
msg = build_message(cfg, "/tmp/report.xlsx", "Иванов", "Q1", [])
|
||||
plain_parts = [p for p in msg.walk() if p.get_content_type() == "text/plain"]
|
||||
assert len(plain_parts) == 1
|
||||
assert "Автор: Иванов, период: Q1" in plain_parts[0].as_string()
|
||||
payload = plain_parts[0].get_payload(decode=True).decode("utf-8")
|
||||
assert "Автор: Иванов, период: Q1" in payload
|
||||
|
||||
def test_wire_format_is_8bit_utf8(self):
|
||||
"""Сериализация в байты (как в smtplib.send_message) — 8bit UTF-8."""
|
||||
from email.generator import BytesGenerator
|
||||
from io import BytesIO
|
||||
|
||||
cfg = _make_email_config(body_text="Автор: {author}", attach=False)
|
||||
msg = build_message(cfg, "/tmp/r.xlsx", "Иванов", "Q1", [])
|
||||
|
||||
buf = BytesIO()
|
||||
BytesGenerator(buf, policy=msg.policy.clone(linesep="\r\n")).flatten(msg)
|
||||
data = buf.getvalue()
|
||||
|
||||
assert b"Content-Transfer-Encoding: 8bit" in data
|
||||
assert "Автор: Иванов".encode("utf-8") in data
|
||||
|
||||
def test_plain_part_uses_8bit_utf8(self):
|
||||
"""Тела письма кодируются 8bit UTF-8 (не base64), точечно на часть."""
|
||||
cfg = _make_email_config(
|
||||
body_text="Автор: {author}, период: {period}", attach=False
|
||||
)
|
||||
msg = build_message(cfg, "/tmp/r.xlsx", "Иванов", "Q1", [])
|
||||
|
||||
plain = [p for p in msg.walk() if p.get_content_type() == "text/plain"][0]
|
||||
assert plain["Content-Transfer-Encoding"] == "8bit"
|
||||
assert (
|
||||
plain.get_payload(decode=True).decode("utf-8")
|
||||
== "Автор: Иванов, период: Q1"
|
||||
)
|
||||
|
||||
def test_from_header(self):
|
||||
cfg = _make_email_config(from_="sender@example.com", attach=False)
|
||||
|
||||
Reference in New Issue
Block a user