使用 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).