Пользователи любого сервиса всегда теряют, забывают или компрометируют свои пароли: таково их неотъемлемое свойство. Поэтому в модуль django.contib.auth встроен сценарий восстановление пароля: пользователь отправляет через специальную веб-форму свой email, и если этот адрес есть в базе, ему уходит письмо с инструкцией по восстановлению.
Но мы-то знаем, что никакое письмо никуда не уходит. Для отправки писем в распоряжении разработчика должен быть настроенный почтовый сервер и зарегистрированный на нём аккаунт, от имени которого будет уходить письмо. Сейчас в проекте Yatube всего этого нет, и при попытке восстановить пароль текст письма просто появится в консоли, но никуда не отправится и нигде не сохранится.
Можно создать свой почтовый сервер или работать с крупными почтовыми сервисами, но они могут быть недоступны, если вы работаете в корпоративной сети или, например, оказались оффлайн на одном из островов Индонезии.
Для обхода этой проблемы в Django можно настроить эмуляцию работы почтового сервера. Система будет производить все действия по отправке писем, но в реальности они никуда отправляться не будут. При тестировании проекта это удобно: почтовый ящик не будет завален тестовыми письмами, да и отлаживать отправку почты можно оффлайн.
Сохранение писем в файлы
В Django есть несколько модулей для отправки писем, подключить их можно через ключ конфигурации EMAIL_BACKEND в settings.py
:
PYTHONEMAIL_BACKEND = 'django.core.mail.backends.XXX'
Вместо XXX
указывается название модуля. Встроенные в Django почтовые модули могут отправлять почту по протоколу SMTP, выводить в консоль содержимое письма, сохранять письма в файлы, хранить их в памяти или просто ничего не делать (даже для «ничего не делать» написан специальный модуль).
Подключите к проекту модуль filebased.EmailBackend: он будет сохранять текст отправленных электронных писем в файлы в отдельную директорию.Добавьте в settings.py
такой код:
# подключаем движок filebased.EmailBackend
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
# указываем директорию, в которую будут складываться файлы писем
EMAIL_FILE_PATH = os.path.join(BASE_DIR, 'sent_emails')
Создайте папку /sent_emails
в головной директории проекта.
Теперь при запросе на восстановление пароля система будет делать вид, что отправила письмо, но эти письма будут «отправляться» в директорию sent_emails
. Если эта директория не существует, она будет создана после первого «письма».
Пройдите процедуру восстановления пароля для своего аккаунта. Если вы всё настроили правильно — в sent_emails
будут созданы файлы с текстом уведомления. Вот тут:
└── yatube
├── core
├── posts
├── sent_emails <-- Директория для хранения писем
├── templates
├── users
└── manage.py
При восстановлении забытого пароля Django проверяет, существует ли указанный в форме адрес почты у зарегистрированных пользователей. Если такого адреса в базе нет — письмо не будет отправлено.
Делать не нужно, но знать полезно
Для работы с почтой в Django есть специальный модуль Mail, отправкой писем занимаются функции из этого модуля:
- send_mail() — для отправки единичного письма получателю.
- send_mass_mail() — для отправки множества писем.
- mail_admins — отправить письмо администраторам сайта. Список адресов администраторов перечисляется в списке ADMINS в
settings.py
. - mail_managers — для отправки писем менеджерам сайта. Большой проект может управляться большим количеством сотрудников, и в списке MANAGERS конфига можно задать список их почтовых адресов, по которым будет идти служебная рассылка.
Отдельная функция для массовой отправки писем потребовалась потому, что каждое подключение к почтовому серверу технически обходится дорого. Надо дождаться соединения, отправить авторизационную информацию, затем отправить сообщения — при массовой рассылке эти операции необходимо оптимизировать отдельно.
Самый простой способ отправить письмо из собственной view-функции или класса — вызвать стандартную функцию Django send_mail()
и передать ей на вход необходимые данные:
from django.core.mail import send_mail
send_mail(
'Тема письма',
'Текст письма.',
'from@example.com', # Это поле "От кого"
['to@example.com'], # Это поле "Кому" (можно указать список адресов)
fail_silently=False, # Сообщать об ошибках («молчать ли об ошибках?»)
)