【问题标题】:django 1.7.8 not sending emails with password resetdjango 1.7.8 不发送带有密码重置的电子邮件
【发布时间】:2015-07-31 22:19:15
【问题描述】:

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

)

根据要求,这里是密码重置表格:

{% 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/,并且没有发送任何电子邮件。

我的相关@​​987654328@变量:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'XXX@gmail.com'
EMAIL_HOST_PASSWORD = 'XXXXXX' 
EMAIL_PORT = 587

DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SERVER_EMAIL = EMAIL_HOST_USER

我知道电子邮件有效,因为我在django-registration-redux 的注册流程完美无缺。

有什么想法吗?

【问题讨论】:

  • 您能否向我们展示您负责发送电子邮件的视图示例?
  • @tanorix 正如你在上面的urls.py 中看到的那样,有内置的,所以你可以在这里看到它们:github.com/django/django/blob/master/django/contrib/auth/…
  • 尝试暂时切换到file backend(或控制台后端,如果你在你的开发环境中)——这应该有助于显示问题是在视图中还是在电子邮件配置中(我知道你说这些电子邮件在 django-registration-redux 中工作,但无论如何这可能值得一试)。
  • 你什么时候显示你的地址电子邮件?因为正如我们在您向我们展示的 url 中看到的那样,在第 154 行,该函数尝试发送电子邮件,因此在您的 urls.py 中,您必须在 ^accounts/password/reset/done/$
  • @Alasdair,只是尝试过,没有运气。似乎问题不在于尝试发送电子邮件,而在于甚至一开始就尝试过,这似乎没有发生

标签: python django email


【解决方案1】:

当您 POST 到 ^accounts/password/reset/$ 时,django.contrib.auth.views.password_reset 函数将运行。这将使用默认的django.contrib.auth.forms.PasswordResetForm 类来验证电子邮件。

您应该注意到,电子邮件只会发送给与提供的电子邮件匹配的活动用户,并且只有当他们有可用的密码时。

尝试在 Django 管理 shell 中使用以下功能:

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()

【讨论】:

  • 是的,这些断言毫无问题地成功了。在较新版本的 Djano 中,您需要 from django.contrib.auth.models import User 而不是 get_user_model
  • 感谢您提出密码重置电子邮件所需的条件 -- 我正在尝试编写密码重置工作流的测试,但不知道 has_usable_password 检查。
  • 是的,如果您使用 create_user 创建用户并且不设置密码,他们将不会重置。使用password = User.objects.make_random_password()
【解决方案2】:

您的templates 文件夹中有电子邮件模板吗?

registration/password_reset_email.html
registration/password_reset_subject.txt

【讨论】:

  • 是的,这些我都有。
【解决方案3】:

好的,很可能是表单清理方法失败了,而您没有捕获该错误。所以你只是得到重定向而不发送邮件,也不知道为什么。 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>

【讨论】:

    【解决方案4】:

    我肯定会检查垃圾邮件文件夹。因为有时某些电子邮件过滤器会非常严厉地处理带有链接的文本电子邮件。

    我建议使用(一些带有 IDE 的)python 调试器并在 pdb(python 调试器)的帮助下遍历 django.contrib.auth.form.PasswordResetForm.save 和 django.contrib.auth.views.password_reset 看看有什么作用不工作。

    【讨论】:

      【解决方案5】:

      我试图重现您的情况,但遇到了以下情况:

      1. 邮件只发送给活跃用户。与没有用户关联的电子邮件将不会收到任何电子邮件(显然)。
      2. 我在第 270 行为email = loader.render_to_string(email_template_name, c) 找到了错误表单的保存方法:

      NoReverseMatch 在 /accounts/password/reset/ 反向 'password_reset_confirm' 带有参数 '()' 和关键字参数 '{'token': '42h-4e68c02f920d69a82fbf', 'uidb64': b'Mg'}' 未找到。 0 尝试的模式:[]

      您的 urls.py 似乎不包含任何名为“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/'},),
      

      收件人:

      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。使用您在问题中所写的网址和视图。

      【讨论】:

        【解决方案6】:

        answer by domtes 为我解决了这个问题,但我想强调一下这个潜在的原因:

        如果您尝试重置的用户当前(在重置之前)密码无效,Django 将不会发送重置电子邮件!

        在我的情况下,我不小心覆盖了管理员中的密码字段(自定义用户模型 + LastPass),之后那个用户就不再重置了。

        【讨论】:

          【解决方案7】:

          对于 mac 用户,特别是如果您在正常的 Terminal 旁边有 iTerm,并且可能在 .bash_profile 中设置了环境变量之前,请在 ~/.zshrc 上再次设置它们(如果您使用 Django 项目运行iTerm):

          export EMAIL_USER='email@gmail.com'
          export EMAIL_PASS='password'
          

          重新加载文件~/.zshrcsource ~/.zshrc,或者干脆关闭并再次打开iTerm

          当然,以前,您在电子邮件设置中打开了不太安全的选项。

          【讨论】:

            猜你喜欢
            • 2013-12-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-08-13
            • 2020-09-26
            • 1970-01-01
            • 2015-11-26
            相关资源
            最近更新 更多