【问题标题】:django - persisting an email to database to be able to send it later?django - 将电子邮件保存到数据库以便以后发送?
【发布时间】:2016-06-17 21:34:53
【问题描述】:

在我的 django 项目中,我想在数据库中存储一封电子邮件,以便以后能够检索并发送它。我正在为向许多用户发送电子邮件实现一个节流机制。

我认为这就像存储“收件人、发件人、主题、正文”一样简单,但后来我意识到有附件、多部分电子邮件等,至少有两个类 EmailMessageEmailMultiAlternatives...变量和选项太多!

我想存储使用message() 方法获得的原始电子邮件,但不知道如何构造回电子邮件。也尝试了pickle,但得到了can't pickle lock objects

有什么想法吗?

【问题讨论】:

  • 我认为这是使用 django-mailer 实现节流的建议。然而,问题本身是非常不同的。
  • 这听起来像是 celery 的工作,但您仍然需要一种方法来序列化消息,除非您在更高级别进行序列化。
  • 我刚刚尝试腌制带有附件的 EmailMessage 并且有效。
  • (啊哈,我尝试在没有 Django 配置的情况下对其进行酸洗!)

标签: python django email django-email


【解决方案1】:

我将根据您的 can't pickle lock objects 消息进行猜测,您可能正在尝试使用包含默认 SMTP connection 的对象 pickle

尝试不使用它 - 通过源代码查找它是具有 self._locksmtp 模块。将connection=None 传递给消息的构造函数。

在 Django 1.9 上,这对我有用(Python2):

from django.core.mail import EmailMessage
from django.core.mail import EmailMultiAlternatives
import pickle

email = EmailMessage(
    'Hello',
    'Body goes here',
    'from@example.com',
    ['to1@example.com', 'to2@example.com'],
    ['bcc@example.com'],
    reply_to=['another@example.com'],
    headers={'Message-ID': 'foo'},
    connection=None,
)

email.attach("foo", [l for l in open(__file__)], 'text')

print len(pickle.dumps(email))

subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
text_content = 'This is an important message.'
html_content = '<p>This is an <strong>important</strong> message.</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, [to], connection=None)
msg.attach_alternative(html_content, "text/html")

print len(pickle.dumps(msg))

根据messages.py 中的Django 代码,稍后当您调用send() 时,如果EmailMessage.connectionNone,它将尝试使用django.core.mail 中的get_connection() 来获取您的默认连接。

....或者,如果你想使用json,这也适用于connection=None

import json                                                            
print json.dumps(msg.__dict__)                                         
print json.dumps(email.__dict__)

这意味着您可以相当容易地编写JSONEncoderJSONDecoder 来序列化/反序列化您的对象,基本上使用对象的__dict__

关于 JSON 的更多信息:

如上所示,编码__dict__ 使编码变得容易。你可以做msg.__dict__ = json.load(...),但困难的是必须在更改其值之前创建EmailMessage 对象。因此,您可以使用具有虚拟值的 EmailMessage 初始化 msg,然后分配 __dict__,或解码 JSON 并通过传递存储在JSON 到构造函数。不过,这需要您了解内部情况。

我会选择pickle,尽管存在安全隐患。

This SO question 还涵盖了其他一些替代方案。

【讨论】:

  • 如果我不是构建电子邮件的人,我仍然可以将连接设置为无,对吗?会试试看。谢谢!!!
  • 啊,你在下游?是的,您可以通过 msg.connection = None 取消设置。
  • 是的,我正在编写一个自定义电子邮件后端,用于存储电子邮件并稍后发送。谢谢!它有效:D
  • 嘿,您将如何使用 json 加载对象?我遇到了以下错误stackoverflow.com/questions/556269/…
  • @MartinMassera 你正在用二进制读写? "wb"?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
  • 1970-01-01
  • 2011-05-19
相关资源
最近更新 更多