Added NTLM auth to email client settings

This commit is contained in:
Daniel Schick 2026-01-13 07:01:15 +01:00
parent 62c13eb17a
commit 77959b4a50
2 changed files with 34 additions and 1 deletions

View File

@ -35,3 +35,4 @@ typing_extensions==4.12.2
tzdata==2024.1
webargs==8.6.0
Werkzeug==3.0.4
ntlm-auth==1.5.0

View File

@ -3,6 +3,7 @@ import pydapper
import smtplib
import json
import os
import base64
from email.message import EmailMessage
from BreCal.schemas import model, defs
@ -110,8 +111,33 @@ def SendEmails(email_dict):
pooledConnection = getPoolConnection()
commands = pydapper.using(pooledConnection)
def _parse_bool(value) -> bool:
if isinstance(value, bool):
return value
if value is None:
return False
return str(value).strip().lower() in ("1", "true", "yes", "y", "on")
def _smtp_auth_ntlm(connection, username: str, password: str, domain: str | None = None, workstation: str | None = None):
try:
from ntlm_auth.ntlm import NtlmContext
except Exception as exc:
raise RuntimeError("NTLM auth requested but ntlm-auth is not installed") from exc
context = NtlmContext(username, password, domain=domain, workstation=workstation)
negotiate = context.step()
code, challenge = connection.docmd("AUTH", "NTLM " + base64.b64encode(negotiate).decode("ascii"))
if code != 334:
raise smtplib.SMTPException(f"NTLM negotiate failed: {code} {challenge}")
challenge_bytes = base64.b64decode(challenge.strip())
authenticate = context.step(challenge_bytes)
code, msg = connection.docmd(base64.b64encode(authenticate).decode("ascii"))
if code != 235:
raise smtplib.SMTPAuthenticationError(code, msg)
encryption = defs.email_credentials.get("encryption") or defs.email_credentials.get("encryption_method") or "STARTTLS"
encryption_norm = str(encryption).strip().upper().replace(" ", "").replace("_", "").replace("-", "")
use_ntlm_auth = _parse_bool(defs.email_credentials.get("USE_NTLM_AUTH"))
if encryption_norm in ("SSLTLS", "SSL", "TLS"):
conn = smtplib.SMTP_SSL(defs.email_credentials["server"], defs.email_credentials["port"])
else:
@ -127,6 +153,12 @@ def SendEmails(email_dict):
logging.warning("Unknown email encryption '%s'; defaulting to STARTTLS.", encryption)
conn.starttls()
conn.ehlo()
if use_ntlm_auth:
ntlm_user = defs.email_credentials.get("ntlm_user") or defs.email_credentials["sender"]
ntlm_domain = defs.email_credentials.get("ntlm_domain")
ntlm_workstation = defs.email_credentials.get("ntlm_workstation")
_smtp_auth_ntlm(conn, ntlm_user, defs.email_credentials["password_send"], domain=ntlm_domain, workstation=ntlm_workstation)
else:
conn.login(defs.email_credentials["sender"], defs.email_credentials["password_send"])
current_path = os.path.dirname(os.path.abspath(__file__))