238 lines
6.8 KiB
Python
Executable File
238 lines
6.8 KiB
Python
Executable File
"""Email service.
|
|
|
|
Uses database settings from Admin panel instead of environment variables.
|
|
"""
|
|
|
|
import logging
|
|
import smtplib
|
|
from datetime import UTC, datetime
|
|
from email.mime.multipart import MIMEMultipart
|
|
from email.mime.text import MIMEText
|
|
|
|
from flask import current_app, render_template, url_for
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def get_mail_config():
|
|
"""Get mail configuration from database.
|
|
|
|
Returns:
|
|
dict: Mail configuration from database or defaults
|
|
"""
|
|
try:
|
|
from customer_portal.models import get_db
|
|
from customer_portal.models.settings import PortalSettings
|
|
|
|
db = get_db()
|
|
return PortalSettings.get_mail_config(db)
|
|
except Exception as e:
|
|
logger.error(f"Failed to get mail config from database: {e}")
|
|
# Fallback to app config (environment variables)
|
|
return {
|
|
"mail_server": current_app.config.get("MAIL_SERVER", ""),
|
|
"mail_port": current_app.config.get("MAIL_PORT", 587),
|
|
"mail_use_tls": current_app.config.get("MAIL_USE_TLS", True),
|
|
"mail_use_ssl": current_app.config.get("MAIL_USE_SSL", False),
|
|
"mail_username": current_app.config.get("MAIL_USERNAME", ""),
|
|
"mail_password": current_app.config.get("MAIL_PASSWORD", ""),
|
|
"mail_default_sender": current_app.config.get("MAIL_DEFAULT_SENDER", ""),
|
|
"mail_default_sender_name": "Kundenportal",
|
|
}
|
|
|
|
|
|
def send_email(to: str, subject: str, html_body: str, text_body: str = "") -> bool:
|
|
"""Send email using database SMTP settings.
|
|
|
|
Args:
|
|
to: Recipient email address
|
|
subject: Email subject
|
|
html_body: HTML content
|
|
text_body: Plain text content (optional)
|
|
|
|
Returns:
|
|
True if sent successfully, False otherwise
|
|
"""
|
|
config = get_mail_config()
|
|
|
|
if not config.get("mail_server"):
|
|
logger.error("Mail server not configured")
|
|
return False
|
|
|
|
try:
|
|
# Create message
|
|
msg = MIMEMultipart("alternative")
|
|
msg["Subject"] = subject
|
|
msg["To"] = to
|
|
|
|
# Build sender
|
|
sender_name = config.get("mail_default_sender_name", "Kundenportal")
|
|
sender_email = config.get("mail_default_sender", "")
|
|
if sender_name and sender_email:
|
|
msg["From"] = f"{sender_name} <{sender_email}>"
|
|
else:
|
|
msg["From"] = sender_email
|
|
|
|
# Add plain text
|
|
if text_body:
|
|
msg.attach(MIMEText(text_body, "plain", "utf-8"))
|
|
|
|
# Add HTML
|
|
msg.attach(MIMEText(html_body, "html", "utf-8"))
|
|
|
|
# Connect to SMTP server
|
|
server = config.get("mail_server")
|
|
port = config.get("mail_port", 587)
|
|
use_ssl = config.get("mail_use_ssl", False)
|
|
use_tls = config.get("mail_use_tls", True)
|
|
|
|
if use_ssl:
|
|
smtp = smtplib.SMTP_SSL(server, port)
|
|
else:
|
|
smtp = smtplib.SMTP(server, port)
|
|
if use_tls:
|
|
smtp.starttls()
|
|
|
|
# Login if credentials provided
|
|
username = config.get("mail_username")
|
|
password = config.get("mail_password")
|
|
if username and password:
|
|
smtp.login(username, password)
|
|
|
|
# Send
|
|
smtp.sendmail(sender_email, [to], msg.as_string())
|
|
smtp.quit()
|
|
|
|
logger.info(f"Email sent to {to}: {subject}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to send email to {to}: {e}")
|
|
return False
|
|
|
|
|
|
class EmailService:
|
|
"""Send emails using database SMTP settings."""
|
|
|
|
SUBJECT_MAP = {
|
|
"login": "Ihr Login-Code fuer das Kundenportal",
|
|
"register": "Willkommen - Ihre Registrierung",
|
|
"reset": "Ihr Code zum Zuruecksetzen",
|
|
"prefill": "Ihr Code fuer die Buchung",
|
|
}
|
|
|
|
@staticmethod
|
|
def send_otp(email: str, code: str, purpose: str = "login") -> bool:
|
|
"""Send OTP code via email.
|
|
|
|
Args:
|
|
email: Recipient email address
|
|
code: OTP code
|
|
purpose: OTP purpose (login, register, reset, prefill)
|
|
|
|
Returns:
|
|
True if sent successfully, False otherwise
|
|
"""
|
|
subject = EmailService.SUBJECT_MAP.get(purpose, "Ihr Code")
|
|
|
|
html_body = render_template(
|
|
"emails/otp.html",
|
|
code=code,
|
|
purpose=purpose,
|
|
)
|
|
|
|
text_body = f"""
|
|
Ihr Code: {code}
|
|
|
|
Dieser Code ist 10 Minuten gueltig.
|
|
|
|
Falls Sie diesen Code nicht angefordert haben, ignorieren Sie diese E-Mail.
|
|
"""
|
|
|
|
success = send_email(email, subject, html_body, text_body)
|
|
|
|
if success:
|
|
logger.info(f"OTP email sent to {email} for {purpose}")
|
|
# In development, log the code for testing
|
|
elif current_app.debug:
|
|
logger.warning(f"DEBUG MODE - OTP code for {email}: {code}")
|
|
|
|
return success
|
|
|
|
@staticmethod
|
|
def send_login_notification(email: str, ip_address: str, user_agent: str) -> bool:
|
|
"""Send notification about new login.
|
|
|
|
Args:
|
|
email: Recipient email address
|
|
ip_address: Login IP address
|
|
user_agent: Browser user agent
|
|
|
|
Returns:
|
|
True if sent successfully
|
|
"""
|
|
html_body = render_template(
|
|
"emails/login_notification.html",
|
|
ip_address=ip_address,
|
|
user_agent=user_agent,
|
|
)
|
|
|
|
return send_email(email, "Neue Anmeldung in Ihrem Kundenportal", html_body)
|
|
|
|
@staticmethod
|
|
def send_welcome(email: str, name: str) -> bool:
|
|
"""Send welcome email after registration.
|
|
|
|
Args:
|
|
email: Recipient email address
|
|
name: Customer name
|
|
|
|
Returns:
|
|
True if sent successfully, False otherwise
|
|
"""
|
|
# Get portal URL from config or build it
|
|
portal_url = current_app.config.get("PORTAL_URL", "")
|
|
if not portal_url:
|
|
try:
|
|
portal_url = url_for("main.index", _external=True)
|
|
except RuntimeError:
|
|
portal_url = "http://localhost:8502"
|
|
|
|
html_body = render_template(
|
|
"emails/welcome.html",
|
|
name=name,
|
|
portal_url=portal_url,
|
|
year=datetime.now(UTC).year,
|
|
)
|
|
|
|
text_body = f"""
|
|
Willkommen, {name}!
|
|
|
|
Ihr Kundenkonto wurde erfolgreich erstellt.
|
|
|
|
Im Kundenportal koennen Sie:
|
|
- Ihre Buchungen einsehen
|
|
- Rechnungen herunterladen
|
|
- Videos ansehen
|
|
- Stornierungen beantragen
|
|
|
|
Zum Portal: {portal_url}
|
|
"""
|
|
|
|
success = send_email(
|
|
email, "Willkommen im Kundenportal - Webwerkstatt", html_body, text_body
|
|
)
|
|
|
|
if success:
|
|
logger.info(f"Welcome email sent to {email}")
|
|
elif current_app.debug:
|
|
logger.warning(f"DEBUG MODE - Welcome email would be sent to {email}")
|
|
|
|
return success
|
|
|
|
|
|
# Keep Flask-Mail for backwards compatibility (but not used anymore)
|
|
from flask_mail import Mail
|
|
|
|
mail = Mail()
|