README.md

This commit is contained in:
2026-09-06 17:32:29 +03:00
parent 216da22bc2
commit 7ae77c0775
16 changed files with 811 additions and 56 deletions
+210
View File
@@ -0,0 +1,210 @@
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)