使用 pyramid_mailer 和 apscheduler 发送预定的电子邮件
Send scheduled emails with pyramid_mailer and apscheduler
我试过让它工作,但一定有更好的方法,欢迎任何意见。
我正在尝试使用 pyramid_mailer(设置存储在 .ini 文件中)在我的 python 金字塔应用程序中发送预定的电子邮件,并使用 apscheduler 来设置计划。
我还使用 SQLAlchemyJobStore,因此如果应用程序重新启动,作业可以重新启动。
jobstores = {
'default': SQLAlchemyJobStore(url='mysql://localhost/lgmim')
}
scheduler = BackgroundScheduler(jobstores=jobstores)
@view_config(route_name='start_email_schedule')
def start_email_schedule(request):
# add the job and start the scheduler
scheduler.add_job(send_scheduled_email, 'interval', [request], weeks=1)
scheduler.start()
return HTTPOk()
def send_scheduled_email(request):
# compile message and recipients
# send mail
send_mail(request, subject, recipients, message)
def send_mail(request, subject, recipients, body):
mailer = request.registry['mailer']
message = Message(subject=subject,
recipients=recipients,
body=body)
mailer.send_immediately(message, fail_silently=False)
这是我所得到的,现在我收到一个错误,大概是因为它无法 pickle 请求。
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
第一次使用pyramid.threadlocal.get_current_registry().settings
使邮件程序正常工作,但此后出现错误。建议无论如何不要使用它。
我还能做什么?
通常,您不能 pickle request
对象,因为它包含对打开的套接字和其他活动对象等内容的引用。
这里有一些有用的模式
您在数据库中预生成电子邮件 ID,然后通过调度程序传递 ID(int,UUID)
您生成模板上下文(JSON dict),然后将其传递给调度程序并在 worker 中呈现模板
您在调度程序中执行所有数据库获取和相关操作,并且不传递任何参数
具体来说,如何在调度程序中生成人造 request
对象的问题可以这样解决:
from pyramid import scripting
from pyramid.paster import bootstrap
def make_standalone_request():
bootstrap_env = bootstrap("your-pyramid-config.ini")
app = bootstrap_env["app"]
pyramid_env = scripting.prepare(registry=bootstrap_env["registry"])
request = pyramid_env["request"]
# Note that request.url will be always dummy,
# so if your email refers to site URL, you need to
# resolve request.route_url() calls before calling the scheduler
# or read the URLs from settings
return request
Some more inspiration can be found here (disclaimer: I am the author).
我试过让它工作,但一定有更好的方法,欢迎任何意见。
我正在尝试使用 pyramid_mailer(设置存储在 .ini 文件中)在我的 python 金字塔应用程序中发送预定的电子邮件,并使用 apscheduler 来设置计划。
我还使用 SQLAlchemyJobStore,因此如果应用程序重新启动,作业可以重新启动。
jobstores = {
'default': SQLAlchemyJobStore(url='mysql://localhost/lgmim')
}
scheduler = BackgroundScheduler(jobstores=jobstores)
@view_config(route_name='start_email_schedule')
def start_email_schedule(request):
# add the job and start the scheduler
scheduler.add_job(send_scheduled_email, 'interval', [request], weeks=1)
scheduler.start()
return HTTPOk()
def send_scheduled_email(request):
# compile message and recipients
# send mail
send_mail(request, subject, recipients, message)
def send_mail(request, subject, recipients, body):
mailer = request.registry['mailer']
message = Message(subject=subject,
recipients=recipients,
body=body)
mailer.send_immediately(message, fail_silently=False)
这是我所得到的,现在我收到一个错误,大概是因为它无法 pickle 请求。
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
第一次使用pyramid.threadlocal.get_current_registry().settings
使邮件程序正常工作,但此后出现错误。建议无论如何不要使用它。
我还能做什么?
通常,您不能 pickle request
对象,因为它包含对打开的套接字和其他活动对象等内容的引用。
这里有一些有用的模式
您在数据库中预生成电子邮件 ID,然后通过调度程序传递 ID(int,UUID)
您生成模板上下文(JSON dict),然后将其传递给调度程序并在 worker 中呈现模板
您在调度程序中执行所有数据库获取和相关操作,并且不传递任何参数
具体来说,如何在调度程序中生成人造 request
对象的问题可以这样解决:
from pyramid import scripting
from pyramid.paster import bootstrap
def make_standalone_request():
bootstrap_env = bootstrap("your-pyramid-config.ini")
app = bootstrap_env["app"]
pyramid_env = scripting.prepare(registry=bootstrap_env["registry"])
request = pyramid_env["request"]
# Note that request.url will be always dummy,
# so if your email refers to site URL, you need to
# resolve request.route_url() calls before calling the scheduler
# or read the URLs from settings
return request
Some more inspiration can be found here (disclaimer: I am the author).