181 lines
6.3 KiB
Python
181 lines
6.3 KiB
Python
"""
|
|
notify.py — Email notifications for NetAdmin
|
|
"""
|
|
|
|
import datetime
|
|
import email.utils
|
|
import logging
|
|
import quopri
|
|
import socket
|
|
from email.header import Header
|
|
from email.message import Message
|
|
from email.mime.multipart import MIMEMultipart
|
|
from email.mime.text import MIMEText
|
|
from typing import Optional
|
|
|
|
from config import cfg
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
def _make_qp_part(content: str, subtype: str) -> Message:
|
|
"""Build a text/plain or text/html MIME part using quoted-printable encoding.
|
|
|
|
MIMEText with charset='utf-8' defaults to base64.
|
|
We encode manually as QP so mail clients display it as plain text.
|
|
"""
|
|
encoded = quopri.encodestring(content.encode("utf-8"), quotetabs=False)
|
|
part = Message()
|
|
part["Content-Type"] = f"text/{subtype}; charset=utf-8"
|
|
part["Content-Transfer-Encoding"] = "quoted-printable"
|
|
part.set_payload(encoded.decode("ascii"))
|
|
return part
|
|
|
|
|
|
def _send(to_addr: str, subject: str, body_text: str, body_html: Optional[str] = None):
|
|
"""Send an email with correct headers and QP encoding."""
|
|
s = cfg.smtp
|
|
if not s.enabled or not to_addr:
|
|
return
|
|
|
|
try:
|
|
msg = MIMEMultipart("alternative")
|
|
|
|
# RFC-required headers
|
|
msg["Message-ID"] = email.utils.make_msgid(domain=s.from_addr.split("@")[-1])
|
|
msg["Date"] = email.utils.formatdate(localtime=True)
|
|
msg["Subject"] = Header(subject, "utf-8").encode()
|
|
msg["From"] = email.utils.formataddr((s.from_name, s.from_addr))
|
|
msg["To"] = to_addr
|
|
msg["X-Mailer"] = "NetAdmin"
|
|
|
|
# Attach parts with quoted-printable (readable in all clients)
|
|
msg.attach(_make_qp_part(body_text, "plain"))
|
|
if body_html:
|
|
msg.attach(_make_qp_part(body_html, "html"))
|
|
|
|
if s.use_ssl:
|
|
server = __import__("smtplib").SMTP_SSL(s.host, s.port, timeout=10)
|
|
else:
|
|
server = __import__("smtplib").SMTP(s.host, s.port, timeout=10)
|
|
if s.use_tls:
|
|
server.starttls()
|
|
|
|
if s.username and s.password:
|
|
server.login(s.username, s.password)
|
|
|
|
server.sendmail(s.from_addr, [to_addr], msg.as_string())
|
|
server.quit()
|
|
log.info(f"[notify] Email sent to {to_addr}: {subject}")
|
|
|
|
except Exception as e:
|
|
log.warning(f"[notify] Failed to send email to {to_addr}: {e}")
|
|
|
|
|
|
def notify_login(username: str, email_addr: Optional[str], ip: str):
|
|
if not cfg.smtp.notify_login or not email_addr:
|
|
return
|
|
|
|
hostname = socket.gethostname()
|
|
now = datetime.datetime.now().strftime("%d/%m/%Y à %H:%M")
|
|
|
|
subject = "Connexion à votre compte NetAdmin"
|
|
text = (
|
|
f"Bonjour {username},\n\n"
|
|
f"Une connexion a été détectée sur votre compte NetAdmin.\n\n"
|
|
f" Date : {now}\n"
|
|
f" Adresse IP : {ip or 'inconnue'}\n"
|
|
f" Serveur : {hostname}\n\n"
|
|
f"Si vous n'êtes pas à l'origine de cette connexion, "
|
|
f"contactez immédiatement votre administrateur.\n\n"
|
|
f"-- NetAdmin"
|
|
)
|
|
html = f"""\
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="utf-8"></head>
|
|
<body style="font-family:Arial,sans-serif;color:#333;max-width:520px;margin:0 auto">
|
|
<h2 style="color:#0d7bc4;border-bottom:2px solid #0d7bc4;padding-bottom:8px">
|
|
Connexion à votre compte NetAdmin
|
|
</h2>
|
|
<p>Bonjour <strong>{username}</strong>,</p>
|
|
<p>Une connexion a été détectée sur votre compte NetAdmin.</p>
|
|
<table style="border-collapse:collapse;margin:16px 0;width:100%">
|
|
<tr style="background:#f5f5f5">
|
|
<td style="padding:8px 12px;font-weight:bold;width:120px">Date</td>
|
|
<td style="padding:8px 12px">{now}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding:8px 12px;font-weight:bold">Adresse IP</td>
|
|
<td style="padding:8px 12px;font-family:monospace">{ip or 'inconnue'}</td>
|
|
</tr>
|
|
<tr style="background:#f5f5f5">
|
|
<td style="padding:8px 12px;font-weight:bold">Serveur</td>
|
|
<td style="padding:8px 12px">{hostname}</td>
|
|
</tr>
|
|
</table>
|
|
<p style="color:#c00;font-weight:bold">
|
|
Si vous n'êtes pas à l'origine de cette connexion,
|
|
contactez immédiatement votre administrateur.
|
|
</p>
|
|
<hr style="border:none;border-top:1px solid #ddd;margin:24px 0">
|
|
<p style="color:#999;font-size:11px">NetAdmin — notification automatique</p>
|
|
</body>
|
|
</html>"""
|
|
|
|
_send(email_addr, subject, text, html)
|
|
|
|
|
|
def notify_role_assigned(
|
|
target_username: str,
|
|
target_email: Optional[str],
|
|
role: str,
|
|
scopes: list,
|
|
assigned_by: str,
|
|
):
|
|
if not cfg.smtp.notify_role_added or not target_email:
|
|
return
|
|
|
|
scope_str = ", ".join(str(s) for s in scopes if s) if scopes and scopes != [None] else "global"
|
|
|
|
subject = f"NetAdmin — Nouveau rôle assigné : {role}"
|
|
text = (
|
|
f"Bonjour {target_username},\n\n"
|
|
f"Un nouveau rôle vous a été assigné sur NetAdmin.\n\n"
|
|
f" Rôle : {role}\n"
|
|
f" Périmètre : {scope_str}\n"
|
|
f" Assigné par : {assigned_by}\n\n"
|
|
f"Connectez-vous à NetAdmin pour consulter vos permissions.\n\n"
|
|
f"-- NetAdmin"
|
|
)
|
|
html = f"""\
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="utf-8"></head>
|
|
<body style="font-family:Arial,sans-serif;color:#333;max-width:520px;margin:0 auto">
|
|
<h2 style="color:#0d7bc4;border-bottom:2px solid #0d7bc4;padding-bottom:8px">
|
|
Nouveau rôle NetAdmin
|
|
</h2>
|
|
<p>Bonjour <strong>{target_username}</strong>,</p>
|
|
<p>Un nouveau rôle vous a été assigné.</p>
|
|
<table style="border-collapse:collapse;margin:16px 0;width:100%">
|
|
<tr style="background:#f5f5f5">
|
|
<td style="padding:8px 12px;font-weight:bold;width:140px">Rôle</td>
|
|
<td style="padding:8px 12px;font-weight:bold;color:#0d7bc4">{role}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding:8px 12px;font-weight:bold">Périmètre</td>
|
|
<td style="padding:8px 12px;font-family:monospace">{scope_str}</td>
|
|
</tr>
|
|
<tr style="background:#f5f5f5">
|
|
<td style="padding:8px 12px;font-weight:bold">Assigné par</td>
|
|
<td style="padding:8px 12px">{assigned_by}</td>
|
|
</tr>
|
|
</table>
|
|
<hr style="border:none;border-top:1px solid #ddd;margin:24px 0">
|
|
<p style="color:#999;font-size:11px">NetAdmin — notification automatique</p>
|
|
</body>
|
|
</html>"""
|
|
|
|
_send(target_email, subject, text, html)
|