EmailBackend 用于在 Django 中通过多个 SMTP 发送电子邮件

Posted

技术标签:

【中文标题】EmailBackend 用于在 Django 中通过多个 SMTP 发送电子邮件【英文标题】:EmailBackend for sending email through multiple SMTP in Django 【发布时间】:2012-11-15 10:40:50 【问题描述】:

使用标准设置很好地解释了让 Django 发送电子邮件here,如下所示。

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = "mail.mysmtpserver.somewhere"
#EMAIL_PORT
EMAIL_HOST_USER = "my@login"
EMAIL_HOST_PASSWORD = "mypassword"
#EMAIL_USE_TLS = True

然后使用django.core.mail.EmailMessage发送。

但是,如果您运行多个站点并且需要每个站点通过它们自己的 SMTP 服务器发送电子邮件(或者只是在同一个 SMTP 服务器中的不同登录名),该怎么办?

搜索这样的 EmailBackend 或使用当前后端执行此操作的方法没有产生任何令人满意的结果。

【问题讨论】:

【参考方案1】:

如果您想覆盖提供的设置,您可以创建自己的连接并将其提供给 send_emailEmailMessage

from django.core.mail import get_connection, send_mail
from django.core.mail.message import EmailMessage
# TODO: Insert clever settings mechanism
my_host = ''
my_port = 587
my_username = ''
my_password = ''
my_use_tls = True
connection = get_connection(host=my_host, 
                            port=my_port, 
                            username=my_username, 
                            password=my_password, 
                            use_tls=my_use_tls) 

send_mail('diditwork?', 'test message', 'from_email', ['to'], connection=connection)
# or
EmailMessage('diditwork?', 'test message', 'from_email', ['to'], connection=connection).send(fail_silently=False)

更新:确保在使用后关闭连接,@michel.iamit 答案指向显示连接已缓存以供 smpt 的代码。 @dhackner 回答展示了如何使用 with 语句自动关闭连接。

【讨论】:

我在使用这个解决方案时发现的东西是 Celery/Kombu cant pickle the EmailMessage 当你传递一个连接对象时,所以我认为这个方法在为将来安排电子邮件时可能不起作用交货 您可能永远不应该尝试腌制“连接”,因为它可能在未来的任务中不可用。如果只是将数据传递给未来的任务,并且在任务执行时构造 EmailMessage,它应该可以工作......【参考方案2】:

我会稍微修改 Daniel Backman 的答案,以使用文档中的上下文管理器。它会自己处理 open() 和 close() 调用。

from django.core.mail import get_connection, send_mail
from django.core.mail.message import EmailMessage

with get_connection(
    host=my_host, 
    port=my_port, 
    username=my_username, 
    password=my_password, 
    use_tls=my_use_tls
) as connection:
    EmailMessage(subject1, body1, from1, [to1],
                 connection=connection).send()

https://docs.djangoproject.com/en/dev/topics/email/#email-backends

【讨论】:

确实是一个更优雅的解决方案,只是一个说明,它仅在当前的django开发版本(> 1.7)中可用 如果您使用的是django 我想我找到了。 connection.close()。我应该猜到了。 :) 参数应该是use_tls 而不是@paketep 指出的user_tls【参考方案3】:

对不起,不能直接评论其余的答案,没有足够的代表。

只有一个补充:

connection = get_connection(host=my_host, 
                                port=my_port, 
                                username=my_username, 
                                password=my_password, 
                                user_tls=my_use_tls)

应该是

connection = get_connection(host=my_host, 
                                port=my_port, 
                                username=my_username, 
                                password=my_password, 
                                use_tls=my_use_tls)

只有在您不使用 TLS 时才会出现问题(您应该这样做),因为它默认为 True。

【讨论】:

@Manish,是的! “user_tls”与“use_tls” @RajkumarRajendran:好的。无论如何,您可能刚刚提到了那个特定的参数。 ;) @ManishMunikar 这不是我的答案。我回复了你的评论;)【参考方案4】:

看看 django 的电子邮件后端并创建一个自定义的可能是一个想法。

这里是代码:https://github.com/django/django/blob/master/django/core/mail/backends/smtp.py

这个例子展示了如何定制一个(这个使用 SMTP_SSL 而不是 SMTP):

https://gist.github.com/jsummerfield/1486891

我分叉了一个,将两者结合起来(这样我就可以将一个后端用于具有不同邮件设置的不同站点):

https://gist.github.com/iamit/5415771

不确定这是否可行,但如您所见,如果已经存在连接,则上述所有代码都会在打开连接时返回... 所以也许你的解决方案已经开始了......不要这样做,关闭打开的连接并使用不同的设置重新打开......(不确定这是否有效)。

【讨论】:

【参考方案5】:

为每个站点使用不同的配置。

一种方法是,除了您的settings.py 之外,每个站点还有一个settings_SITENAME.py。 这些文件将具有自定义邮件服务器设置。 每个站点都有settings_local.py 是指向它自己的自定义设置文件的符号链接

然后把这节放在settings.py的底部:

try:                                                                                                                                                                            
    from settings_local import *                                                                                                                                                
except ImportError:                                                                                                                                                             
    pass  

现在您拥有每个站点的自定义设置

【讨论】:

用一个设置文件有什么办法吗?我需要一个 Django 实例来使用多个 SMTP 服务器进行发送。 不要使用 django 电子邮件后端 - 使用较低级别的 python 库 - docs.python.org/2/library/email-examples.html 请不要,大声笑。如果 settings_local 需要修改现有设置怎么办? @CloudArtisans 创建一个类似 send_email 的函数,但从您的自定义电子邮件设置中提取,而不是从 django 硬编码的那些中提取。如果你有很多,你可以在字典中给它们起别名(就像 django 如何处理数据库一样)并将别名传递给你的 send_mail 函数。您唯一不能这样做的是更改 django 默认发送的电子邮件的凭据(如果 django 允许,可能需要为此进行monkeypatch 或添加自定义邮件后端)。

以上是关于EmailBackend 用于在 Django 中通过多个 SMTP 发送电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

在 django 中发送(发件人)邮件配置

使用django进行发送 邮件

46)django-发送邮件

django发邮件

django-发送文件

使用在 django 的 cpanel 上创建的电子邮件