使用 Gmail 的 Django 错误报告

Posted

技术标签:

【中文标题】使用 Gmail 的 Django 错误报告【英文标题】:Django error reporting with Gmail 【发布时间】:2017-06-27 07:04:18 【问题描述】:

我正在尝试设置我的 Django 帐户以接收错误报告 (docs here)。

我已将ADMINS 添加到我的settings.py。然后,根据文档:

为了发送电子邮件,Django 需要一些设置告诉它如何 连接到您的邮件服务器。至少,你需要 指定 EMAIL_HOST 和可能的 EMAIL_HOST_USER 和 EMAIL_HOST_PASSWORD,但可能还需要其他设置 取决于您的邮件服务器的配置。咨询 Django 有关电子邮件相关设置的完整列表的设置文档。

但这是我迷路的时候。 我有一个企业 Gmail 帐户,这是我想在此处链接的帐户。 This post 解释得很精彩,

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'myemail@mydomain.com'
EMAIL_HOST_PASSWORD = 'mypassword'

但它说:

在 2016 年,Gmail 不再允许这样做。

显然,问题出在EMAIL_HOST_PASSWORD 设置中,它必须是特定密码,如this other post 中所述。

但是,很难相信 Gmail 以任何方式不允许这样做,尤其是对于您为服务付费的企业帐户。

不幸的是,我找到的所有相关信息都早于 2016 年,因此不再有用。

有没有办法将 Django 应用程序与 Gmail 连接起来?

【问题讨论】:

您是否为安全性较低的应用打开了访问权限? support.google.com/accounts/answer/6010255 是的。这一点在我遵循的解释中进行了描述,并且我能够做到。但是,我更愿意保留两步验证:This setting is not available for accounts with 2-Step Verification enabled. Such accounts require an application-specific password for less secure apps access. 那么使用应用专用密码有什么问题? 我无法得到它,正如this answer的cmets中所解释的那样 @J0ANNM 我认为没有其他选择。我知道在任何时候我想从 Django 使用我的谷歌应用程序帐户时,我总是必须启用不太安全的访问。 【参考方案1】:

我想提供截至 2021 年 8 月的更新。

我仅使用 Django 附带的库在商业 gmail 帐户上工作。

在settings.py中

EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'myname@mydomain.com'
EMAIL_HOST_PASSWORD = 'myappspecificpassword'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

对于密码,您需要为相关帐户生成应用专用密码。您可以访问此链接:https://security.google.com/settings/u/3/security/apppasswords。

注意:您必须为发送邮件的帐户启用 2 因素身份验证。这必须通过您发送邮件的帐户启用,而不是管理员帐户。

这样做,我可以在views.py的视图中使用这个sn-p发送电子邮件

        from django.core.mail import EmailMessage
        ...


        email = EmailMessage(
        'Hello',
        'Body goes here',
        'bob@example.com',
        ['user@mydomain.com'],
        ['bcc@example.com'],
        reply_to=['myuser@mydomain.com'],
        headers='Message-ID': 'foo',
        )
        
        email.send()

【讨论】:

【参考方案2】:

您可以使用 Gmail API 通过 Gmail 电子邮件地址发送授权电子邮件。一个好的起点是文档:https://developers.google.com/gmail/api/quickstart/python

我一直遇到这个问题,所以我在一篇博文中记录了如何使用 API:https://www.willcarh.art/blog/Automating-Emails-in-Python/

我最终构建了自己的 Python 实用程序来通过 Gmail API 发送电子邮件真是太痛苦了。这是我最初的原型:

import os
import sys
import pickle
import base64
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from email.mime.text import MIMEText

def get_gmail_api_instance():
    """
    Setup Gmail API instance
    """
    if not os.path.exists('token.pickle'):
        return None
    with open('token.pickle', 'rb') as token:
        creds = pickle.load(token)
    service = build('gmail', 'v1', credentials=creds)
    return service

def create_message(sender, to, subject, message_text):
    """
    Create a message for an email
        :sender: (str) the email address of the sender
        :to: (str) the email address of the receiver
        :subject: (str) the subject of the email
        :message_text: (str) the content of the email
    """
    message = MIMEText(message_text)
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject
    raw = base64.urlsafe_b64encode(message.as_bytes())
    raw = raw.decode()
    body = 'raw': raw
    return body

def send_email(service, user_id, message):
    """
    Send an email via Gmail API
        :service: (googleapiclient.discovery.Resource) authorized Gmail API service instance
        :user_id: (str) sender's email address, used for special "me" value (authenticated Gmail account)
        :message: (base64) message to be sent
    """
    try:
        message = (service.users().messages().send(userId=user_id, body=message).execute())
        return message
    except Exception as e:
        print("err: problem sending email")
        print(e)

def main():
    """
    Set up Gmail API instance, use it to send an email
      'sender' is the Gmail address that is authenticated by the Gmail API
      'receiver' is the receiver's email address
      'subject' is the subject of our email
      'message_text' is the content of the email
    """
    # draft our message
    sender = 'pythonista@gmail.com'
    receiver = 'receiver@gmail.com'
    subject = 'Just checking in!'
    message_text = "Hi! How's it going?"

    # authenticate with Gmail API
    service = get_gmail_api_instance()
    if service == None:
        print("err: no credentials .pickle file found")
        sys.exit(1)

    # create message structure
    message = create_message(sender, receiver, subject, message_text)

    # send email
    result = send_email(service, sender, message)
    if not result == None:
        print(f"Message sent successfully! Message id: result['id']")

if __name__ == '__main__':
    main()

然后,要让 Django 发送有关 404、500 等错误的电子邮件,请添加到相关的urls.py

from django.conf.urls import handler404, handler500
handler404 = projectname_views.error_404
handler500 = projectname_views.error_500

并在相关的views.py 中添加:

import send_gmail
from django.shortcuts import render

def error_500(request):
    # call email function
    send_gmail.main()
    response = render(request, '500_errror_template.html')
    response.status_code = 500
    return response

上面代码的 GitHub 要点:https://gist.github.com/wcarhart/b4f509c46ad1515a9954d356aaf10df1

【讨论】:

【参考方案3】:

最终对我有用的解决方法是为此目的创建一个新的 Gmail 帐户。这暂时有效,尽管我在其他地方读到的一些 cmets 说相反。

请注意,这个新帐户将没有两步验证,但安全性并不是一个大问题,因为该帐户将“仅”处理 Django 电子邮件。

【讨论】:

以上是关于使用 Gmail 的 Django 错误报告的主要内容,如果未能解决你的问题,请参考以下文章

使用自定义 send_email 报告 Django 错误

django InlineFormsets错误报告,其中formset错误列表为空

Django 发生错误时如何将用户信息添加到 Sentry 的报告中?

使用 Redis、Celery 设置 Django 以通过 Gmail 发送电子邮件

Django 错误报告电子邮件 - 自定义设置参数

uwsgi部署django项目—报内部错误