Files
service-finder/backend/app/services/email_manager.py

132 lines
6.0 KiB
Python
Executable File

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"""
<html>
<body style="font-family: Arial, sans-serif; color: #333; line-height: 1.6;">
<div style="max-width: 600px; margin: 0 auto; border: 1px solid #ddd; padding: 30px; border-radius: 10px;">
<h2 style="color: #2c3e50;">{greeting}</h2>
<p>{body}</p>
<div style="text-align: center; margin: 40px 0;">
<a href="{variables.get('link', '#')}"
style="background-color: #3498db; color: white; padding: 15px 30px; text-decoration: none; border-radius: 5px; font-weight: bold; font-size: 16px;">
{button_text}
</a>
</div>
<p style="font-size: 0.85em; color: #777; word-break: break-all;">
{link_fallback_text}<br>
<a href="{variables.get('link')}" style="color: #3498db;">{variables.get('link')}</a>
</p>
<hr style="border: 0; border-top: 1px solid #eee; margin: 30px 0;">
<p style="font-size: 0.8em; color: #999; text-align: center;">{footer}</p>
</div>
</body>
</html>
"""
@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()