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_email
或 EmailMessage
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 发送电子邮件的主要内容,如果未能解决你的问题,请参考以下文章