Отправка писем с формы в Django 3.0

В этом материале создадим простую контактную форму для отправки электронных сообщений с сайта Django 3.0. Воспользуемся возможностями встроенной поддержки email, что позволит без лишних усилий отправлять электронные сообщения, используя сервис SendGrid.

Архив с проектом contact.rar

Первоначальная настройка

Если вы уже знаете как создавать джанго-приложение, этот шаг можно пропустить. Создайте проект — config, приложение — sendemail и виртуальное окружение contact.

Первый шаг — создание отдельной папки для проекта. Создайте ее в ручную или с помощью терминала. В командной строке (Mаc или Linux, для Windows некоторые команды отличаются) выполните следующие команды, чтобы перейти в нужную директорию и создать новую папку «contact».

$ cd ~/ПУТЬ_К_ПАПКЕ
$ mkdir contact && cd contact

Теперь можно установить Django и активировать виртуальную среду.

Примечание:

Есть pipenv у вас не установлен, начните с pip install pipenv
$ pipenv install django==3.0.5
$ pipenv shell

Далее создадим новый проект Django под названием config в приложении sendemail:

(contact) $ django-admin startproject config .
(contact) $ python manage.py startapp sendemail

Чтобы убедиться, что все работает, запустим migrate и runserver.

(contact) $ python manage.py migrate
(contact) $ python manage.py runserver

Если теперь открыть ссылку 127.0.0.1:8000, то должно появиться приблизительно следующее:

Первоначальная настройка

Обновление settings.py

Созданное приложение теперь нужно явно добавить в проект Django. В файле settings.py следует записать sendemail в разделе INSTALLED_APPS.


# config/settings.py
INSTALLED_APPS [
'sendemail.apps.SendemailConfig', # новая строка
...
]

Затем в этом же файле нужно создать DEFAULT_FROM_EMAIL — ваша@почта.com и RECIPIENTS_EMAIL — список почт получателей по уполчанию. Также стоит обновить EMAIL_BACKEND, указав, какой бэкенд email используется — в данном случае это console. Это нужно, чтобы почта выводилась в командной строке.


# config/settings.py
RECIPIENTS_EMAIL = ['manager@mysite.com'] # замените на свою почту
DEFAULT_FROM_EMAIL = 'admin@mysite.com' # замените на свою почту
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

Обновление urls.py

После добавления приложения в проект Django нужно обновить корневой файл config/urls.py, добавив include в верхней строке, а также новый urlpattern в приложении:


# config/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('', include('sendemail.urls')),
]

Дальше создайте файл sendemail/urls.py в приложении вручную или:

touch sendemail/urls.py

Теперь — этот код. Благодаря ему основная контактная форма будет доступна по ссылке email/, а удачная отправка — перенаправлять на success/.


# sendemail/urls.py
from django.contrib import admin
from django.urls import path

from .views import contact_view, success_view

urlpatterns = [
path('contact/', contact_view, name='contact'),
path('success/', success_view, name='success'),
]

Создание forms.py

Внутри приложения sendemail теперь нужно создать новый файл forms.py.

touch sendemail/forms.py

Он будет содержать все поля для самой формы. Потребуются три: from_email, subject и message.


# sendemail/forms.py
from django import forms

class ContactForm(forms.Form):
from_email = forms.EmailField(label='Email', required=True)
subject = forms.CharField(label='Тема', required=True)
message = forms.CharField(label='Сообщение', widget=forms.Textarea, required=True)

Будем использовать встроенный в Django Forms API для быстрого создания трех полей.

Создание views.py

Создадим представление, которое будет выполнять основную работу для контактной формы. Обновим существующий файл sendemail/views.py:


from django.shortcuts import render

from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from .forms import ContactForm
from config.settings import RECIPIENTS_EMAIL, DEFAULT_FROM_EMAIL

def contact_view(request):
# если метод GET, вернем форму
if request.method == 'GET':
form = ContactForm()
elif request.method == 'POST':
# если метод POST, проверим форму и отправим письмо
form = ContactForm(request.POST)
if form.is_valid():
subject = form.cleaned_data['subject']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
try:
send_mail(f'{subject} от {from_email}', message,
DEFAULT_FROM_EMAIL, RECIPIENTS_EMAIL)
except BadHeaderError:
return HttpResponse('Ошибка в теме письма.')
return redirect('success')
else:
return HttpResponse('Неверный запрос.')
return render(request, "email.html", {'form': form})

def success_view(request):
return HttpResponse('Приняли! Спасибо за вашу заявку.')

Сначала импортируем send_email и BadHeaderError для безопасности. После этого добавим ссылку на класс ContactForm, который был создан в файле forms.py.

Создание шаблонов

В качестве финального шага нужно создать шаблоны для сообщения и страницы с информацией об успешной отправке. Для этого используем новую папку templates в директории с проектом.

