Ctrl K
ComunidadGuías…

scripts/smtp_probe.py

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""Health/readiness probe client for the email handler, usable as a k8s exec probe.

    python scripts/smtp_probe.py health|ready [--host H] [--port P] [--timeout S]

Exits 0 only if the server replies with the expected code *and* marker text, so
a plain SMTP server answering ``250 OK`` to everything is reported as failing.
Only EHLO/MAIL/RCPT are sent, never DATA.
"""

import argparse
import os
import smtplib
import sys
from typing import Tuple

# Keep in sync with app/email_probe.py; duplicated so the script needs only the stdlib.
EXPECTED = {
    "health": (
        os.environ.get("EMAIL_HANDLER_HEALTH_ADDRESS", "health@probe.invalid"),
        250,
        b"2.0.0 SL-PROBE HEALTH OK",
    ),
    "ready": (
        os.environ.get("EMAIL_HANDLER_READY_ADDRESS", "ready@probe.invalid"),
        250,
        b"2.0.0 SL-PROBE READY OK",
    ),
}


def probe(mode: str, host: str, port: int, timeout: float) -> int:
    address, code, marker = EXPECTED[mode]
    try:
        with smtplib.SMTP(host, port, timeout=timeout) as smtp:
            smtp.ehlo()
            smtp.mail("<>")
            reply: Tuple[int, bytes] = smtp.docmd("RCPT", f"TO:<{address}>")
    except (OSError, smtplib.SMTPException) as e:
        print(f"{mode} probe failed: {e}", file=sys.stderr)
        return 1
    if reply != (code, marker):
        print(f"{mode} probe got unexpected reply: {reply}", file=sys.stderr)
        return 1
    return 0


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
    parser.add_argument("mode", choices=sorted(EXPECTED))
    parser.add_argument("--host", default="127.0.0.1")
    parser.add_argument("--port", type=int, default=20381)
    parser.add_argument("--timeout", type=float, default=5.0)
    args = parser.parse_args()
    return probe(args.mode, args.host, args.port, args.timeout)


if __name__ == "__main__":
    sys.exit(main())