306 lines
17 KiB
Python
306 lines
17 KiB
Python
import smtplib
|
|
from email.mime.multipart import MIMEMultipart
|
|
from email.mime.text import MIMEText
|
|
from typing import Optional, List
|
|
import logging
|
|
|
|
from config.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AuthEmailService:
|
|
@staticmethod
|
|
def _send_email(
|
|
to: str,
|
|
subject: str,
|
|
html_body: str,
|
|
cc: Optional[List[str]] = None,
|
|
bcc: Optional[List[str]] = None,
|
|
) -> bool:
|
|
try:
|
|
msg = MIMEMultipart("alternative")
|
|
msg["From"] = settings.smtp_from
|
|
msg["To"] = to
|
|
msg["Subject"] = subject
|
|
|
|
if cc:
|
|
msg["Cc"] = ", ".join(cc)
|
|
|
|
msg.attach(MIMEText(html_body, "html", "utf-8"))
|
|
|
|
recipients = [to]
|
|
if cc:
|
|
recipients.extend(cc)
|
|
if bcc:
|
|
recipients.extend(bcc)
|
|
|
|
with smtplib.SMTP(
|
|
settings.smtp_host, settings.smtp_port, timeout=30
|
|
) as server:
|
|
if settings.smtp_use_tls:
|
|
server.starttls()
|
|
|
|
if settings.smtp_user and settings.smtp_password:
|
|
server.login(settings.smtp_user, settings.smtp_password)
|
|
|
|
server.sendmail(settings.smtp_from, recipients, msg.as_string())
|
|
|
|
logger.info(f"Email envoye: {subject} vers {to}")
|
|
return True
|
|
|
|
except smtplib.SMTPException as e:
|
|
logger.error(f"Erreur SMTP envoi email: {e}")
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"Erreur envoi email: {e}")
|
|
return False
|
|
|
|
@classmethod
|
|
def send_verification_email(cls, email: str, token: str, base_url: str) -> bool:
|
|
verification_link = f"{base_url}/auth/verify-email?token={token}"
|
|
|
|
html_body = f"""
|
|
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Verification de votre email</title>
|
|
</head>
|
|
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background-color: #f5f5f5;">
|
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="background-color: #f5f5f5; padding: 40px 20px;">
|
|
<tr>
|
|
<td align="center">
|
|
<table role="presentation" width="600" cellspacing="0" cellpadding="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
<tr>
|
|
<td style="background-color: #4F46E5; padding: 32px; text-align: center; border-radius: 8px 8px 0 0;">
|
|
<h1 style="color: #ffffff; margin: 0; font-size: 24px; font-weight: 600;">Verification de votre email</h1>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 40px 32px;">
|
|
<p style="color: #374151; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
|
|
Bienvenue sur Sage Dataven. Pour activer votre compte, veuillez verifier votre adresse email en cliquant sur le bouton ci-dessous.
|
|
</p>
|
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0">
|
|
<tr>
|
|
<td align="center" style="padding: 24px 0;">
|
|
<a href="{verification_link}" style="display: inline-block; background-color: #4F46E5; color: #ffffff; text-decoration: none; padding: 14px 32px; border-radius: 6px; font-size: 16px; font-weight: 500;">Verifier mon email</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p style="color: #6B7280; font-size: 14px; line-height: 1.6; margin: 24px 0 0;">
|
|
Si le bouton ne fonctionne pas, copiez ce lien dans votre navigateur :
|
|
</p>
|
|
<p style="color: #4F46E5; font-size: 14px; word-break: break-all; background-color: #F3F4F6; padding: 12px; border-radius: 4px; margin: 12px 0 24px;">
|
|
{verification_link}
|
|
</p>
|
|
<p style="color: #EF4444; font-size: 14px; margin: 0;">
|
|
Ce lien expire dans 24 heures.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="background-color: #F9FAFB; padding: 24px 32px; border-radius: 0 0 8px 8px; border-top: 1px solid #E5E7EB;">
|
|
<p style="color: #9CA3AF; font-size: 12px; margin: 0; text-align: center;">
|
|
Si vous n'avez pas cree de compte, ignorez cet email.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
return cls._send_email(
|
|
email, "Verifiez votre adresse email - Sage Dataven", html_body
|
|
)
|
|
|
|
@classmethod
|
|
def send_password_reset_email(
|
|
cls, email: str, token: str, frontend_url: str
|
|
) -> bool:
|
|
reset_link = f"{frontend_url}/reset-password?token={token}"
|
|
|
|
html_body = f"""
|
|
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Reinitialisation de mot de passe</title>
|
|
</head>
|
|
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background-color: #f5f5f5;">
|
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="background-color: #f5f5f5; padding: 40px 20px;">
|
|
<tr>
|
|
<td align="center">
|
|
<table role="presentation" width="600" cellspacing="0" cellpadding="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
<tr>
|
|
<td style="background-color: #DC2626; padding: 32px; text-align: center; border-radius: 8px 8px 0 0;">
|
|
<h1 style="color: #ffffff; margin: 0; font-size: 24px; font-weight: 600;">Reinitialisation du mot de passe</h1>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 40px 32px;">
|
|
<p style="color: #374151; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
|
|
Vous avez demande la reinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour creer un nouveau mot de passe.
|
|
</p>
|
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0">
|
|
<tr>
|
|
<td align="center" style="padding: 24px 0;">
|
|
<a href="{reset_link}" style="display: inline-block; background-color: #DC2626; color: #ffffff; text-decoration: none; padding: 14px 32px; border-radius: 6px; font-size: 16px; font-weight: 500;">Reinitialiser mon mot de passe</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p style="color: #6B7280; font-size: 14px; line-height: 1.6; margin: 24px 0 0;">
|
|
Si le bouton ne fonctionne pas, copiez ce lien :
|
|
</p>
|
|
<p style="color: #DC2626; font-size: 14px; word-break: break-all; background-color: #FEF2F2; padding: 12px; border-radius: 4px; margin: 12px 0 24px;">
|
|
{reset_link}
|
|
</p>
|
|
<p style="color: #EF4444; font-size: 14px; margin: 0;">
|
|
Ce lien expire dans 1 heure.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="background-color: #FEF2F2; padding: 24px 32px; border-radius: 0 0 8px 8px; border-top: 1px solid #FECACA;">
|
|
<p style="color: #991B1B; font-size: 12px; margin: 0; text-align: center;">
|
|
Si vous n'avez pas demande cette reinitialisation, ignorez cet email. Votre mot de passe restera inchange.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
return cls._send_email(
|
|
email, "Reinitialisation de votre mot de passe - Sage Dataven", html_body
|
|
)
|
|
|
|
@classmethod
|
|
def send_password_changed_notification(cls, email: str) -> bool:
|
|
html_body = """
|
|
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Mot de passe modifie</title>
|
|
</head>
|
|
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background-color: #f5f5f5;">
|
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="background-color: #f5f5f5; padding: 40px 20px;">
|
|
<tr>
|
|
<td align="center">
|
|
<table role="presentation" width="600" cellspacing="0" cellpadding="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
<tr>
|
|
<td style="background-color: #059669; padding: 32px; text-align: center; border-radius: 8px 8px 0 0;">
|
|
<h1 style="color: #ffffff; margin: 0; font-size: 24px; font-weight: 600;">Mot de passe modifie</h1>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 40px 32px;">
|
|
<p style="color: #374151; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
|
|
Votre mot de passe a ete modifie avec succes.
|
|
</p>
|
|
<p style="color: #374151; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
|
|
Si vous n'etes pas a l'origine de ce changement, contactez immediatement notre support.
|
|
</p>
|
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="background-color: #FEF3C7; border-left: 4px solid #F59E0B; border-radius: 4px;">
|
|
<tr>
|
|
<td style="padding: 16px;">
|
|
<p style="color: #92400E; font-size: 14px; margin: 0;">
|
|
<strong>Securite :</strong> Toutes vos sessions actives ont ete deconnectees. Vous devrez vous reconnecter sur tous vos appareils.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="background-color: #F9FAFB; padding: 24px 32px; border-radius: 0 0 8px 8px; border-top: 1px solid #E5E7EB;">
|
|
<p style="color: #9CA3AF; font-size: 12px; margin: 0; text-align: center;">
|
|
Sage Dataven - Notification de securite
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
return cls._send_email(
|
|
email, "Votre mot de passe a ete modifie - Sage Dataven", html_body
|
|
)
|
|
|
|
@classmethod
|
|
def send_security_alert(
|
|
cls, email: str, alert_type: str, details: str, ip_address: Optional[str] = None
|
|
) -> bool:
|
|
ip_info = (
|
|
f"<p style='color: #6B7280; font-size: 14px;'>Adresse IP : {ip_address}</p>"
|
|
if ip_address
|
|
else ""
|
|
)
|
|
|
|
html_body = f"""
|
|
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Alerte de securite</title>
|
|
</head>
|
|
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background-color: #f5f5f5;">
|
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="background-color: #f5f5f5; padding: 40px 20px;">
|
|
<tr>
|
|
<td align="center">
|
|
<table role="presentation" width="600" cellspacing="0" cellpadding="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
<tr>
|
|
<td style="background-color: #B91C1C; padding: 32px; text-align: center; border-radius: 8px 8px 0 0;">
|
|
<h1 style="color: #ffffff; margin: 0; font-size: 24px; font-weight: 600;">Alerte de securite</h1>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 40px 32px;">
|
|
<p style="color: #374151; font-size: 16px; line-height: 1.6; margin: 0 0 16px;">
|
|
<strong>{alert_type}</strong>
|
|
</p>
|
|
<p style="color: #374151; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
|
|
{details}
|
|
</p>
|
|
{ip_info}
|
|
<p style="color: #6B7280; font-size: 14px; margin: 24px 0 0;">
|
|
Si vous reconnaissez cette activite, vous pouvez ignorer ce message. Sinon, nous vous recommandons de changer votre mot de passe immediatement.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="background-color: #FEF2F2; padding: 24px 32px; border-radius: 0 0 8px 8px; border-top: 1px solid #FECACA;">
|
|
<p style="color: #991B1B; font-size: 12px; margin: 0; text-align: center;">
|
|
Sage Dataven - Alerte de securite automatique
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
return cls._send_email(
|
|
email, f"Alerte de securite : {alert_type} - Sage Dataven", html_body
|
|
)
|