notifications.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import smtplib
  2. import ssl
  3. from email.mime.text import MIMEText
  4. from flask import current_app
  5. def _get(key, default=""):
  6. from db import Setting
  7. s = Setting.query.filter_by(key=key).first()
  8. return s.value if s else default
  9. def send_job_notification(run, job):
  10. """Envoie une notification email après un job. Silencieux si non configuré."""
  11. if run.status == "success" and _get("notify_on_success", "0") != "1":
  12. return
  13. if run.status == "error" and _get("notify_on_error", "1") != "1":
  14. return
  15. smtp_host = _get("smtp_host")
  16. smtp_to = _get("smtp_to")
  17. if not smtp_host or not smtp_to:
  18. return
  19. instance = current_app.config.get("INSTANCE_NAME", "backupmanager")
  20. if run.status == "success":
  21. subject = f"[{instance}] ✓ {run.archive_name or job.name} — sauvegarde réussie"
  22. d = run.duration_seconds or 0
  23. duration = f"{d // 60}min {d % 60}s" if d >= 60 else f"{d}s"
  24. body = (
  25. f"Sauvegarde réussie\n\n"
  26. f"Job : {job.name}\n"
  27. f"Type : {job.type}\n"
  28. f"Archive : {run.archive_name}\n"
  29. f"Taille : {run.size_human}\n"
  30. f"Durée : {duration}\n"
  31. f"Instance : {instance}\n"
  32. )
  33. else:
  34. subject = f"[{instance}] ✗ {job.name} — ERREUR de sauvegarde"
  35. body = (
  36. f"Erreur lors de la sauvegarde\n\n"
  37. f"Job : {job.name}\n"
  38. f"Type : {job.type}\n"
  39. f"Instance : {instance}\n\n"
  40. f"Détail :\n{run.log_text or '(aucun log)'}\n"
  41. )
  42. try:
  43. _send(
  44. host=smtp_host,
  45. port=int(_get("smtp_port", "587")),
  46. user=_get("smtp_user"),
  47. password=_get("smtp_password"),
  48. from_addr=_get("smtp_from") or _get("smtp_user"),
  49. to_addr=smtp_to,
  50. subject=subject,
  51. body=body,
  52. use_ssl=_get("smtp_ssl", "0") == "1",
  53. use_tls=_get("smtp_tls", "1") == "1",
  54. )
  55. except Exception as exc:
  56. current_app.logger.warning(f"Notification email échouée : {exc}")
  57. def send_test_email(host, port, user, password, from_addr, to_addr, use_ssl, use_tls):
  58. """Envoie un email de test. Lève une exception si ça échoue."""
  59. _send(
  60. host=host,
  61. port=int(port),
  62. user=user,
  63. password=password,
  64. from_addr=from_addr or user,
  65. to_addr=to_addr,
  66. subject="Test SMTP — Backup Manager",
  67. body="Si vous recevez cet email, la configuration SMTP est correcte.",
  68. use_ssl=use_ssl,
  69. use_tls=use_tls,
  70. )
  71. def _send(host, port, user, password, from_addr, to_addr, subject, body, use_ssl, use_tls):
  72. msg = MIMEText(body, "plain", "utf-8")
  73. msg["Subject"] = subject
  74. msg["From"] = from_addr
  75. msg["To"] = to_addr
  76. ctx = ssl.create_default_context()
  77. if use_ssl:
  78. with smtplib.SMTP_SSL(host, port, context=ctx) as smtp:
  79. if user:
  80. smtp.login(user, password)
  81. smtp.sendmail(from_addr, [to_addr], msg.as_string())
  82. else:
  83. with smtplib.SMTP(host, port, timeout=15) as smtp:
  84. if use_tls:
  85. smtp.starttls(context=ctx)
  86. if user:
  87. smtp.login(user, password)
  88. smtp.sendmail(from_addr, [to_addr], msg.as_string())