116 lines
3.5 KiB
Python
Executable File
116 lines
3.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# This program is free software, licensed under the terms of the GNU GPL.
|
|
# See the Bongo COPYING file for full details.
|
|
# Copyright (c) 2026 Bongo Project contributors
|
|
|
|
"""Verify that BINARYMIME remains unavailable while CHUNKING is enabled."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import os
|
|
from pathlib import Path
|
|
import sys
|
|
import time
|
|
|
|
|
|
TOKEN = f"smtp16-{os.getpid()}-{int(time.time())}"
|
|
TOKEN_PREFIX = b"smtp16-"
|
|
ALLOW_LIVE = os.environ.get("BONGO_ALLOW_LIVE_SMTP_TEST") == "1"
|
|
|
|
|
|
class SMTP16Error(RuntimeError):
|
|
"""Raised when SMTP exposes or accepts unsupported BINARYMIME."""
|
|
|
|
|
|
def load_helpers():
|
|
path = Path(__file__).with_name("smtp-pipelining-check.py")
|
|
specification = importlib.util.spec_from_file_location(
|
|
"bongo_smtp16_helpers", path
|
|
)
|
|
if specification is None or specification.loader is None:
|
|
raise SMTP16Error(f"cannot load SMTP test helpers from {path}")
|
|
module = importlib.util.module_from_spec(specification)
|
|
sys.modules[specification.name] = module
|
|
specification.loader.exec_module(module)
|
|
module.TOKEN_PREFIX = TOKEN_PREFIX
|
|
return module
|
|
|
|
|
|
HELPERS = load_helpers()
|
|
|
|
|
|
def reject_binary(client, parameters: str) -> None:
|
|
client.command(
|
|
f"MAIL FROM:<{TOKEN}@example.test> {parameters}", 504
|
|
)
|
|
client.command(
|
|
f"RCPT TO:<{HELPERS.USER}@{HELPERS.DOMAIN}>", 503
|
|
)
|
|
client.command("NOOP", 250)
|
|
|
|
|
|
def main() -> int:
|
|
if not ALLOW_LIVE:
|
|
raise SMTP16Error(
|
|
"set BONGO_ALLOW_LIVE_SMTP_TEST=1 for the live protocol test"
|
|
)
|
|
if not HELPERS.PASSWORD:
|
|
raise SMTP16Error("BONGO_TEST_PASSWORD is required")
|
|
|
|
store = HELPERS.open_store()
|
|
try:
|
|
HELPERS.cleanup(store)
|
|
client = HELPERS.SMTPConnection()
|
|
try:
|
|
client.require(220, "greeting")
|
|
capabilities = client.command(
|
|
"EHLO smtp16-client.example", 250
|
|
)
|
|
if b"CHUNKING" not in capabilities:
|
|
raise SMTP16Error("EHLO did not advertise CHUNKING")
|
|
if b"BINARYMIME" in capabilities:
|
|
raise SMTP16Error("EHLO advertised unsupported BINARYMIME")
|
|
|
|
reject_binary(client, "BODY=BINARYMIME")
|
|
reject_binary(client, "BODY=binarymime")
|
|
reject_binary(client, "SIZE=123 BODY=BINARYMIME")
|
|
reject_binary(client, "BODY=BINARYMIME SIZE=123")
|
|
|
|
client.command(
|
|
f"MAIL FROM:<{TOKEN}@example.test> BODY=7BIT", 250
|
|
)
|
|
client.command("RSET", 250)
|
|
client.command(
|
|
f"MAIL FROM:<{TOKEN}@example.test> BODY=8BITMIME", 250
|
|
)
|
|
client.command("RSET", 250)
|
|
client.command("QUIT", 221)
|
|
finally:
|
|
client.close()
|
|
|
|
HELPERS.cleanup(store)
|
|
if HELPERS.store_token_documents(store) or HELPERS.queue_token_ids():
|
|
raise SMTP16Error("test content remains after cleanup")
|
|
finally:
|
|
try:
|
|
HELPERS.cleanup(store)
|
|
finally:
|
|
store.Quit()
|
|
|
|
print(
|
|
"SMTP-16 PASS advertised=chunking/no-binarymime "
|
|
"body-binarymime=504 case-insensitive=504 combined=504 "
|
|
"transaction-state=clean body-7bit=accepted "
|
|
"body-8bitmime=accepted queue-clean=yes store-clean=yes"
|
|
)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
raise SystemExit(main())
|
|
except (OSError, SMTP16Error, ValueError) as error:
|
|
print(f"SMTP-16 FAIL: {type(error).__name__}: {error}")
|
|
raise SystemExit(1)
|