Bot commit: Добавлен файл email_task.py

This commit is contained in:
Vladislav 2026-06-30 19:13:50 -04:00
parent dc9d3d48ce
commit 623d452d7d

114
email_task.py Normal file
View File

@ -0,0 +1,114 @@
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from celery import Celery
from config import *
from templates import templates
import logging
from typing import Optional
import asyncio
from email.utils import formatdate, make_msgid
def build_unsubscribe_url(email: str, token: str, base_url: str) -> str:
return f"{base_url}/api/v1/email/unsubscribe?token={token}&email={email}"
async def create_email_message(
to_email: str,
subject: str,
html_content: str,
user_id: int = None,
):
msg = MIMEMultipart("alternative")
msg['From'] = f"{FROM_NAME} <{FROM_EMAIL}>"
msg['To'] = to_email
msg['Subject'] = subject
msg['Message-ID'] = make_msgid(domain=FROM_EMAIL.split('@')[1])
msg['Date'] = formatdate(localtime=True)
msg['X-Priority'] = "3"
msg['Importance'] = "normal"
msg['X-Auto-Response-Suppress'] = "All"
# token = await create_unsubscribe_token(to_email, user_id)
unsubscribe_url = build_unsubscribe_url(to_email, None, FULL_DOMAIN)
if to_email != FROM_EMAIL:
msg['List-Unsubscribe'] = f"<{unsubscribe_url}>"
msg['List-Unsubscribe-Post'] = "List-Unsubscribe=One-Click"
msg.attach(MIMEText(html_content, 'html'))
return msg
def connect(email_server, email_port):
server = smtplib.SMTP(email_server, email_port)
server.starttls(context=ctx)
return server
def send_email(
to_email: str,
html_content: str,
subject: str,
user_id: Optional[str] = None,
) -> bool:
msg =asyncio.run(create_email_message(
to_email=to_email,
subject=subject,
html_content=html_content,
user_id=user_id,
))
try:
with connect(EMAIL_SMTP_SERVER, EMAIL_SMTP_PORT) as server:
server.login(FROM_EMAIL, EMAIL_PASS)
server.send_message(msg)
# server.close()
logging.info(f"Email sent successfully to: {to_email} | Subject: {subject}")
return True
except Exception as e:
logging.error(
f"Error sending email to: {to_email}, "
f"Subject: {subject}, Error: {str(e)}"
)
return False
celery_app_email = Celery('emails', broker=f'amqps://admin:{RABBITMQ_PASS}@{RABBITMQ_HOST}/email', backend=f'redis://{REDIS_HOST}:{6379 if PROD else 30003}/0', task_track_started=True )
@celery_app_email.task(
bind=True,
rate_limit='30/m',
name='email_task.send_email',
retry_backoff=True,
retry_backoff_max=600,
retry_jitter=True,
max_retries=3,
soft_time_limit=30,
time_limit=45,
)
def notify(self, to_email: str, data: dict, subject: str = EMAIL_SUBJECT, template: str = 'main.html'):
logging.info(f"Отправка email на {to_email} (попытка {self.request.retries + 1})")
try:
html_content = templates.get_template(f"email/{template}").render({
"subject": subject,
"data": data
})
ok = send_email(to_email, html_content, subject=subject)
if ok:
return ok
else:
raise self.retry(exc=exc)
except Exception as exc:
logging.warning(
f"Ошибка при отправке email на {to_email} (попытка {self.request.retries + 1}): {exc}"
)
raise self.retry(exc=exc)