import smtplib import logging from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from typing import Optional from sqlalchemy.ext.asyncio import AsyncSession from app.core.config import settings from app.core.i18n import locale_manager from app.services.config_service import config from app.db.session import AsyncSessionLocal # Szükséges a beállítások lekéréséhez logger = logging.getLogger("Email-Manager-2.0") class EmailManager: @staticmethod def _get_html_template(template_key: str, variables: dict, lang: str = "hu") -> str: """HTML sablon generálása a fordítási fájlok alapján (Megmaradt az eredeti logika).""" greeting = locale_manager.get(f"email.{template_key}_greeting", lang=lang, **variables) body = locale_manager.get(f"email.{template_key}_body", lang=lang, **variables) button_text = locale_manager.get(f"email.{template_key}_button", lang=lang) footer = locale_manager.get(f"email.{template_key}_footer", lang=lang) link_fallback_text = locale_manager.get("email.link_fallback", lang=lang) return f"""

{greeting}

{body}

{button_text}

{link_fallback_text}
{variables.get('link')}


{footer}

""" @staticmethod async def send_email(recipient: str, template_key: str, variables: dict, lang: str = "hu", db: Optional[AsyncSession] = None): """ E-mail küldése admin-vezérelt szolgáltatóval (SendGrid vagy SMTP). """ # 1. Belső session kezelés, ha kívülről nem kaptunk (pl. háttérfolyamatoknál) session_internal = False if db is None: db = AsyncSessionLocal() session_internal = True try: # 2. Dinamikus beállítások lekérése az adatbázisból (Admin 2.0) provider = await config.get_setting(db, "email_provider", default="disabled") from_email = await config.get_setting(db, "emails_from_email", default="noreply@profibot.hu") from_name = await config.get_setting(db, "emails_from_name", default="Sentinel System") if provider == "disabled": logger.info(f"Email küldés letiltva (Admin config). Cél: {recipient}") return html = EmailManager._get_html_template(template_key, variables, lang) subject = locale_manager.get(f"email.{template_key}_subject", lang=lang) # 3. KÜLDÉSI LOGIKA VÁLASZTÁSA if provider == "sendgrid": api_key = await config.get_setting(db, "sendgrid_api_key") if api_key: return await EmailManager._send_via_sendgrid(api_key, from_email, from_name, recipient, subject, html) logger.warning("SendGrid szolgáltató kiválasztva, de nincs API kulcs!") # Fallback vagy közvetlen SMTP smtp_cfg = await config.get_setting(db, "smtp_config", default={ "host": "localhost", "port": 587, "user": "", "pass": "", "tls": True }) return await EmailManager._send_via_smtp(smtp_cfg, from_email, from_name, recipient, subject, html) finally: if session_internal: await db.close() @staticmethod async def _send_via_sendgrid(api_key: str, from_email: str, from_name: str, recipient: str, subject: str, html: str): try: from sendgrid import SendGridAPIClient from sendgrid.helpers.mail import Mail message = Mail( from_email=(from_email, from_name), to_emails=recipient, subject=subject, html_content=html ) sg = SendGridAPIClient(api_key) response = sg.send(message) logger.info(f"SendGrid siker: {response.status_code} -> {recipient}") return {"status": "success", "provider": "sendgrid"} except Exception as e: logger.error(f"SendGrid hiba: {str(e)}") return {"status": "error", "message": "SendGrid failed"} @staticmethod async def _send_via_smtp(cfg: dict, from_email: str, from_name: str, recipient: str, subject: str, html: str): try: msg = MIMEMultipart() msg["From"] = f"{from_name} <{from_email}>" msg["To"] = recipient msg["Subject"] = subject msg.attach(MIMEText(html, "html")) with smtplib.SMTP(cfg["host"], cfg["port"], timeout=15) as server: if cfg.get("tls", True): server.starttls() if cfg.get("user") and cfg.get("pass"): server.login(cfg["user"], cfg["pass"]) server.send_message(msg) logger.info(f"SMTP siker -> {recipient}") return {"status": "success", "provider": "smtp"} except Exception as e: logger.error(f"SMTP hiba: {str(e)}") return {"status": "error", "message": str(e)} email_manager = EmailManager()