import os import smtplib import ssl from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.utils import formataddr from threading import Thread from flask import render_template_string, render_template from dotenv import load_dotenv load_dotenv() class Mailer: def __init__(self): self.enabled = os.environ.get('MAIL_ENABLED', 'false').lower() == 'true' self.smtp_server = os.environ.get('MAIL_SERVER', 'smtp.gmail.com') self.smtp_port = int(os.environ.get('MAIL_PORT', 587)) self.use_tls = os.environ.get('MAIL_USE_TLS', 'true').lower() == 'true' self.use_ssl = os.environ.get('MAIL_USE_SSL', 'false').lower() == 'true' self.username = os.environ.get('MAIL_USERNAME', '') self.password = os.environ.get('MAIL_PASSWORD', '') self.default_sender = os.environ.get('MAIL_DEFAULT_SENDER', self.username) def is_enabled(self) -> bool: if not self.enabled: return False if not self.username or not self.password: print("Mail: Отсутствуют логин или пароль") return False return True def _get_connection(self): if self.use_ssl: context = ssl.create_default_context() return smtplib.SMTP_SSL(self.smtp_server, self.smtp_port, context=context) else: server = smtplib.SMTP(self.smtp_server, self.smtp_port) if self.use_tls: server.starttls() return server def _send(self, to_emails, subject, body, html_body=None, from_email=None, from_name='SecretText'): if not self.is_enabled(): print(f"Mail: Пропущено письмо (отключено)") return False if not to_emails: print("Mail: Не указаны получатели") return False if isinstance(to_emails, str): to_emails = [to_emails] from_email = from_email or self.default_sender try: msg = MIMEMultipart('alternative') msg['Subject'] = subject msg['From'] = formataddr((from_name, from_email)) msg['To'] = ', '.join(to_emails) msg.attach(MIMEText(body, 'plain', 'utf-8')) if html_body: msg.attach(MIMEText(html_body, 'html', 'utf-8')) with self._get_connection() as server: if self.username and self.password: server.login(self.username, self.password) server.send_message(msg) print(f"Mail: Письмо отправлено на {', '.join(to_emails)}") return True except Exception as e: print(f"Mail: Ошибка отправки: {e}") return False def send_email(self, to_emails, subject, body, html_body=None, from_email=None, from_name='SecretText'): if not self.is_enabled(): print(f"Mail: Письмо не отправлено (отключено)") return None thread = Thread( target=self._send, args=(to_emails, subject, body, html_body, from_email, from_name), daemon=True ) thread.start() return thread def send_email_with_template(self, to_emails, subject, template_name, context=None, from_email=None, from_name='SecretText'): from main import app context = context or {} with app.app_context(): html_body = render_template(template_name, **context) body = f"Письмо от SecretText. Пожалуйста, используйте почтовый клиент с поддержкой HTML." return self.send_email(to_emails, subject, body, html_body, from_email, from_name) def send_user_created_email(self, to_email, username, view_url): subject = f"Ваш аккаунт в SecretText создан!" context = { 'username': username, 'view_url': view_url, 'base_url': self._get_base_url() } return self.send_email_with_template( to_email, subject, 'emails/user_created.html', context ) def _get_base_url(self): from main import app return app.config.get('APP_URL', 'http://localhost:5000') def send_welcome_email(self, to_email, username): subject = f"Добро пожаловать в SecretText, {username}!" context = { 'username': username, 'base_url': self._get_base_url() } return self.send_email_with_template( to_email, subject, 'emails/welcome.html', context ) def send_secret_notification(self, to_email, username, secret_id=None): subject = f"Новый секрет для вас!" context = { 'username': username, 'base_url': self._get_base_url() } return self.send_email_with_template( to_email, subject, 'emails/secret_notification.html', context ) def send_secret_viewed_notification(self, to_email, username): subject = f"Ваш секрет просмотрен!" context = { 'username': username, 'base_url': self._get_base_url() } return self.send_email_with_template( to_email, subject, 'emails/secret_viewed.html', context ) # mailer.py def send_secret_received_email(self, to_email, username, note=None): subject = f"Вам отправили секрет по запросу!" context = { 'username': username, 'note': note, 'base_url': self._get_base_url() } return self.send_email_with_template( to_email, subject, 'emails/secret_received.html', context ) mailer = Mailer() def send_mail(to_emails, subject, body, html_body=None): return mailer.send_email(to_emails, subject, body, html_body) def send_mail_template(to_emails, subject, template_name, context=None): return mailer.send_email_with_template(to_emails, subject, template_name, context) def send_user_created_email(to_email, username, view_url): return mailer.send_user_created_email(to_email, username, view_url) def send_welcome_email(to_email, username): return mailer.send_welcome_email(to_email, username) def send_secret_notification(to_email, username, secret_id=None): return mailer.send_secret_notification(to_email, username, secret_id) def send_secret_viewed_notification(to_email, username): return mailer.send_secret_viewed_notification(to_email, username) def send_secret_received_email(to_email, username, note=None): return mailer.send_secret_received_email(to_email, username, note)