class Migration(migrations.Migration): dependencies = [ ('dbmail', '0013_auto_20160923_2201'), ] operations = [ migrations.AlterField( model_name='maillog', name='backend', field=models.CharField(choices=SORTED_BACKEND_CHOICES, db_index=True, default=b'mail', editable=False, max_length=25, verbose_name='Backend'), ), migrations.AlterField( model_name='mailsubscription', name='address', field=models.CharField(db_index=True, help_text='Must be phone number/email/token', max_length=350, verbose_name='Address'), ), migrations.AlterField( model_name='mailsubscription', name='backend', field=models.CharField(choices=BACKENDS_MODEL_CHOICES, default=BACKEND.get('mail'), max_length=50, verbose_name='Backend'), ), migrations.AlterField( model_name='mailsubscription', name='data', field=SubscriptionDataField(blank=True, default=dict, null=True), ), migrations.AlterField( model_name='mailsubscription', name='title', field=models.CharField(blank=True, max_length=350, null=True), ), migrations.AlterField( model_name='mailtemplate', name='category', field=models.ForeignKey(blank=True, default=2, null=True, on_delete=django.db.models.deletion.CASCADE, to='dbmail.MailCategory', verbose_name='Category'), ), migrations.AlterField( model_name='mailtemplate', name='from_email', field=models.ForeignKey(blank=True, default=2, help_text='If not specified, then used default.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='dbmail.MailFromEmail', verbose_name='Message from'), ), ]
class MailLog(models.Model): is_sent = models.BooleanField(_('Is sent'), default=True, db_index=True) template = models.ForeignKey(MailTemplate, verbose_name=_('Template')) created = models.DateTimeField(_('Created'), auto_now_add=True) user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_('User'), null=True, blank=True) error_message = models.TextField(_('Error message'), null=True, blank=True) error_exception = models.ForeignKey(MailLogException, null=True, blank=True, verbose_name=_('Exception')) num_of_retries = models.PositiveIntegerField(_('Number of retries'), default=1) log_id = models.CharField(_('Log ID'), max_length=60, editable=False, db_index=True) backend = models.CharField(_('Backend'), max_length=25, editable=False, db_index=True, choices=BACKEND.items(), default='mail') provider = models.CharField(_('Provider'), max_length=250, editable=False, db_index=True, default=None, null=True, blank=True) @staticmethod def store_email_log(log, email_list, mail_type): if log and email_list: for email in email_list: MailLogEmail.objects.create(log=log, email=email, mail_type=mail_type) @classmethod def store(cls, to, cc, bcc, is_sent, template, user, num, msg='', ex=None, log_id=None, backend=None, provider=None): if ex is not None: ex = MailLogException.objects.get_or_create(name=ex)[0] log = cls.objects.create(template=template, is_sent=is_sent, user=user, log_id=log_id, num_of_retries=num, error_message=msg, error_exception=ex, backend=_BACKEND[backend], provider=provider) cls.store_email_log(log, to, 'to') cls.store_email_log(log, cc, 'cc') cls.store_email_log(log, bcc, 'bcc') @classmethod def cleanup(cls, days=7): date = now() - datetime.timedelta(days=days) cls.objects.filter(created__lte=date).delete() def __unicode__(self): return self.template.name class Meta: verbose_name = _('Mail log') verbose_name_plural = _('Mail logs')
class MailSubscriptionAbstract(models.Model): title = models.CharField(null=True, max_length=350, blank=True) user = models.ForeignKey( AUTH_USER_MODEL, verbose_name=_('User'), null=True, blank=True) backend = models.CharField( _('Backend'), choices=BACKENDS_MODEL_CHOICES, max_length=50, default=BACKEND.get('mail')) start_hour = models.CharField( _('Start hour'), default='00:00', max_length=5) end_hour = models.CharField(_('End hour'), default='23:59', max_length=5) is_enabled = models.BooleanField( _('Is enabled'), default=True, db_index=True) is_checked = models.BooleanField( _('Is checked'), default=False, db_index=True) defer_at_allowed_hours = models.BooleanField( _('Defer at allowed hours'), default=False) address = models.CharField( _('Address'), max_length=350, db_index=True, help_text=_('Must be phone number/email/token')) data = SubscriptionDataField(null=True, blank=True) def send_confirmation_link( self, slug='subs-confirmation', *args, **kwargs): from dbmail import db_sender kwargs['backend'] = self.backend db_sender(slug, self.address, *args, **kwargs) @staticmethod def get_now(): d = timezone.now() if d.tzinfo: return timezone.localtime(timezone.now()) return d @staticmethod def get_current_hour(): current = MailSubscriptionAbstract.get_now() return datetime.timedelta(hours=current.hour, minutes=current.minute) @staticmethod def convert_to_date(value): hour, minute = value.split(':') return datetime.timedelta(hours=int(hour), minutes=int(minute)) @classmethod def mix_hour_with_date(cls, value): return datetime.datetime.strptime( cls.get_now().strftime('%Y-%m-%d ') + value, '%Y-%m-%d %H:%M') @classmethod def get_notification_list(cls, user_id, **kwargs): kwargs.update({ 'is_enabled': True, 'is_checked': True, }) if user_id is not None: kwargs.update({ 'user_id': user_id, }) return cls.objects.filter(**kwargs) @classmethod def notify(cls, slug, user_id=None, sub_filter=None, **kwargs): from dbmail import db_sender now_hour = cls.get_current_hour() context_dict = kwargs.pop('context', {}) context_instance = kwargs.pop('context_instance', None) sub_filter = sub_filter if isinstance(sub_filter, dict) else {} for method_id in cls.get_notification_list( user_id, **sub_filter).values_list('pk', flat=True): method = cls.objects.get(pk=method_id) method_kwargs = kwargs.copy() method_kwargs['send_at_date'] = None start_hour = cls.convert_to_date(method.start_hour) end_hour = cls.convert_to_date(method.end_hour) if not (start_hour <= now_hour <= end_hour): if (method.defer_at_allowed_hours and method_kwargs['use_celery']): method_kwargs['send_at_date'] = cls.mix_hour_with_date( method.start_hour) else: continue method_kwargs['backend'] = method.backend method_kwargs = method.update_notify_kwargs(**method_kwargs) use_slug = method.get_final_slug(slug, method.get_short_type()) db_sender(use_slug, method.address, context_dict, context_instance, **method_kwargs) def update_notify_kwargs(self, **kwargs): return kwargs def get_final_slug(self, slug, _): for extra_slug in self.get_extra_slugs(slug): try: if MailTemplate.get_template(slug=extra_slug): slug = extra_slug break except MailTemplate.DoesNotExist: pass return slug def get_extra_slugs(self, slug): return [ u'{}-{}'.format(slug, self.get_short_type()), ] def get_short_type(self): return self.backend.split('.')[-1] class Meta: abstract = True