Improved bulk mailer detection and fixes on domain serializer validation
This commit is contained in:
parent
1223ed85e6
commit
7c5eff9a90
|
@ -15,7 +15,7 @@ class AccountSerializer(serializers.HyperlinkedModelSerializer):
|
|||
class AccountSerializerMixin(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AccountSerializerMixin, self).__init__(*args, **kwargs)
|
||||
self.account = None
|
||||
self.account = self.get_account()
|
||||
|
||||
def get_account(self):
|
||||
request = self.context.get('request')
|
||||
|
|
|
@ -93,7 +93,7 @@ hr {
|
|||
{{ buyer.vat }}<br>
|
||||
{{ buyer.address }}<br>
|
||||
{{ buyer.zipcode }} - {{ buyer.city }}<br>
|
||||
{{ buyer.get_country_display }}<br>
|
||||
{% trans buyer.get_country_display %}<br>
|
||||
</div>
|
||||
|
||||
<div id="number" class="column-1">
|
||||
|
|
|
@ -39,9 +39,13 @@ class DomainSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
|||
def validate(self, data):
|
||||
""" Checks if everything is consistent """
|
||||
data = super(DomainSerializer, self).validate(data)
|
||||
if self.instance and data.get('name'):
|
||||
name = data.get('name')
|
||||
if name:
|
||||
instance = self.instance
|
||||
if instance is None:
|
||||
instance = Domain(name=name, account=self.account)
|
||||
records = data['records']
|
||||
domain = domain_for_validation(self.instance, records)
|
||||
domain = domain_for_validation(instance, records)
|
||||
validators.validate_zone(domain.render_zone())
|
||||
return data
|
||||
|
||||
|
@ -52,9 +56,9 @@ class DomainSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
|||
domain.records.create(type=record['type'], value=record['value'])
|
||||
return domain
|
||||
|
||||
def update(self, validated_data):
|
||||
def update(self, instance, validated_data):
|
||||
precords = validated_data.pop('records')
|
||||
domain = super(DomainSerializer, self).update(validated_data)
|
||||
domain = super(DomainSerializer, self).update(instance, validated_data)
|
||||
to_delete = []
|
||||
for erecord in domain.records.all():
|
||||
match = False
|
||||
|
@ -63,7 +67,7 @@ class DomainSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
|||
match = True
|
||||
break
|
||||
if match:
|
||||
precords.remove(ix)
|
||||
precords.pop(ix)
|
||||
else:
|
||||
to_delete.append(erecord)
|
||||
for precord in precords:
|
||||
|
|
|
@ -120,7 +120,10 @@ def validate_zone(zone):
|
|||
# Don't use /dev/stdin becuase the 'argument list is too long' error
|
||||
check = run(' '.join([checkzone, zone_name, zone_path]), valid_codes=(0,1,127), display=False)
|
||||
finally:
|
||||
os.unlink(zone_path)
|
||||
try:
|
||||
os.unlink(zone_path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
if check.exit_code == 127:
|
||||
logger.error("Cannot validate domain zone: %s not installed." % checkzone)
|
||||
elif check.exit_code == 1:
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from django.conf import settings as djsettings
|
||||
from django.core.mail.backends.base import BaseEmailBackend
|
||||
|
||||
from orchestra.core.caches import get_request_cache
|
||||
|
||||
from . import settings
|
||||
from .models import Message
|
||||
from .tasks import send_message
|
||||
|
||||
|
@ -9,17 +12,27 @@ class EmailBackend(BaseEmailBackend):
|
|||
"""
|
||||
A wrapper that manages a queued SMTP system.
|
||||
"""
|
||||
messages = 0
|
||||
|
||||
def send_messages(self, email_messages):
|
||||
if not email_messages:
|
||||
return
|
||||
num_sent = 0
|
||||
cache = get_request_cache()
|
||||
key = 'mailer.sent_messages'
|
||||
sent_messages = cache.get(key) or 0
|
||||
sent_messages += 1
|
||||
cache.set(key, sent_messages)
|
||||
|
||||
is_bulk = len(email_messages) > 1
|
||||
if sent_messages > settings.MAILER_NON_QUEUED_MAILS_PER_REQUEST_THRESHOLD:
|
||||
is_bulk = True
|
||||
default_priority = Message.NORMAL if is_bulk else Message.CRITICAL
|
||||
num_sent = 0
|
||||
for message in email_messages:
|
||||
priority = message.extra_headers.get('X-Mail-Priority', default_priority)
|
||||
content = message.message().as_string()
|
||||
for to_email in message.recipients():
|
||||
message = Message.objects.create(
|
||||
message = Message(
|
||||
priority=priority,
|
||||
to_address=to_email,
|
||||
from_address=getattr(message, 'from_email', djsettings.DEFAULT_FROM_EMAIL),
|
||||
|
@ -29,5 +42,7 @@ class EmailBackend(BaseEmailBackend):
|
|||
if priority == Message.CRITICAL:
|
||||
# send immidiately
|
||||
send_message.apply_async(message)
|
||||
else:
|
||||
message.save()
|
||||
num_sent += 1
|
||||
return num_sent
|
||||
|
|
|
@ -50,7 +50,7 @@ class Message(models.Model):
|
|||
|
||||
def sent(self):
|
||||
self.state = self.SENT
|
||||
self.save(update_fields=('state',))
|
||||
self.save()
|
||||
|
||||
def log(self, error):
|
||||
result = SMTPLog.SUCCESS
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.contrib.settings import Setting
|
||||
|
||||
|
||||
|
@ -9,3 +11,9 @@ MAILER_DEFERE_SECONDS = Setting('MAILER_DEFERE_SECONDS',
|
|||
MAILER_MESSAGES_CLEANUP_DAYS = Setting('MAILER_MESSAGES_CLEANUP_DAYS',
|
||||
7
|
||||
)
|
||||
|
||||
|
||||
MAILER_NON_QUEUED_MAILS_PER_REQUEST_THRESHOLD = Setting('MAILER_NON_QUEUED_MAILS_PER_REQUEST_THRESHOLD',
|
||||
2,
|
||||
help_text=_("Number of emails that will be sent directly before starting to queue them."),
|
||||
)
|
||||
|
|
|
@ -27,11 +27,19 @@ def get_request_cache():
|
|||
|
||||
class RequestCacheMiddleware(object):
|
||||
def process_request(self, request):
|
||||
cache = _request_cache.get(currentThread(), RequestCache())
|
||||
_request_cache[currentThread()] = cache
|
||||
current_thread = currentThread()
|
||||
cache = _request_cache.get(current_thread, RequestCache())
|
||||
_request_cache[current_thread] = cache
|
||||
cache.clear()
|
||||
|
||||
def process_response(self, request, response):
|
||||
def clear_cache(self):
|
||||
current_thread = currentThread()
|
||||
if currentThread() in _request_cache:
|
||||
_request_cache[currentThread()].clear()
|
||||
_request_cache[current_thread].clear()
|
||||
|
||||
def process_exception(self, request, exception):
|
||||
self.clear_cache()
|
||||
|
||||
def process_response(self, request, response):
|
||||
self.clear_cache()
|
||||
return response
|
||||
|
|
|
@ -5,7 +5,6 @@ from orchestra.utils.sys import run
|
|||
|
||||
def html_to_pdf(html, pagination=False):
|
||||
""" converts HTL to PDF using wkhtmltopdf """
|
||||
print(pagination)
|
||||
context = {
|
||||
'pagination': textwrap.dedent("""\
|
||||
--footer-center "Page [page] of [topage]"\\
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.template.loader import render_to_string
|
|||
from django.template import Context
|
||||
|
||||
|
||||
def send_email_template(template, context, to, email_from=None, html=None, attachments=[]):
|
||||
def render_email_template(template, context):
|
||||
"""
|
||||
Renders an email template with this format:
|
||||
{% if subject %}Subject{% endif %}
|
||||
|
@ -13,7 +13,6 @@ def send_email_template(template, context, to, email_from=None, html=None, attac
|
|||
|
||||
context can be a dictionary or a template.Context instance
|
||||
"""
|
||||
|
||||
if isinstance(context, dict):
|
||||
context = Context(context)
|
||||
if isinstance(to, str):
|
||||
|
@ -27,13 +26,16 @@ def send_email_template(template, context, to, email_from=None, html=None, attac
|
|||
'scheme': url.scheme,
|
||||
'domain': url.netloc,
|
||||
}
|
||||
|
||||
#subject cannot have new lines
|
||||
subject = render_to_string(template, {'subject': True}, context).strip()
|
||||
message = render_to_string(template, {'message': True}, context).strip()
|
||||
return subject, message
|
||||
|
||||
|
||||
def send_email_template(template, context, to, email_from=None, html=None, attachments=[]):
|
||||
subject, message = render_email_template(template, context)
|
||||
msg = EmailMultiAlternatives(subject, message, email_from, to, attachments=attachments)
|
||||
if html:
|
||||
html_message = render_to_string(html, {'message': True}, context)
|
||||
subject, html_message = render_email_template(html, context)
|
||||
msg.attach_alternative(html_message, "text/html")
|
||||
msg.send()
|
||||
|
||||
|
|
Loading…
Reference in a new issue