(contact) $ mkdir templates
(contact) $ touch templates/email.html

Теперь обновим файл settings.py, чтобы Django знал, где искать папку с шаблонами. Обновим настройку DIRS в TEMPLATES.


# config/settings.py
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
...
},
]

Далее обновим сами файлы шаблонов, используя следующий код:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Пример отправки сообщений</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
  <h1 class="text-center">Оставьте заявку</h1>
  <div class="container text-center">
    <div id="form_container">
      <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <div class="form-actions form-group ">
          <button type="submit" class="form-control btn btn-success">Отправить</button>
        </div>
      </form>
    </div>
  </div>
</body>
</html>

Отправка первого сообщения

Убедитесь, что сервер запущен с помощью команды python manage.py runserver и откройте http://127.0.0.1:8000/contact в браузере. Заполните форму и нажмите кнопку Отправить.

Отправка первого сообщения

Программа перенаправит на страницу http://127.0.0.1:8000/success, если сообщение отправилось.

Отправка первого сообщения

А в консоли должно отобразиться, что сообщение отправилось:

Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Subject: =?utf-8?b?0J/RgNC40LLQtdGC?=
From: admin@mysite.com
To: manager@mysite.com
Date: Sat, 03 Oct 2020 11:10:29 -0000
Message-ID: <160172342967.9128.15896163902795968694@DESKTOP-4G7VN>

Email-сервис

Для реальной отправки сообщений нужно настроить сервис: SendGrid, mailgun или SES. К счастью, в Django их очень легко использовать.

Для использования SendGrid нужно создать бесплатный аккаунт и выбрать вариант SMTP. Его легче настраивать при работе с Web API.

Необходимо выполнить верификацию отправителя. Инструкции доступны по этой ссылке. Если раньше можно было отправлять сообщения с бесплатных адресов (gmail.com или yahoo.com), но теперь это не будет работать из-за протокола email-аутентификации DMARC. Поэтому для реальной отправки сообщений нужно почту на своем домене, владение которой придется подтвердить.

Отправка писем с формы в Django 3.0

После добавления отправителя на странице https://app.sendgrid.com/settings/sender_auth/senders/new, подтвердите почту и переходите к настройке Web API https://app.sendgrid.com/guide/integrate/langs/python.

Следующее окно требует указать название для API-ключа. После этого нужно нажать на Create Key.

Отправка писем с формы в Django 3.0

Следуйте инструкциям. На момент написания нужно установить библиотеку sendgrid и отправить тестовое письмо. Можете воспользоваться этим файлом sg_verify.py. Пройдя все этапы вы увидите сообщение об успешном подключении:

Отправка писем с формы в Django 3.0

Дальше обновим файл settings.py, поменяв значение console на smtp в переменной EMAIL_BACKEND. Также добавим еще несколько полей. А также EMAIL_HOST_PASSWORD с ключем аккаунта SendGrid.


# config/settings.py
# почты для получения писем
RECIPIENTS_EMAIL = ['manager@mysite.com']
# почта отправителя по умолчанию, та что верифицирована
DEFAULT_FROM_EMAIL = 'admin@myiyte.com'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_HOST_USER = 'apikey'
# ваш уникальный апи-ключ с сайта sendgrid
EMAIL_HOST_PASSWORD = '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'
EMAIL_PORT = 587
EMAIL_USE_TLS = True

Вернемся на http://127.0.0.1:8000/contact/, заполним и отправим форму еще раз. Работает!

Отправка писем с формы в Django 3.0

Выводы

После всех этих этапов у вас будет рабочее приложение с функцией отправки реальных сообщений из Django. Часто это нужно при регистрации пользователей, сбросе пароля, быстрых ответов и так далее.

Обучение с трудоустройством

Профессия Python-разработчик / Skillbox

Профессия Python-разработчик / Skillbox

7 500 3 750 ₽/мес.
Факультет Python-разработки / GeekBrains

Факультет Python-разработки / GeekBrains

4 990 ₽/мес.
Факультет Аналитики Big Data / GeekBrains

Факультет Аналитики Big Data / GeekBrains

7 490 ₽/мес.
Профессия Data Scientist / Skillbox

Профессия Data Scientist / Skillbox

8 167 4 083 ₽/мес.

Тест на знание python

Что выведет этот код?
Какая из функций python делает вывод в консоль?
Какой будет результат выполнения кода — print(type(lambda: None)) ?
Какой будет результат выполнения кода — print('Monty' + 'Python') ?
Что выведет этот код?
Александр
Я создал этот блог в 2018 году, чтобы распространять полезные учебные материалы, документации и уроки на русском. На сайте опубликовано множество статей по основам python и библиотекам, уроков для начинающих и примеров написания программ.