Python/Django: 后台发送电子邮件

19

假设有一个用户在网站上执行了某个操作并通知管理员。 假设需要通知20名管理员。使用Django发送电子邮件的常规方法,用户必须等待所有电子邮件发送完成才能继续。

如何在单独的进程中发送所有电子邮件以便用户无需等待?这是否可能?


1
另一种(简单)解决方案可能是发送电子邮件到 Gmail(或其他)地址,然后使用规则或其他方式将其发送给所有管理员。 - Josh Hunt
1
发送到 Gmail 地址并不是一个好的解决方案。这会导致很多其他问题,例如在管理员更改时保持 Gmail 地址同步。Gmail 也可能出现不可预测的缓慢和/或高延迟甚至宕机,这将给用户带来很多意外的错误和缓慢。 - andreaspelme
3个回答

25

使用 celery 作为任务队列,并使用 django-celery-email,它是一个Django邮件后端,将电子邮件发送分派给一个celery任务。


我可以问一件事吗?如果我理解正确的话,我不需要更改我的应用程序代码来实现celery,除了我的settings.py文件。是这样吗? - nemesisdesign
3
只要您使用django.core.mail API,就不需要更改代码。备用电子邮件后端负责celery集成。但是,您可以(轻松地)编写其他任意celery任务以在后台执行,这非常方便。 - andreaspelme
我遇到了 kombu 中的 OperationalError: [Errno 111] Connection refused 错误。 - Paul R

7

5
如果我们只是要一次发送20封邮件,使用线程可能是一个可行的解决方案。对于耗时的后台任务,请使用Celery。
以下是使用线程的示例:
# This Python file uses the following encoding: utf-8

#threading
from threading import Thread

...

class afegeixThread(Thread):
    
    def __init__ (self,usuari, parameter=None):
        Thread.__init__(self)
        self.parameter = parameter
        ...
      
    def run(self):        
        errors = []
        try:
             if self.paramenter:
                   ....
        except Exception, e:                
             ...
...

n = afegeixThread( 'p1' )
n.start()

3
这是可能的,但工作仍然在Web服务器进程中完成,这对于后台任务来说并不理想。如果您有能力,应该设置一个合适的任务队列,并尽可能卸载Web进程。 - andreaspelme
1
嗨Andrea,你说的是真的。在一个有4个处理器的机器上,其中一个处理器会一直保持100%的使用率,直到任务结束。在小型网站中,线程可能是一种解决方案,但在大型网站中则不行。但是,你如何排队执行密集的Django任务(在模型中进行了许多操作)? - dani herrera
我不确定您的确切问题,但是celery是用于处理异步工作负载的,并且可以在Web进程之外构建,而且非常容易和直接上手,详情请参见celery文档。如果可能的话,将繁重的工作拆分为较小的工作通常是一种好的做法。然后可以在多台机器上运行Celery并并行消耗任务,使其非常容易扩展和处理繁重的工作!例如,这可以应用于视频上传、图像调整大小、发送电子邮件、生成PDF或其他类似的繁重工作! - andreaspelme
是的,celerity肯定是最优雅的解决方案。但是,我们现在讨论的是发送20封电子邮件。 - dani herrera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接