Site/programmer/utils/email_notifications.py
2026-06-19 19:00:29 +03:00

295 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.core.mail import send_mail, get_connection
from django.template.loader import render_to_string
from django.conf import settings
from django.utils.html import strip_tags
import logging
logger = logging.getLogger(__name__)
def send_callback_notification(callback_request):
"""
Отправляет уведомление о новой заявке на обратный звонок
"""
try:
subject = f'🚨 Новая заявка на обратный звонок от {callback_request.name}'
# HTML версия письма
html_message = render_to_string('emails/callback_notification.html', {
'callback': callback_request,
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
})
# Текстовая версия письма
plain_message = strip_tags(html_message)
# Проверяем настройки email
if not all([settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD]):
logger.error("Email settings are not configured properly")
return False
# Отправляем email
send_mail(
subject=subject,
message=plain_message,
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=settings.ADMIN_EMAILS,
html_message=html_message,
fail_silently=False,
)
logger.info(f"Email notification sent successfully for callback #{callback_request.id}")
return True
except Exception as e:
logger.error(f"Error sending email notification: {e}")
return False
def send_test_email():
"""
Функция для тестирования отправки email
"""
try:
send_mail(
subject='📧 Test Email from Django',
message='This is a test email from your Django application.',
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=settings.ADMIN_EMAILS,
fail_silently=False,
)
return True
except Exception as e:
logger.error(f"Test email failed: {e}")
return False
def send_multiple_callback_notifications(callbacks):
"""
Отправляет уведомления для нескольких заявок, используя одно SMTP-соединение.
Возвращает количество успешно отправленных.
"""
if not callbacks:
return 0
connection = get_connection()
try:
connection.open()
count = 0
for callback in callbacks:
try:
subject = f'🚨 Новая заявка на обратный звонок от {callback.name}'
html_message = render_to_string('emails/callback_notification.html', {
'callback': callback,
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
})
plain_message = strip_tags(html_message)
send_mail(
subject=subject,
message=plain_message,
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=settings.ADMIN_EMAILS,
html_message=html_message,
connection=connection, # используем одно соединение
fail_silently=False,
)
count += 1
except Exception as e:
logger.error(f"Error sending email for callback #{callback.id}: {e}")
connection.close()
return count
except Exception as e:
logger.error(f"Connection error: {e}")
if connection:
connection.close()
return 0
# ===== Уведомления о заказах =====
def send_order_notification(order):
"""
Отправляет уведомление о новом заказе:
- администратору (на ADMIN_EMAILS)
- клиенту (на email из заказа, если указан)
Возвращает True, если хотя бы одно письмо отправлено.
"""
try:
if not all([settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD]):
logger.error("Email settings are not configured properly")
return False
admin_sent = False
client_sent = False
# Письмо администратору
subject_admin = f'🛒 Новый заказ #{order.id} от {order.name}'
html_admin = render_to_string('products/emails/order_admin.html', {
'order': order,
'product': order.product,
'configuration': order.configuration,
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
})
plain_admin = strip_tags(html_admin)
send_mail(
subject=subject_admin,
message=plain_admin,
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=settings.ADMIN_EMAILS,
html_message=html_admin,
fail_silently=False,
)
admin_sent = True
logger.info(f"Order admin notification sent for order #{order.id}")
# Письмо клиенту (если email указан)
if order.email:
subject_client = f'✅ Ваш заказ #{order.id} на {order.product.title} принят'
html_client = render_to_string('products/emails/order_client.html', {
'order': order,
'product': order.product,
'configuration': order.configuration,
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
})
plain_client = strip_tags(html_client)
send_mail(
subject=subject_client,
message=plain_client,
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=[order.email],
html_message=html_client,
fail_silently=False,
)
client_sent = True
logger.info(f"Order client notification sent to {order.email} for order #{order.id}")
return admin_sent or client_sent
except Exception as e:
logger.error(f"Error sending order notification for order #{order.id}: {e}")
return False
def send_multiple_order_notifications(orders):
"""
Отправляет уведомления для нескольких заказов, используя одно SMTP-соединение.
Возвращает количество успешно отправленных заказов.
"""
if not orders:
return 0
connection = get_connection()
try:
connection.open()
count = 0
for order in orders:
try:
# Администратору
subject_admin = f'🛒 Новый заказ #{order.id} от {order.name}'
html_admin = render_to_string('products/emails/order_admin.html', {
'order': order,
'product': order.product,
'configuration': order.configuration,
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
})
plain_admin = strip_tags(html_admin)
send_mail(
subject=subject_admin,
message=plain_admin,
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=settings.ADMIN_EMAILS,
html_message=html_admin,
connection=connection,
fail_silently=False,
)
# Клиенту
if order.email:
subject_client = f'✅ Ваш заказ #{order.id} на {order.product.title} принят'
html_client = render_to_string('products/emails/order_client.html', {
'order': order,
'product': order.product,
'configuration': order.configuration,
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
})
plain_client = strip_tags(html_client)
send_mail(
subject=subject_client,
message=plain_client,
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=[order.email],
html_message=html_client,
connection=connection,
fail_silently=False,
)
count += 1
logger.info(f"Order notifications sent for order #{order.id}")
except Exception as e:
logger.error(f"Error sending order notifications for order #{order.id}: {e}")
connection.close()
return count
except Exception as e:
logger.error(f"Connection error in send_multiple_order_notifications: {e}")
if connection:
connection.close()
return 0
def send_test_order_email():
"""Тестовая отправка письма для проверки настроек почты."""
try:
send_mail(
subject='📧 Test Order Email',
message='This is a test email for order notifications.',
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=settings.ADMIN_EMAILS,
fail_silently=False,
)
return True
except Exception as e:
logger.error(f"Test order email failed: {e}")
return False
# Асинхронная отправка
def send_order_notification_async(order):
"""Выбирает способ отправки в зависимости от DEBUG."""
if settings.DEBUG:
# Используем background-tasks
from ..tasks import send_order_notification_background
send_order_notification_background(order.id)
return True # задача поставлена в очередь
else:
# Используем Celery
try:
from ..tasks import send_order_notification_celery
send_order_notification_celery.delay(order.id)
return True
except (ImportError, AttributeError):
# fallback на синхронную отправку
from .email_notifications import send_order_notification
return send_order_notification(order)
def send_multiple_order_notifications_async(orders):
if settings.DEBUG:
from ..tasks import send_multiple_order_notifications_background
order_ids = list(orders.values_list('id', flat=True))
send_multiple_order_notifications_background(order_ids)
return len(order_ids)
else:
try:
from ..tasks import send_multiple_order_notifications_celery
order_ids = list(orders.values_list('id', flat=True))
send_multiple_order_notifications_celery.delay(order_ids)
return len(order_ids)
except (ImportError, AttributeError):
from .email_notifications import send_multiple_order_notifications
return send_multiple_order_notifications(orders)