Простой блог на Django - часть 16. Отправка почты

У нас в шаблоне из верхнего меню осталась нереализованной только страничка с контактами, на которой отображается форма - данные с неё должны отправляться на почту. Так что давайте приступим к реализации этого функционала. 

Создадим приложение contacts, которое будет отвечать как за вывод контактной формы, так и за отправку почты. Для этого нам понадобятся две настройки: 

DEFAULT_FROM_EMAIL - почта для отправки,
RECIPIENTS_EMAIL - список получателей. 

Пропишем их в файле newapp/newapp/settings.py главного приложения:

DEFAULT_FROM_EMAIL = 'admin@my.site'
RECIPIENTS_EMAIL = ['noreply@my.site']

Так же, поскольку мы работаем с локальным сервером, то нам понадобится следующая настройка:

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

Она необходима для того, чтобы фреймворк выводил письма в консоли, а не пытался отправить их на почту. 

В файле urls.py нам понадобится 2 маршрута:

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'),
]

Поскольку мы будем работать с полями формы, то, как и всегда в таких случаях, нам понадобится класс с формой. Какие именно поля формы нам нужны, можно посмотреть в файле шаблона contact.html Итак, создаём файл forms.py, со следующим содержимым:

from django import forms

class ContactForm(forms.Form):
  name = forms.CharField(required=True, widget=forms.TextInput(
  attrs = {
    'class': "form-control",
    'placeholder': "Name",
    'autocomplete': 'off'
  }))

  email = forms.EmailField(required=True, widget=forms.TextInput(
  attrs = {
    'class': "form-control",
    'placeholder': "Email Address",
    'autocomplete': 'off'
  }))

  phone = forms.CharField(required=False, widget=forms.TextInput(
  attrs = {
    'class': "form-control",
    'placeholder': "Phone Number",
    'autocomplete': 'off'
  }))

  message = forms.CharField(required=False, widget=forms.Textarea(
  attrs = {
    'class': "form-control",
    'placeholder': "Message",
    'autocomplete': 'off'
  }))

Здесь мы используем Django Forms API, с помощью которого создаём объекты полей, задавая им тип и прописывая соответствующие атрибуты. 

Что касается View функций, то contact_view мы будем использовать для вывода формы, success_view - для её отправки.

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

def success_view(request):
  return render(request, "success.html")

В плане работы с формами, я думаю код в пояснении не нуждается, поскольку с данным объектом нам приходилось работать ранее. Тут может быть интересной разве что функция send_mail, которая используется для отправки почты. 

Шаблон для вывода формы

Нам будет доступен объект form, поля которого мы перечислим и обратимся к их свойствам, для рендеринга непосредственно самих полей формы. Для этого разместим в папке templates файл email.html следующего содержания:

{% extends "index.html" %}
{% block title %} Отправка почты {% endblock %}
{% block content %}
<div class="row">
  <div class="col-lg-8 col-md-10 mx-auto">
    <p>Want to get in touch? Fill out the form below to send me a message and I will get back to you as soon as possible!</p>
 
    <form name="sentMessage" id="contactForm" novalidate method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {% for field in form %}
      <div class="control-group">
        <div class="form-group floating-label-form-group controls">
          <label>{{ field.label }}</label>
          {{ field }}
          <p class="help-block text-danger"></p>
        </div>
      </div>
    {% endfor %}
      <br>
      <div id="success"></div>
      <button type="submit" class="btn btn-primary" id="sendMessageButton">Send</button>
    </form>
  </div>
</div>
{% endblock %}

Шаблон успешной отправки

Здесь всё максимально лаконично, так как мы просто выводим благодарственное сообщение. Создадим файл success.html:

{% extends "index.html" %}
{% block content %}
<div class="row">
  <div class="col-lg-8 col-md-10 mx-auto">
    Спасибо за вашу заявку! Наши менеджеры свяжутся с вами.
  </div>
</div>
{% endblock %}

Теперь пришло время проверить, как это всё работает. Заходим на страничку http://127.0.0.1:8000/contact/contact/, заполняем поля и отправляем форму. При этом в случае успеха и прохождения валидации всех полей формы, вы будете перенаправлены на страницу благодарности, а в консоли отобразится текст письма. 

Отправка писем в реальных условиях (работа на хостинге)

Сейчас у нас письмо при отправке выводится в консоли, однако когда сайт будет работать на сервере, необходимо будет настроить отправку писем через SMTP сервис. Для этого нужно будет произвести некоторые настройки:

1) Значение переменной EMAIL_BACKEND поменять на django.core.mail.backends.smtp.EmailBackend
2) Добавить и заполнить несколько переменных в том же файле settings.py: EMAIL_HOST, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, EMAIL_PORT, EMAIL_USE_TLS

Значения, которыми необходимо будет заполнить данные настройки, будут зависеть от того, какие почтовые сервисы для отправки писем вы будете использовать. 

Посмотреть изменения можно в репозитории - https://github.com/maclen2007/simple_django_blog/commit/4a9c27da6333a2b3662a5fee947b2df34b27f552

Комментарии ()

    Вы должны авторизоваться, чтобы оставлять комментарии.