mirror of
https://github.com/zulip/zulip.git
synced 2025-11-17 20:41:46 +00:00
ScheduledJob was written for much more generality than it ended up being used for. Currently it is used by send_future_email, and nothing else. Tailoring the model to emails in particular will make it easier to do things like selectively clear emails when people unsubscribe from particular email types, or seamlessly handle using the same email on multiple realms.
73 lines
2.5 KiB
Python
Executable File
73 lines
2.5 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
"""
|
|
Deliver email messages that have been queued by various things
|
|
(at this time invitation reminders and day1/day2 followup emails).
|
|
|
|
This management command is run via supervisor. Do not run on multiple machines,
|
|
as you may encounter multiple sends in a specific race condition.
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
|
|
from django.conf import settings
|
|
from django.core.management.base import BaseCommand
|
|
from django.utils.timezone import now as timezone_now
|
|
from django.utils.html import format_html
|
|
|
|
from zerver.models import ScheduledEmail
|
|
from zerver.lib.context_managers import lockfile
|
|
from zerver.lib.send_email import send_email, EmailNotDeliveredException
|
|
|
|
import time
|
|
import logging
|
|
from datetime import datetime
|
|
from ujson import loads
|
|
from typing import Any, Dict
|
|
|
|
## Setup ##
|
|
log_format = "%(asctime)s: %(message)s"
|
|
logging.basicConfig(format=log_format)
|
|
|
|
formatter = logging.Formatter(log_format)
|
|
file_handler = logging.FileHandler(settings.EMAIL_DELIVERER_LOG_PATH)
|
|
file_handler.setFormatter(formatter)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
logger.setLevel(logging.DEBUG)
|
|
logger.addHandler(file_handler)
|
|
|
|
class Command(BaseCommand):
|
|
help = """Deliver emails queued by various parts of Zulip
|
|
(either for immediate sending or sending at a specified time).
|
|
|
|
Run this command under supervisor. This is for SMTP email delivery.
|
|
|
|
Usage: ./manage.py deliver_email
|
|
"""
|
|
|
|
def handle(self, *args, **options):
|
|
# type: (*Any, **Any) -> None
|
|
# TODO: this only acquires a lock on the system, not on the DB:
|
|
# be careful not to run this on multiple systems.
|
|
|
|
# In the meantime, we have an option to prevent this job from
|
|
# running on >1 machine
|
|
if settings.EMAIL_DELIVERER_DISABLED:
|
|
return
|
|
|
|
with lockfile("/tmp/zulip_email_deliver.lockfile"):
|
|
while True:
|
|
email_jobs_to_deliver = ScheduledEmail.objects.filter(scheduled_timestamp__lte=timezone_now())
|
|
if email_jobs_to_deliver:
|
|
for job in email_jobs_to_deliver:
|
|
try:
|
|
send_email(**loads(job.data))
|
|
job.delete()
|
|
except EmailNotDeliveredException:
|
|
logger.warn("%r not delivered" % (job,))
|
|
time.sleep(10)
|
|
else:
|
|
# Less load on the db during times of activity, and more responsiveness when the load is low
|
|
time.sleep(2)
|