Отправка email в Django

Django предоставляет удобный API для отправки электронных писем. Это мощный инструмент для автоматизации уведомлений, рассылок и коммуникации с пользователями.

Настройка SMTP

Базовая конфигурация SMTP в settings.py:

1EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
2EMAIL_HOST = 'smtp.gmail.com'
3EMAIL_PORT = 587
4EMAIL_USE_TLS = True
5EMAIL_HOST_USER = 'your-email@gmail.com'
6EMAIL_HOST_PASSWORD = 'your-app-password'
7DEFAULT_FROM_EMAIL = 'your-email@gmail.com'

Настройка для различных провайдеров

Gmail (с двухфакторной аутентификацией):

1EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
2EMAIL_HOST = 'smtp.gmail.com'
3EMAIL_PORT = 587
4EMAIL_USE_TLS = True
5EMAIL_HOST_USER = 'your-email@gmail.com'
6EMAIL_HOST_PASSWORD = 'your-app-password'  # Пароль приложения, не обычный пароль

Yandex:

1EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
2EMAIL_HOST = 'smtp.yandex.ru'
3EMAIL_PORT = 465
4EMAIL_USE_SSL = True
5EMAIL_HOST_USER = 'your-email@yandex.ru'
6EMAIL_HOST_PASSWORD = 'your-password'

Mail.ru:

1EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
2EMAIL_HOST = 'smtp.mail.ru'
3EMAIL_PORT = 465
4EMAIL_USE_SSL = True
5EMAIL_HOST_USER = 'your-email@mail.ru'
6EMAIL_HOST_PASSWORD = 'your-password'

Отправка простых писем

Базовый пример отправки 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 для получения исключений.