Files
notytex/backend/debug_smtp_server.py
Bertrand Benjamin f76b033d55
All checks were successful
Build and Publish Docker Images / Build Frontend Image (push) Successful in 2m56s
Build and Publish Docker Images / Build Backend Image (push) Successful in 3m5s
Build and Publish Docker Images / Build Summary (push) Successful in 3s
feat(mail): restauration de l'envoie de mail
2025-12-04 06:04:13 +01:00

184 lines
6.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Serveur SMTP de débogage pour Notytex
======================================
Serveur SMTP de développement qui affiche les emails en console au lieu de les envoyer.
Idéal pour tester l'envoi de bilans sans configuration SMTP réelle.
Usage:
python debug_smtp_server.py
Configuration dans l'interface web:
- Serveur SMTP: localhost
- Port: 1025
- Utilisateur/Mot de passe: (laisser vides)
- TLS: Désactivé
"""
import asyncio
import email
from email.policy import default
from datetime import datetime
from aiosmtpd.controller import Controller
from aiosmtpd.smtp import SMTP as SMTPServer
class DebugSMTPHandler:
"""Gestionnaire personnalisé pour afficher les emails en console."""
async def handle_DATA(self, server, session, envelope):
"""
Traite les emails reçus et les affiche en console.
Args:
server: Instance du serveur SMTP
session: Session SMTP courante
envelope: Envelope contenant les données de l'email
Returns:
str: Code de statut SMTP
"""
print("\n" + "=" * 80)
print("📧 NOUVEL EMAIL REÇU")
print("=" * 80)
# Informations de l'envelope
print(f"\n🔹 De: {envelope.mail_from}")
print(f"🔹 À: {', '.join(envelope.rcpt_tos)}")
print(f"🔹 Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
# Parse le contenu de l'email
try:
msg = email.message_from_bytes(envelope.content, policy=default)
# En-têtes principaux
print(f"\n📋 HEADERS:")
print(f" Subject: {msg.get('Subject', '(sans sujet)')}")
print(f" From: {msg.get('From', '(inconnu)')}")
print(f" To: {msg.get('To', '(inconnu)')}")
print(f" Date: {msg.get('Date', '(inconnue)')}")
# Parcourir les parties du message
if msg.is_multipart():
print(f"\n📦 MESSAGE MULTIPART ({len(msg.get_payload())} parties)")
for idx, part in enumerate(msg.iter_parts(), 1):
content_type = part.get_content_type()
print(f"\n Partie {idx}: {content_type}")
# Afficher le contenu texte
if content_type == 'text/plain':
text_content = part.get_content()
print(f"\n 📄 CONTENU TEXTE:")
print(" " + "-" * 76)
for line in text_content.split('\n')[:20]: # Limiter à 20 lignes
print(f" {line}")
if len(text_content.split('\n')) > 20:
print(f" ... ({len(text_content.split('\n')) - 20} lignes supplémentaires)")
print(" " + "-" * 76)
# Afficher un aperçu du contenu HTML
elif content_type == 'text/html':
html_content = part.get_content()
print(f"\n 🎨 CONTENU HTML ({len(html_content)} caractères)")
print(" " + "-" * 76)
# Extraire et afficher le titre si présent
if '<title>' in html_content:
import re
title_match = re.search(r'<title>(.*?)</title>', html_content, re.IGNORECASE)
if title_match:
print(f" Titre: {title_match.group(1)}")
# Afficher un extrait du HTML
lines = html_content.split('\n')
preview_lines = [l.strip() for l in lines if l.strip() and not l.strip().startswith('<!')][:10]
for line in preview_lines:
print(f" {line[:100]}")
print(f" ... (aperçu du HTML)")
print(" " + "-" * 76)
# Sauvegarder le HTML pour consultation
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f"debug_email_{timestamp}.html"
try:
with open(filename, 'w', encoding='utf-8') as f:
f.write(html_content)
print(f"\n 💾 HTML sauvegardé dans: {filename}")
except Exception as e:
print(f"\n ⚠️ Erreur sauvegarde HTML: {e}")
else:
# Message simple (non multipart)
content = msg.get_content()
print(f"\n📄 CONTENU:")
print("-" * 80)
print(content[:1000]) # Limiter à 1000 caractères
if len(content) > 1000:
print(f"... ({len(content) - 1000} caractères supplémentaires)")
print("-" * 80)
except Exception as e:
print(f"\n❌ ERREUR lors du parsing de l'email: {e}")
print("\n📋 CONTENU BRUT:")
print("-" * 80)
print(envelope.content.decode('utf-8', errors='replace')[:2000])
print("-" * 80)
print("\n" + "=" * 80)
print("✅ Email traité avec succès")
print("=" * 80 + "\n")
return '250 Message accepted for delivery'
async def run_server():
"""Lance le serveur SMTP et attend indéfiniment."""
handler = DebugSMTPHandler()
controller = Controller(handler, hostname='localhost', port=1025)
controller.start()
print("✅ Serveur démarré avec succès!")
print("📬 En attente d'emails... (Ctrl+C pour arrêter)\n")
try:
# Attendre indéfiniment
while True:
await asyncio.sleep(3600)
finally:
controller.stop()
def main():
"""Lance le serveur SMTP de débogage."""
print("\n" + "=" * 80)
print("🚀 SERVEUR SMTP DE DÉBOGAGE NOTYTEX")
print("=" * 80)
print("\nConfiguration recommandée dans l'interface web:")
print(" • Serveur SMTP: localhost")
print(" • Port: 1025")
print(" • Utilisateur: (laisser vide)")
print(" • Mot de passe: (laisser vide)")
print(" • TLS: Désactivé")
print("\n" + "-" * 80)
print("📡 Démarrage du serveur sur localhost:1025...")
print("-" * 80 + "\n")
try:
asyncio.run(run_server())
except KeyboardInterrupt:
print("\n\n" + "=" * 80)
print("🛑 Arrêt du serveur...")
print("=" * 80)
print("✅ Serveur arrêté proprement\n")
except Exception as e:
print(f"\n❌ ERREUR: {e}")
raise
if __name__ == "__main__":
main()