Блог на Django #21: Отправка email

169

Отправлять электронные письма с помощью Django очень просто. В первую очередь нужен локальный SMTP-сервер или определенная конфигурация внешнего в соответствующих настройках в файле settings.py проекта:

  • EMAIL_HOST: хост SMTP-сервера, по умолчанию — localhost.
  • EMAIL_PORT: порт SMTP, по умолчанию — 25.
  • EMAIL_HOST_USER: имя пользователя SMTP-сервера.
  • EMAIL_HOST_PASSWORD: пароль SMTP-сервера.
  • EMAIL_USE_TLS: использовать ли безопасное TLS-соединение.
  • EMAIL_USE_SSL: использовать ли безопасное SSL-соединение.

Если SMTP-сервер использовать не получается, можно задать Django, чтобы он выводил письма в оболочку. Это удобно для тестирования приложения без сервера.

Если нужно отправлять письма, но локального SMTP-сервера нет, можно использовать сервер провайдера. Следующая конфигурация подойдет для отправки через Gmail с помощью Google-аккаунта:

EMAIL_HOST = 'smtp.gmail.com' 
EMAIL_HOST_USER = 'your_account@gmail.com' EMAIL_HOST_PASSWORD = 'your_password' 
EMAIL_PORT = 587 
EMAIL_USE_TLS = True

Запустите команду python manage.py shell для открытия оболочки и отправьте письма следующим образом:

>>> from django.core.mail import send_mail 
>>>> send_mail('Django mail', 'This e-mail was sent with Django.', 
'your_account@gmail.com', ['your_account@gmail.com'], fail_silently=False)

Функция send_mail() принимает тему, сообщение, отправителя и список получателей в качестве аргументов. С помощью необязательного аргумента fail_silent=False можно сделать так, чтобы при неудачной попытке отправки было вызвано исключение. Если вывод — 1, значит письмо было отправлено.

Если будет использоваться аккаунт Gmail, в настройках по ссылке https://myaccount.google.com/lesssecureapps нужно активировать следующий пункт:

отправка email в Django через Gmail

Теперь необходимо добавить функциональность представлению:

Отредактируйте представление post_share в файле views.py приложения blog:

from django.core.mail import send_mail 

def post_share(request, post_id):   
    # Получить пост по id   
    post = get_object_or_404(Post, id=post_id, status='published')   
    sent = False   
    if request.method == 'POST':   
        # Форма была отправлена   
        form = EmailPostForm(request.POST)   
        if form.is_valid():   
            # Поля формы прошли проверку   
	    cd = form.cleaned_data   
            post_url = request.build_absolute_uri(post.get_absolute_url())   
            subject = '{} ({}) recommends you reading " {}"'.format(cd['name'], cd['email'], post.title)   
            message = 'Read "{}" at {}\n\n{}\'s comments: {}'.format(post.title, post_url, cd['name'], cd['comments'])   
            send_mail(subject, message, 'admin@myblog.com', [cd['to']])   
            sent = True   
    else:   
        form = EmailPostForm()   
    return render(request, 'blog/post/share.html', {'post': post,   
						    'form': form,   
						    'sent': sent})

Объявляем переменную sent и задаем для нее значение True, когда пост отправлен. Эта переменная будет использоваться позже в шаблоне, чтобы отображать сообщение об успешной отправке. Поскольку нужно включать ссылку на пост в email, с помощью метода get_absolute_url() можно будет получить абсолютный путь. Он будет использоваться как ввод для request.build_absolute_uri() для построения URL со схемой HTTP и именем хоста. Тема и тело письма создаются на основе очищенных данных из отправленной формы. Наконец, email отправляется по адресу указанному в поле to формы.

Когда представление готово, нужно добавить новый URL-шаблон. Откройте файл urls.py приложения blog и добавьте URL-шаблон post_share:

urlpatterns = [ 
    # ... 
    path('<int:post_id>/share/',
         views.post_share, name='post_share'), 
]

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

Что выведет этот код?
Что выведет этот код?
Какой ввод НЕ приведет к ошибке?
Какая из функций python делает вывод в консоль?
Какой будет результат выполнения этого кода?
Викиум