Commit bfec4e8d by benjaoming

rename command, cleanup code, add logging

parent 15b02ae1
......@@ -4,45 +4,65 @@ import time
from datetime import datetime
from optparse import make_option
from django_notify import settings as notify_settings
from django.contrib.sites.models import Site
from django.core import mail
from django.core.management.base import BaseCommand, CommandError
from django.core.management.base import BaseCommand
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django_notify import models
from django_notify.settings import INTERVALS, DEFAULT_EMAIL,NOTIFY_SLEEP_TIME,EMAIL_SUBJECT
import smtplib
import logging
logger = logging.getLogger('django_notify')
if not logger.handlers:
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.INFO)
class Command(BaseCommand):
help = 'Sends Notification emails to subscribed users taking into account the subscription interval'
help = 'Sends notification emails to subscribed users taking into account the subscription interval' #@ReservedAssignment
option_list = BaseCommand.option_list + (
make_option('--daemon','-d',
action='store_true',
dest='daemon',
default=True,
default=False,
help='Go to daemon mode and exit'),
)
def _send_user_notifications(self,context,connection):
subject = _(EMAIL_SUBJECT)
message = render_to_string('emails/notification_email_message.txt',
context)
email = mail.EmailMessage(subject, message, DEFAULT_EMAIL,
[context['user'].email], connection=connection)
def _send_user_notifications(self, context, connection):
subject = _(notify_settings.EMAIL_SUBJECT)
message = render_to_string(
'emails/notification_email_message.txt',
context
)
email = mail.EmailMessage(
subject, message, notify_settings.EMAIL_SENDER,
[context['user'].email], connection=connection
)
email.send()
def handle(self, *args, **options):
logger.info("Starting django_notify e-mail dispatcher")
if not notify_settings.SEND_EMAILS:
print "E-mails disabled - quitting."
sys.exit()
daemon = options['daemon']
# Run as daemon, ie. fork the process
if daemon:
logger.info("Daemon mode enabled, forking")
try:
fpid = os.fork()
if fpid > 0:
# Running as daemon now. PID is fpid
logger.info("PID: %s" % str(fpid))
pid_file = file('/tmp/daemon-example.pid', "w")
pid_file.write(str(fpid))
pid_file.close()
......@@ -50,7 +70,14 @@ class Command(BaseCommand):
except OSError, e:
sys.stderr.write("fork failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
try:
self.send_loop()
except KeyboardInterrupt:
print "\nQuitting..."
def send_loop(self):
# This could be /improved by looking up the last notified person
last_sent = None
context = {'user': None,
......@@ -59,12 +86,22 @@ class Command(BaseCommand):
'site': Site.objects.get_current()}
#create a connection to smtp server for reuse
connection = mail.get_connection()
try:
connection = mail.get_connection()
except:
logger.error("Could get a mail connection")
raise
while True:
connection.open()
try:
connection.open()
except:
logger.error("Could not use e-mail connection")
raise
started_sending_at = datetime.now()
logger.info("Starting send loop at %s" % str(started_sending_at))
if last_sent:
settings = models.Settings.objects.filter(
interval__lte=((started_sending_at-last_sent).seconds // 60) // 60
......@@ -76,15 +113,30 @@ class Command(BaseCommand):
context['user'] = setting.user
context['notifications']= []
#get the index of the tuple corresponding to the interval and get the string name
context['digest'] = INTERVALS[[y[0] for y in INTERVALS].index(setting.interval)][1]
for subscription in setting.subscription_set.filter(send_emails=True,latest__is_emailed=False):
context['digest'] = notify_settings.INTERVALS[[y[0] for y in notify_settings.INTERVALS].index(setting.interval)][1]
for subscription in setting.subscription_set.filter(
send_emails=True,
latest__is_emailed=False
):
context['notifications'].append(subscription.latest)
subscription.latest.is_emailed=True
subscription.latest.save()
if len(context['notifications']) > 0:
self._send_user_notifications(context,connection)
try:
self._send_user_notifications(context, connection)
for n in context['notifications']:
n.is_emailed=True
n.save()
except smtplib.SMTPException:
# TODO: Only quit on certain errors, retry on others.
logger.error("You have an error with your SMTP server connection, quitting.")
raise
connection.close()
last_sent = datetime.now()
elapsed_minutes = ((last_sent - started_sending_at).seconds) // 60
time.sleep(max((min(INTERVALS)[0]*60-elapsed_minutes)*60,NOTIFY_SLEEP_TIME))
elapsed_seconds = ((last_sent - started_sending_at).seconds)
time.sleep(
max(
(min(notify_settings.INTERVALS)[0] - elapsed_seconds) * 60,
notify_settings.NOTIFY_SLEEP_TIME,
0
)
)
......@@ -5,43 +5,50 @@ _ = lambda x: x
DB_TABLE_PREFIX = 'notify'
# You need to switch this setting on, otherwise nothing will happen :)
ENABLED = getattr(django_settings, "NOTIFY_ENABLED", True)
ENABLED = getattr(django_settings, 'NOTIFY_ENABLED', True)
# Enable django-admin registration
ENABLE_ADMIN = getattr(django_settings, "NOTIFY_ENABLE_ADMIN", False)
ENABLE_ADMIN = getattr(django_settings, 'NOTIFY_ENABLE_ADMIN', False)
##################################
# PLANNED CONFIGURATION SETTINGS #
##################################
# Email notifications won't get sent unless you run
# python manage.py notifymail
SEND_EMAILS = getattr(django_settings, 'NOTIFY_SEND_EMAILS', True)
# Email notifications are just optional... if you don't have access
# to a proper SMTP server, just leave it off...
SEND_EMAILS = getattr(django_settings, "NOTIFY_SEND_EMAILS", False)
EMAIL_SUBJECT = getattr(django_settings,
'NOTIFY_EMAIL_SUBJECT', _("You have new notifications"))
EMAIL_SUBJECT = "Notifications"
EMAIL_SENDER = getattr(django_settings,
'NOTIFY_EMAIL_SENDER', "notifications@example.com")
DEFAULT_EMAIL = 'notifications@example.com'
#NOTIFY_SLEEP_TIME must be greater than 0 to allow for Garbage Collection
NOTIFY_SLEEP_TIME = 10
# Seconds to sleep between each database poll
# (leave high unless you really want to send extremely real time
# notifications)
NOTIFY_SLEEP_TIME = 120
# You can always make up more numbers... they simply identify which notifications
# to send when invoking the script, and the number indicates how many hours
# to minimum pass between each notification.
# Actual notifications are sent with a management script and a cron job!
INSTANTLY = 0
DAILY = 24-1 # Subtract 1, because the job finishes less than 24h before the next...
WEEKLY = 7*24-1
DAILY = (24 - 1) * 60 # Subtract 1, because the job finishes less than 24h before the next...
WEEKLY = 7 * (24 - 1) * 60
INTERVALS = getattr(django_settings, "NOTIFY_INTERVALS",
[(INSTANTLY, _(u'instant')),
(DAILY, _(u'daily')),
(WEEKLY, _(u'weekly'))])
# List of intervals available. In minutes
INTERVALS = getattr(django_settings, 'NOTIFY_INTERVALS',
[(INSTANTLY, _(u'instant')),
(DAILY, _(u'daily')),
(WEEKLY, _(u'weekly'))]
)
INTERVALS_DEFAULT = INSTANTLY
####################
# PLANNED SETTINGS #
####################
# Minimum logging and digital garbage! Don't save too much crap!
# After how many days should viewed notifications be deleted?
AUTO_DELETE = getattr(django_settings, "NOTIFY_AUTO_DELETE", 120)
AUTO_DELETE = getattr(django_settings, 'NOTIFY_AUTO_DELETE', 120)
# After how many days should all types of notifications be deleted?
AUTO_DELETE_ALL = getattr(django_settings, "NOTIFY_AUTO_DELETE_ALL", 120)
AUTO_DELETE_ALL = getattr(django_settings, 'NOTIFY_AUTO_DELETE_ALL', 120)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment