58 lines
2.0 KiB
Python
58 lines
2.0 KiB
Python
from __future__ import annotations
|
|
|
|
import smtplib
|
|
from email.utils import parseaddr
|
|
|
|
from django.conf import settings
|
|
from django.core.mail.backends.base import BaseEmailBackend
|
|
|
|
from apps.core.services.microsoft365 import (
|
|
Microsoft365OAuthError,
|
|
acquire_exchange_access_token,
|
|
xoauth2_b64,
|
|
)
|
|
from apps.sources.services.tls import trusted_tls_context
|
|
|
|
|
|
class Microsoft365OAuthEmailBackend(BaseEmailBackend):
|
|
"""Send mail through Exchange Online with app-only SASL XOAUTH2."""
|
|
|
|
def send_messages(self, email_messages) -> int:
|
|
if not email_messages:
|
|
return 0
|
|
sent = 0
|
|
try:
|
|
token = acquire_exchange_access_token()
|
|
username = settings.M365_MAILBOX_USER.strip()
|
|
if not username:
|
|
raise Microsoft365OAuthError(
|
|
"M365_MAILBOX_USER is verplicht voor Microsoft 365-mailuitvoer."
|
|
)
|
|
with smtplib.SMTP(
|
|
settings.EMAIL_HOST or "smtp.office365.com",
|
|
settings.EMAIL_PORT,
|
|
timeout=settings.M365_SMTP_TIMEOUT_SECONDS,
|
|
) as client:
|
|
client.ehlo()
|
|
client.starttls(context=trusted_tls_context())
|
|
client.ehlo()
|
|
code, _ = client.docmd("AUTH", f"XOAUTH2 {xoauth2_b64(username, token)}")
|
|
if code != 235:
|
|
raise Microsoft365OAuthError("Microsoft 365 SMTP OAuth geweigerd.")
|
|
for message in email_messages:
|
|
recipients = message.recipients()
|
|
if not recipients:
|
|
continue
|
|
sender = parseaddr(message.from_email or settings.DEFAULT_FROM_EMAIL)[1]
|
|
client.sendmail(
|
|
sender or username,
|
|
recipients,
|
|
message.message().as_bytes(linesep="\r\n"),
|
|
)
|
|
sent += 1
|
|
except Exception:
|
|
if self.fail_silently:
|
|
return sent
|
|
raise
|
|
return sent
|