From 81ee935150d00562455cb727af55f146e39ad504 Mon Sep 17 00:00:00 2001 From: Kobe Date: Mon, 2 Jun 2025 14:33:04 +0200 Subject: [PATCH] sending mails using SMTP --- routes/__pycache__/main.cpython-313.pyc | Bin 78344 -> 78344 bytes .../__pycache__/notification.cpython-313.pyc | Bin 11525 -> 14952 bytes utils/notification.py | 87 +++++++++++++++++- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/routes/__pycache__/main.cpython-313.pyc b/routes/__pycache__/main.cpython-313.pyc index 2ecb22fc97f5a94af03922d8d869a048e8e62b93..235ab633e184bd63f5c00e1d986030bb1c37c311 100644 GIT binary patch delta 24 ecmeBp!qV}Ch3hjfFBbz4B+P8&+RDZF&kz7(vIlhl delta 24 ecmeBp!qV}Ch3hjfFBbz4Je<=FDtD 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 delta 2082 zcmZ8hPfQ$T6#r&t|1S(s3T2lTc98;8u(YtWsFX`nY!?f$1GSM&*JWpbh5gqzvq74e z#X}FqMB99c(b${Ow223m#Pp`AiC#>sRun&NYV=|+4W=euJow(Xw9w9GfAi-3fA4$W z`^&lXvi6|1HpuY#aN*d(chM_ai{f1A?wyD-gBj|$KM{aHA_&1m2ttV(sF8g4cx|E< zY7-i0^4l|Bm#Bw&Nqff|61!lRqUZ^^4mM$n5IuQBS$eo=u| zW3RMpK-*nXT9Z^|jEdiA+)~_%}Q8Nt9!GVnfWgrShrEIDmEIC~_geTP+x+tEE-bM^9Z*Xb_dDHNUTobZC>l%bH>Y6=;! z0RC0{KRCDcrFJ98mwVcV4o_&?Iq~um1y{Qt<)|%nL=?H{A7QKIIgS-ULt(9W!u?eL8xid6oC`3W~`D!-yRE~ z2zos<@b9Asln(x1^vJ<(aN+$WM%|m8M%{Frt;d6Bb#;9-cD7Uf zsndfr45L)|%C-g6&_J~dNW#grn_c7XCXz#jz$BO?ILSMD->(c2d4#}CKz)H138)QV z5YTu4NeE=#&G-l*c^N~Kyvw)1HwaLC2 zSA}vM(-oMZDslc+{~u?`Sg5EjbJ=c(@MenneAc<{f;g(kN^O@6 zvK1nqhNaX__bDvZgfi-Uz`r_lOet~Y@cl`798{+aFs1vRtkzpDnRpwvLxYXlx=WTx zm)=D;Z#Bh0@UxU4Uek^4#Ko=mY^a3F_5oAw6whp!GcdtXEP zGsdqDK8-Hk>JRfj2Opf4Cjcnf&P90ff?1dyV3iZ*wLBE5|X+)F)^jP?hPP~b9k?fcpWf-FCdq2fXe6-roN(6A)UXW`} z_*1DuI&Y;?ATOxAeRSu9n#HY(%e0sSx;Aof ztWmgvJUVncj<~5RigJgA@3N6~HgcEs-DZ7vSr=;_;twEZ3GSF{cO<}<&zDTDt3mE-!~ diff --git a/utils/notification.py b/utils/notification.py index e3354eb..aa41a9d 100644 --- a/utils/notification.py +++ b/utils/notification.py @@ -1,13 +1,90 @@ from flask import request -from models import Notif, NotifType, db, EmailTemplate, Mail +from models import Notif, NotifType, db, EmailTemplate, Mail, KeyValueSettings from typing import Optional, Dict, Any, List from datetime import datetime, timedelta from flask_login import current_user from sqlalchemy import desc import logging +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +import json logger = logging.getLogger(__name__) +def get_smtp_settings() -> Optional[Dict[str, Any]]: + """ + Get SMTP settings from the database. + + Returns: + Dictionary containing SMTP settings or None if not configured + """ + try: + smtp_settings = KeyValueSettings.get_value('smtp_settings') + if not smtp_settings: + logger.warning("No SMTP settings found in database") + return None + return smtp_settings + except Exception as e: + logger.error(f"Error retrieving SMTP settings: {str(e)}") + return None + +def send_email_via_smtp(mail: Mail) -> bool: + """ + Send an email using the configured SMTP settings. + + Args: + mail: The Mail object containing the email details + + Returns: + bool: True if email was sent successfully, False otherwise + """ + smtp_settings = get_smtp_settings() + if not smtp_settings: + logger.error("Cannot send email: SMTP settings not configured") + return False + + try: + # Create message + msg = MIMEMultipart() + msg['From'] = f"{smtp_settings['smtp_from_name']} <{smtp_settings['smtp_from_email']}>" + msg['To'] = mail.recipient + msg['Subject'] = mail.subject + + # Attach HTML body + msg.attach(MIMEText(mail.body, 'html')) + + # Create SMTP connection + if smtp_settings['smtp_security'] == 'ssl': + server = smtplib.SMTP_SSL(smtp_settings['smtp_host'], int(smtp_settings['smtp_port'])) + else: + server = smtplib.SMTP(smtp_settings['smtp_host'], int(smtp_settings['smtp_port'])) + if smtp_settings['smtp_security'] == 'tls': + server.starttls() + + # Login if credentials are provided + if smtp_settings['smtp_username'] and smtp_settings['smtp_password']: + server.login(smtp_settings['smtp_username'], smtp_settings['smtp_password']) + + # Send email + server.send_message(msg) + server.quit() + + # Update mail status + mail.status = 'sent' + mail.sent_at = datetime.utcnow() + db.session.commit() + + logger.info(f"Email sent successfully to {mail.recipient}") + return True + + except Exception as e: + logger.error(f"Error sending email: {str(e)}") + mail.status = 'failed' + mail.error_message = str(e) + db.session.commit() + return False + def generate_mail_from_notification(notif: Notif) -> Optional[Mail]: """ Generate a mail record from a notification using the appropriate email template. @@ -98,7 +175,13 @@ def generate_mail_from_notification(notif: Notif) -> Optional[Mail]: notif_id=notif.id ) db.session.add(mail) - logger.debug(f"Created mail record: {mail}") + + # Try to send the email immediately + if send_email_via_smtp(mail): + logger.debug(f"Email sent successfully for notification: {notif}") + else: + logger.warning(f"Failed to send email for notification: {notif}") + return mail except Exception as e: logger.error(f"Error generating mail from notification: {str(e)}")