# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import logging

from contextlib import closing
from email.utils import formataddr

from django.conf import settings
from django.contrib.auth.models import User
from django.core import mail
from django.template.loader import render_to_string
from django.utils.encoding import force_text

from pyconde.celery import app

from ..conference.models import current_conference
from .utils import SEND_MAIL_FILTERS, get_addressed_as


LOG = logging.getLogger(__name__)


@app.task(ignore_result=True)
def sendmail_task(target, subject, message, domain):
    users = User.objects.select_related('profile').all()
    users = SEND_MAIL_FILTERS[target](users)

    prefix = '[%s]' % force_text(current_conference())
    if not subject.startswith(prefix):
        subject = '%s %s' % (prefix, subject)

    base_message = message.replace('$$CONFERENCE$$',
                                   force_text(current_conference())) \
                          .replace('$$DOMAIN$$', domain)
    base_message = render_to_string('accounts/emails/sendmail.txt', {
        'conference': current_conference(),
        'message': base_message,
    })

    # Re-use the connection to the server, so that a connection is not
    # implicitly created for every mail, as described in the docs:
    # https://docs.djangoproject.com/en/dev/topics/email/#sending-multiple-emails
    with closing(mail.get_connection()) as connection:
        cnt = 0
        for user in users:
            addressed_as = get_addressed_as(user)
            body = base_message.replace('$$RECEIVER$$', addressed_as)
            to = formataddr((addressed_as, user.email))
            email = mail.EmailMessage(subject, body, to=[to],
                headers={'Reply-To': settings.SUPPORT_EMAIL},
                connection=connection
            )
            email.send()
            cnt += 1
            if cnt % 50 == 0:
                LOG.info('Wrote {0} mails'.format(cnt))
        LOG.info('Wrote {0} mails in total'.format(cnt))

@@ -521,16 +521,94 @@
 me__)%0A%0A%0A
+def chunks(l, n):%0A    for i in xrange(0, len(l), n):%0A        yield l%5Bi:i+n%5D%0A%0A%0A
 @app.tas
@@ -1482,16 +1482,283 @@
 -emails%0A
+    for i, userset in enumerate(chunks(users, 50)):%0A        sendmail_task_users.delay(userset, subject, base_message)%0A        LOG.info('Delayed sendmail_task_users %7B0%7D'.format(i))%0A%0A%0A@app.task(ignore_result=True)%0Adef sendmail_task_users(users, subject, base_message):%0A
     with
@@ -1808,24 +1808,8 @@
 on:%0A
-        cnt = 0%0A
     
@@ -1815,16 +1815,19 @@
      for
+ i,
  user in
@@ -1831,15 +1831,47 @@
  in 
+enumerate(
 users
+)
 :%0A
+            try:%0A    
     
@@ -1916,16 +1916,20 @@
 s(user)%0A
+    
         
@@ -2002,16 +2002,20 @@
         
+ 
+   
 to = for
@@ -2050,16 +2050,20 @@
 email))%0A
+    
         
@@ -2132,16 +2132,20 @@
         
+ 
+   
 headers=
@@ -2182,16 +2182,20 @@
 EMAIL%7D,%0A
+    
         
@@ -2236,18 +2236,26 @@
         
-)%0A
+    )%0A    
         
@@ -2287,156 +2287,120 @@
     
-cnt += 1%0A            if cnt %25 50 == 0:%0A                LOG.info('Wrote %7B0%7D mails'.format(cnt))%0A        LOG.info('Wrote %7B0%7D mails in total'.format(cnt
+except Exception as e:%0A                LOG.error('Error sending mail %22%7B0%7D%22 to %22%7B1%7D%22: %7B2%7D'.format(subject, user, e
 ))%0A

Split mail sending into smaller chunks of users and prevent failing on one user breaking the entire process