Django 1.7.8 не отправляет письма с паролем reset

Соответствующая часть urls.py для проекта:

from django.conf.urls import include, url, patterns
urlpatterns = patterns('',

  # other ones ...

  url(r'^accounts/password/reset/$', 
  'django.contrib.auth.views.password_reset',
 {'post_reset_redirect' : '/accounts/password/reset/done/'}),

  url(r'^accounts/password/reset/done/$', 
  'django.contrib.auth.views.password_reset_done'),

  url(r'^accounts/password/reset/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', 
  'django.contrib.auth.views.password_reset_confirm',
 {'post_reset_redirect' : '/accounts/password/done/'}),

  url(r'^accounts/password/done/$', 
  'django.contrib.auth.views.password_reset_complete'),

)

И по запросу здесь введите пароль reset:

{% extends "site_base.html" %}

{% block title %}Reset Password{% endblock %}

{% block content %}
<p>Please specify your email address to receive instructions for resetting it.</p>

<form action="" method="post">
    <div style="display:none">
        <input type="hidden" value="{{ csrf_token }}" name="csrfmiddlewaretoken">
    </div>
     {{ form.email.errors }}
    <p><label for="id_email">E-mail address:</label> {{ form.email }} <input type="submit" value="Reset password" /></p>
</form>
{% endblock %}

Но всякий раз, когда я перехожу на страницу /accounts/password/reset/ и заполняю электронное письмо, и нажимаю кнопку "Ввести", страница сразу перенаправляется на /accounts/password/reset/done/, и никакое электронное письмо не отправляется.

Мои релевантные переменные settings.py:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'XXXXXX' 
EMAIL_PORT = 587

DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SERVER_EMAIL = EMAIL_HOST_USER

И я знаю, что работает электронная почта, потому что мой процесс регистрации с django-registration-redux работает безупречно.

Любые идеи?

Ответы

Ответ 1

Я попытался воссоздать вашу ситуацию, и я столкнулся со следующими сценариями:

  • Почта отправляется только активным пользователям. Email, связанный без пользователя, не получит никакой электронной почты (очевидно).
  • Я получил способ сохранения формы ошибки в строке 270 для email = loader.render_to_string(email_template_name, c):

NoReverseMatch at/accounts/password/ reset/Реверс для 'password_reset_confirm' с аргументами '()' и ключевыми словами '{' token ':' 42h-4e68c02f920d69a82fbf ',' uidb64 ': b'Mg'} 'не найден. 0 образец (ы): []

Кажется, что ваш urls.py не содержит URL-адрес 'password_reset_confirm'. Поэтому вы должны изменить свой URL:

url(r'^accounts/password/reset/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
  'django.contrib.auth.views.password_reset_confirm',
 {'post_reset_redirect': '/accounts/password/done/'},),

To:

url(r'^accounts/password/reset/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
  'django.contrib.auth.views.password_reset_confirm',
 {'post_reset_redirect': '/accounts/password/done/'}, name='password_reset_confirm'),

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

PS: Я тестировал django 1.7.8, а шаблоны: Python34\Lib\site-packages\django\contrib\admin\templates\registration. Urls и views используются, как вы писали в вопросе.

Ответ 2

Когда вы отправляете POST на ^accounts/password/reset/$, запускается функция django.contrib.auth.views.password_reset. Для проверки подлинности этого сообщения будет использоваться класс django.contrib.auth.forms.PasswordResetForm.

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

Попробуйте использовать следующую функцию с оболочкой управления Django:

from django.contrib.auth.models import get_user_model

def check_password_reset_cond(email):
     for u in get_user_model().objects.filter(email__iexact=email):
         assert u.is_active
         assert u.has_usable_password()

Ответ 3

У вас есть шаблоны электронной почты в папке templates?

registration/password_reset_email.html
registration/password_reset_subject.txt

Ответ 4

ОК, скорее всего, что-то не получается в чистом методе форм, и вы не поймаете эту ошибку. Поэтому вы просто получаете перенаправление, не отправляя почту, и не знаете, почему. Любая ошибка проверки, созданная в clean(), будет отображаться в non_field_errors. Вам нужно добавить {{form.non_field_errors}} на свою страницу, чтобы увидеть их. Попробуйте следующее:

<form method="post">{% csrf_token %}
    {{{form.non_field_errors}}
    {{ form.email.errors }}
<p><label for="id_email">E-mail address:</label> {{ form.email }} <input    type="submit" value="Reset password" /></p>
</form>

Ответ 5

Я бы точно установил папку со спамом. Потому что иногда некоторые фильтры электронной почты обрабатывают текстовые сообщения со ссылками довольно жестко.

Я рекомендую взять (некоторый IDE с) отладчик python и с помощью pdb (отладчик python) пройти через django.contrib.auth.form.PasswordResetForm.save и django.contrib.auth.views.password_reset, чтобы узнать, что делает не работает.

Ответ 6

Ответ domtes разрешил это для меня, но я хотел обратить особое внимание на эту потенциальную причину:

Если пользователь, которому вы пытаетесь выполнить reset, в настоящее время (до reset) имеет недопустимый пароль, Django просто молчает отправить reset email!

В моем случае я случайно перезаписал поле пароля в админке (пользовательская модель + LastPass), и после этого один пользователь просто не сделал reset больше.