Django 的神秘问题 + uWSGI +发送电子邮件

发布于 2024-12-21 15:47:28 字数 4026 浏览 3 评论 0原文

经过大约 1.5 小时的艰苦调试后,我在这里给您写信。


首先,这些是感兴趣的文件:

/project/app/utils.py

from django.core.mail import EmailMultiAlternatives
import threading

class EmailThread(threading.Thread):
    def __init__(self, subject, body, from_email, recipient_list, fail_silently, html):
        self.subject = subject
        self.body = body
        self.recipient_list = recipient_list
        self.from_email = from_email
        self.fail_silently = fail_silently
        self.html = html
        threading.Thread.__init__(self)

    def run(self):
        msg = EmailMultiAlternatives(self.subject, self.body, self.from_email, self.recipient_list)
        if self.html:
            msg.attach_alternative(self.html, "text/html")
        print "sending message"
        msg.send(self.fail_silently)
        print "sent."

def send_html_mail(subject, body, from_email, recipient_list, fail_silently=False, html=None, *args, **kwargs):
    EmailThread(subject, body, from_email, [recipient_list], fail_silently, html).start()

/project/app/views.py

[...]
import utils

def my_view(request):
    [...]
    utils.send_html_mail('subject', '<h1>cool things.</h1>', 'Test <[email protected]>', '[email protected]', html='<h1>cool things.</h1>')

/project/app/settings。 py

# I use Amazon SES

[...]
EMAIL_BACKEND = 'backends.smtp.SSLEmailBackend'
EMAIL_HOST = 'amazon-server'
EMAIL_PORT = 465
EMAIL_HOST_USER = 'user'
EMAIL_HOST_PASSWORD = 'pass'
EMAIL_USE_TLS = True
[...]

/project/backends/smtp.py

# taken from https://gist.github.com/1486891

import smtplib

from django.core.mail.utils import DNS_NAME
from django.core.mail.backends.smtp import EmailBackend

class SSLEmailBackend(EmailBackend):
    def open(self):
        if self.connection:
            return False
        try:
            self.connection = smtplib.SMTP_SSL(self.host, self.port,
                                           local_hostname=DNS_NAME.get_fqdn())
            if self.username and self.password:
                self.connection.login(self.username, self.password)
            return True
        except:
            if not self.fail_silently:
                raise

好的,现在的问题是:

在 localhost 中:

  • 从视图发送电子邮件works
  • 从 django shell 发送电子邮件工作

在我的服务器上部署应用程序:

  • 从视图发送电子邮件不起作用
  • 从django shell发送电子邮件有效

localhost中的Django shell输出>:

# utils.send_html_mail('subject', '<h1>cool things.</h1>', 'Test <[email protected]>', '[email protected]', html='<h1>cool things.</h1>')
sending email
sent.

部署应用中的 Django shell 输出:

# utils.send_html_mail('subject', '<h1>cool things.</h1>', 'Test <[email protected]>', '[email protected]', html='<h1>cool things.</h1>')
sending email

相同的代码,相同的提交。问题可能出在 print "sent." 之前的方法 msg.send(self.fail_silently) 中,但它是什么?我没有想法。

你呢?

I'm here to write you after about 1.5 hour of hard debugging.

First of all, these are the interested files:

/project/app/utils.py

from django.core.mail import EmailMultiAlternatives
import threading

class EmailThread(threading.Thread):
    def __init__(self, subject, body, from_email, recipient_list, fail_silently, html):
        self.subject = subject
        self.body = body
        self.recipient_list = recipient_list
        self.from_email = from_email
        self.fail_silently = fail_silently
        self.html = html
        threading.Thread.__init__(self)

    def run(self):
        msg = EmailMultiAlternatives(self.subject, self.body, self.from_email, self.recipient_list)
        if self.html:
            msg.attach_alternative(self.html, "text/html")
        print "sending message"
        msg.send(self.fail_silently)
        print "sent."

def send_html_mail(subject, body, from_email, recipient_list, fail_silently=False, html=None, *args, **kwargs):
    EmailThread(subject, body, from_email, [recipient_list], fail_silently, html).start()

/project/app/views.py

[...]
import utils

def my_view(request):
    [...]
    utils.send_html_mail('subject', '<h1>cool things.</h1>', 'Test <[email protected]>', '[email protected]', html='<h1>cool things.</h1>')

/project/app/settings.py

# I use Amazon SES

[...]
EMAIL_BACKEND = 'backends.smtp.SSLEmailBackend'
EMAIL_HOST = 'amazon-server'
EMAIL_PORT = 465
EMAIL_HOST_USER = 'user'
EMAIL_HOST_PASSWORD = 'pass'
EMAIL_USE_TLS = True
[...]

/project/backends/smtp.py

# taken from https://gist.github.com/1486891

import smtplib

from django.core.mail.utils import DNS_NAME
from django.core.mail.backends.smtp import EmailBackend

class SSLEmailBackend(EmailBackend):
    def open(self):
        if self.connection:
            return False
        try:
            self.connection = smtplib.SMTP_SSL(self.host, self.port,
                                           local_hostname=DNS_NAME.get_fqdn())
            if self.username and self.password:
                self.connection.login(self.username, self.password)
            return True
        except:
            if not self.fail_silently:
                raise

Ok, now the problem:

in localhost:

  • sending the email from the view works
  • sending the email from the django shell works

in the deploy app on my server:

  • sending the email from the view DOESN'T WORKS
  • sending the email from the django shell works

Django shell output in localhost:

# utils.send_html_mail('subject', '<h1>cool things.</h1>', 'Test <[email protected]>', '[email protected]', html='<h1>cool things.</h1>')
sending email
sent.

Django shell output in deploy app:

# utils.send_html_mail('subject', '<h1>cool things.</h1>', 'Test <[email protected]>', '[email protected]', html='<h1>cool things.</h1>')
sending email

Same code, same commit. The problem is in the method msg.send(self.fail_silently) just before the print "sent." probably, but what is it? I don't have ideas.

And you?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

筱果果 2024-12-28 15:47:28

您是否使用 --enable-threads 在 uWSGI 中启用了线程?

have you enabled threads in uWSGI with --enable-threads ?

烟火散人牵绊 2024-12-28 15:47:28

由于 threading 存在 uWSGI 的激活问题,您可以尝试将其添加到应用程序的 uwsgi 配置中:

lazy = true

这样您的代码将在子进程分叉后加载。

As the threading having activating issue with uWSGI you can try to add this to your app's uwsgi configuration:

lazy = true

So your code will be loaded after child workers forked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文