Отправка email в Django
Django предоставляет удобный API для отправки электронных писем. Это мощный инструмент для автоматизации уведомлений, рассылок и коммуникации с пользователями.
Настройка SMTP
Базовая конфигурация SMTP в settings.py
:
Настройка для различных провайдеров
Gmail (с двухфакторной аутентификацией):
Yandex:
Mail.ru:
Отправка простых писем
Базовый пример отправки email:
1from django.core.mail import send_mail
2from django.conf import settings
3
4def send_welcome_email(user_email, username):
5 subject = 'Добро пожаловать на наш сайт!'
6 message = f'Привет, {username}! Мы рады видеть тебя в нашей системе.'
7
8 send_mail(
9 subject=subject,
10 message=message,
11 from_email=settings.DEFAULT_FROM_EMAIL,
12 recipient_list=[user_email],
13 fail_silently=False,
14 )
Отправка HTML писем
Создание красивых HTML писем:
1from django.core.mail import send_mail
2from django.template.loader import render_to_string
3from django.utils.html import strip_tags
4
5def send_html_email(user_email, username):
6 subject = 'Добро пожаловать!'
7
8 # HTML версия письма
9 html_message = render_to_string('emails/welcome.html', {
10 'username': username,
11 'site_name': 'Мой сайт'
12 })
13
14 # Текстовая версия (для клиентов без поддержки HTML)
15 plain_message = strip_tags(html_message)
16
17 send_mail(
18 subject=subject,
19 message=plain_message,
20 from_email=settings.DEFAULT_FROM_EMAIL,
21 recipient_list=[user_email],
22 html_message=html_message,
23 fail_silently=False,
24 )
HTML шаблон для письма
Создай файл templates/emails/welcome.html
:
1<!DOCTYPE html>
2<html>
3<head>
4 <meta charset="utf-8">
5 <title>Добро пожаловать</title>
6</head>
7<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
8 <div style="max-width: 600px; margin: 0 auto; padding: 20px;">
9 <h1 style="color: #2c3e50;">Добро пожаловать, {{ username }}!</h1>
10 <p>Мы рады видеть тебя на сайте <strong>{{ site_name }}</strong>.</p>
11 <p>Твой аккаунт успешно создан и готов к использованию.</p>
12 <div style="background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin: 20px 0;">
13 <p style="margin: 0;"><strong>Что дальше?</strong></p>
14 <ul style="margin: 10px 0;">
15 <li>Заполни свой профиль</li>
16 <li>Изучи доступные курсы</li>
17 <li>Присоединяйся к сообществу</li>
18 </ul>
19 </div>
20 <p>Если у тебя есть вопросы, не стесняйся обращаться в поддержку.</p>
21 <p>С уважением,<br>Команда {{ site_name }}</p>
22 </div>
23</body>
24</html>
Отправка писем с вложениями
Использование EmailMessage для отправки файлов:
1from django.core.mail import EmailMessage
2from django.conf import settings
3import os
4
5def send_email_with_attachment(user_email, username, file_path):
6 subject = 'Документ для тебя'
7
8 html_message = render_to_string('emails/document.html', {
9 'username': username
10 })
11
12 email = EmailMessage(
13 subject=subject,
14 body=html_message,
15 from_email=settings.DEFAULT_FROM_EMAIL,
16 to=[user_email]
17 )
18 email.content_subtype = "html"
19
20 # Добавляем вложение
21 if os.path.exists(file_path):
22 with open(file_path, 'rb') as f:
23 email.attach(
24 os.path.basename(file_path),
25 f.read(),
26 'application/pdf'
27 )
28
29 email.send()
Массовая рассылка
Отправка писем множеству получателей:
1from django.core.mail import send_mass_mail
2from django.contrib.auth.models import User
3
4def send_newsletter_to_all_users():
5 # Получаем всех активных пользователей
6 users = User.objects.filter(is_active=True)
7
8 # Создаем список кортежей для массовой отправки
9 email_tuples = []
10 for user in users:
11 email_tuple = (
12 'Новости сайта', # subject
13 f'Привет, {user.username}! У нас есть новости для тебя.', # message
14 settings.DEFAULT_FROM_EMAIL, # from_email
15 [user.email], # recipient_list
16 )
17 email_tuples.append(email_tuple)
18
19 # Отправляем все письма одним вызовом
20 send_mass_mail(email_tuples, fail_silently=False)
Асинхронная отправка email
Использование Celery для фоновой отправки:
1from celery import shared_task
2from django.core.mail import send_mail
3from django.conf import settings
4
5@shared_task
6def send_email_task(subject, message, recipient_list, html_message=None):
7 try:
8 send_mail(
9 subject=subject,
10 message=message,
11 from_email=settings.DEFAULT_FROM_EMAIL,
12 recipient_list=recipient_list,
13 html_message=html_message,
14 fail_silently=False,
15 )
16 return f'Email успешно отправлен на {recipient_list}'
17 except Exception as e:
18 return f'Ошибка отправки email: {str(e)}'
19
20# Использование в коде
21def send_welcome_email_async(user_email, username):
22 subject = 'Добро пожаловать!'
23 message = f'Привет, {username}!'
24
25 # Запускаем задачу в фоне
26 send_email_task.delay(subject, message, [user_email])
Настройка для разработки
Использование консольного бэкенда для тестирования:
1# settings.py для разработки
2if DEBUG:
3 EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
4else:
5 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
6 EMAIL_HOST = 'smtp.gmail.com'
7 EMAIL_PORT = 587
8 EMAIL_USE_TLS = True
9 EMAIL_HOST_USER = 'your-email@gmail.com'
10 EMAIL_HOST_PASSWORD = 'your-app-password'
Обработка ошибок
Надежная отправка с обработкой исключений:
1import logging
2from django.core.mail import send_mail
3from smtplib import SMTPException
4
5logger = logging.getLogger(__name__)
6
7def send_email_safely(subject, message, recipient_list):
8 try:
9 result = send_mail(
10 subject=subject,
11 message=message,
12 from_email=settings.DEFAULT_FROM_EMAIL,
13 recipient_list=recipient_list,
14 fail_silently=False,
15 )
16
17 if result == 1:
18 logger.info(f'Email успешно отправлен на {recipient_list}')
19 return True
20 else:
21 logger.error(f'Ошибка отправки email на {recipient_list}')
22 return False
23
24 except SMTPException as e:
25 logger.error(f'SMTP ошибка при отправке email: {e}')
26 return False
27 except Exception as e:
28 logger.error(f'Неожиданная ошибка при отправке email: {e}')
29 return False
Лучшие практики
- Используй переменные окружения - не храни пароли в коде
- Создавай HTML шаблоны - для красивого оформления писем
- Добавляй текстовую версию - для клиентов без поддержки HTML
- Обрабатывай ошибки - логируй проблемы с отправкой
- Используй очереди - Celery для асинхронной отправки
- Тестируй на staging - перед отправкой в production
- Соблюдай лимиты - не превышай квоты провайдера
- Валидируй email адреса - проверяй корректность перед отправкой
Тестирование email
Создание тестов для проверки отправки:
1from django.test import TestCase
2from django.core import mail
3from django.contrib.auth.models import User
4
5class EmailTestCase(TestCase):
6 def test_welcome_email_sending(self):
7 # Очищаем outbox перед тестом
8 mail.outbox.clear()
9
10 # Отправляем email
11 send_welcome_email('test@example.com', 'testuser')
12
13 # Проверяем, что email был отправлен
14 self.assertEqual(len(mail.outbox), 1)
15 self.assertEqual(mail.outbox[0].to, ['test@example.com'])
16 self.assertEqual(mail.outbox[0].subject, 'Добро пожаловать на наш сайт!')
17
18 def test_html_email_content(self):
19 mail.outbox.clear()
20
21 send_html_email('test@example.com', 'testuser')
22
23 email = mail.outbox[0]
24 self.assertIn('html_message', email.__dict__)
25 self.assertIn('testuser', email.body)
FAQ
Q: Как отправить HTML письмо?
A: Используй параметр html_message
в send_mail
или создай HTML шаблон с помощью render_to_string
.
Q: Почему письма не отправляются с Gmail?
A: Включи двухфакторную аутентификацию и создай пароль приложения в настройках Google аккаунта.
Q: Как отправить письмо с вложением?
A: Используй класс EmailMessage
и метод attach()
для добавления файлов.
Q: Можно ли отправить письмо нескольким получателям?
A: Да, передай список email адресов в recipient_list
или используй send_mass_mail
для массовой рассылки.
Q: Как настроить email для разработки?
A: Используй EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
- письма будут выводиться в консоль.
Q: Как обрабатывать ошибки отправки?
A: Используй try-except блоки, логируй ошибки и настрой fail_silently=False
для получения исключений.