title: Setting up Django with Redis, Celery to send emails via Gmail
body: <p>I'd like to set up my Django app to set up emails via Gmail using an async task queue. I'm using Celery, with Redis as my broker. However, I'm not able to send emails when I define Celery as my email backend -- I get an error stating that the connection failed:</p>
  
  <pre><code>   ...: 
  ---------------------------------------------------------------------------
  AttributeError                            Traceback (most recent call last)
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/utils/functional.py in __call__(self)
       35         try:
  ---&gt; 36             return self.__value__
       37         except AttributeError:
  
  AttributeError: 'ChannelPromise' object has no attribute '__value__'
  
  During handling of the above exception, another exception occurred:
  
  ConnectionRefusedError                    Traceback (most recent call last)
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _ensured(*args, **kwargs)
      493                     try:
  --&gt; 494                         return fun(*args, **kwargs)
      495                     except conn_errors as exc:
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/messaging.py in _publish(self, body, priority, content_type, content_encoding, headers, properties, routing_key, mandatory, immediate, exchange, declare)
      186                  immediate, exchange, declare):
  --&gt; 187         channel = self.channel
      188         message = channel.prepare_message(
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/messaging.py in _get_channel(self)
      208         if isinstance(channel, ChannelPromise):
  --&gt; 209             channel = self._channel = channel()
      210             self.exchange.revive(channel)
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/utils/functional.py in __call__(self)
       37         except AttributeError:
  ---&gt; 38             value = self.__value__ = self.__contract__()
       39             return value
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/messaging.py in &lt;lambda&gt;()
      223             self.__connection__ = connection
  --&gt; 224             channel = ChannelPromise(lambda: connection.default_channel)
      225         if isinstance(channel, ChannelPromise):
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in default_channel(self)
      818         # make sure we're still connected, and if not refresh.
  --&gt; 819         self.connection
      820         if self._default_channel is None:
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in connection(self)
      801                 self._default_channel = None
  --&gt; 802                 self._connection = self._establish_connection()
      803                 self._closed = False
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _establish_connection(self)
      756         self._debug('establishing connection...')
  --&gt; 757         conn = self.transport.establish_connection()
      758         self._debug('connection established: %r', self)
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/transport/pyamqp.py in establish_connection(self)
      129         conn.client = self.client
  --&gt; 130         conn.connect()
      131         return conn
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/connection.py in connect(self, callback)
      293         )
  --&gt; 294         self.transport.connect()
      295         self.on_inbound_frame = self.frame_handler_cls(
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/transport.py in connect(self)
      119     def connect(self):
  --&gt; 120         self._connect(self.host, self.port, self.connect_timeout)
      121         self._init_socket(
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/transport.py in _connect(self, host, port, timeout)
      160                 self.sock.settimeout(timeout)
  --&gt; 161                 self.sock.connect(sa)
      162             except socket.error:
  
  ConnectionRefusedError: [Errno 61] Connection refused
  
  During handling of the above exception, another exception occurred:
  
  ConnectionRefusedError                    Traceback (most recent call last)
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _reraise_as_library_errors(self, ConnectionError, ChannelError)
      413         try:
  --&gt; 414             yield
      415         except (ConnectionError, ChannelError):
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _ensured(*args, **kwargs)
      514                             interval_start, interval_step, interval_max,
  --&gt; 515                             reraise_as_library_errors=False,
      516                         )
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in ensure_connection(self, errback, max_retries, interval_start, interval_step, interval_max, callback, reraise_as_library_errors)
      404                             interval_start, interval_step, interval_max,
  --&gt; 405                             callback)
      406         return self
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/utils/functional.py in retry_over_time(fun, catch, args, kwargs, errback, max_retries, interval_start, interval_step, interval_max, callback)
      332         try:
  --&gt; 333             return fun(*args, **kwargs)
      334         except catch as exc:
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in connect(self)
      260         self._closed = False
  --&gt; 261         return self.connection
      262 
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in connection(self)
      801                 self._default_channel = None
  --&gt; 802                 self._connection = self._establish_connection()
      803                 self._closed = False
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _establish_connection(self)
      756         self._debug('establishing connection...')
  --&gt; 757         conn = self.transport.establish_connection()
      758         self._debug('connection established: %r', self)
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/transport/pyamqp.py in establish_connection(self)
      129         conn.client = self.client
  --&gt; 130         conn.connect()
      131         return conn
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/connection.py in connect(self, callback)
      293         )
  --&gt; 294         self.transport.connect()
      295         self.on_inbound_frame = self.frame_handler_cls(
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/transport.py in connect(self)
      119     def connect(self):
  --&gt; 120         self._connect(self.host, self.port, self.connect_timeout)
      121         self._init_socket(
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/transport.py in _connect(self, host, port, timeout)
      160                 self.sock.settimeout(timeout)
  --&gt; 161                 self.sock.connect(sa)
      162             except socket.error:
  
  ConnectionRefusedError: [Errno 61] Connection refused
  
  During handling of the above exception, another exception occurred:
  
  OperationalError                          Traceback (most recent call last)
  &lt;ipython-input-1-75e7f965af5d&gt; in &lt;module&gt;()
        1 from django.core.mail import send_mail
  ----&gt; 2 send_mail('test email', 'hello world', 'myemail@gmail.com', recipient_list=['test@test.com'], fail_silently=False)
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/django/core/mail/__init__.py in send_mail(subject, message, from_email, recipient_list, fail_silently, auth_user, auth_password, connection, html_message)
       59         mail.attach_alternative(html_message, 'text/html')
       60 
  ---&gt; 61     return mail.send()
       62 
       63 
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/django/core/mail/message.py in send(self, fail_silently)
      290             # send to.
      291             return 0
  --&gt; 292         return self.get_connection(fail_silently).send_messages([self])
      293 
      294     def attach(self, filename=None, content=None, mimetype=None):
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/djcelery_email/backends.py in send_messages(self, email_messages)
       15         messages = [email_to_dict(msg) for msg in email_messages]
       16         for chunk in chunked(messages, settings.CELERY_EMAIL_CHUNK_SIZE):
  ---&gt; 17             result_tasks.append(send_emails.delay(chunk, self.init_kwargs))
       18         return result_tasks
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/celery/app/task.py in delay(self, *args, **kwargs)
      410             celery.result.AsyncResult: Future promise.
      411         """
  --&gt; 412         return self.apply_async(args, kwargs)
      413 
      414     def apply_async(self, args=None, kwargs=None, task_id=None, producer=None,
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/celery/app/task.py in apply_async(self, args, kwargs, task_id, producer, link, link_error, shadow, **options)
      533             link=link, link_error=link_error, result_cls=self.AsyncResult,
      534             shadow=shadow, task_type=self,
  --&gt; 535             **options
      536         )
      537 
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/celery/app/base.py in send_task(self, name, args, kwargs, countdown, eta, task_id, producer, connection, router, result_cls, expires, publisher, link, link_error, add_to_parent, group_id, retries, chord, reply_to, time_limit, soft_time_limit, root_id, parent_id, route_name, shadow, chain, task_type, **options)
      735             with P.connection._reraise_as_library_errors():
      736                 self.backend.on_task_call(P, task_id)
  --&gt; 737                 amqp.send_task_message(P, name, message, **options)
      738         result = (result_cls or self.AsyncResult)(task_id)
      739         if add_to_parent:
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/celery/app/amqp.py in send_task_message(producer, name, message, exchange, routing_key, queue, event_dispatcher, retry, retry_policy, serializer, delivery_mode, compression, declare, headers, exchange_type, **kwargs)
      556                 delivery_mode=delivery_mode, declare=declare,
      557                 headers=headers2,
  --&gt; 558                 **properties
      559             )
      560             if after_receivers:
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/messaging.py in publish(self, body, routing_key, delivery_mode, mandatory, immediate, priority, content_type, content_encoding, serializer, headers, compression, exchange, retry, retry_policy, declare, expiration, **properties)
      179             body, priority, content_type, content_encoding,
      180             headers, properties, routing_key, mandatory, immediate,
  --&gt; 181             exchange_name, declare,
      182         )
      183 
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _ensured(*args, **kwargs)
      525                         self._debug('ensure channel error: %r',
      526                                     exc, exc_info=1)
  --&gt; 527                         errback and errback(exc, 0)
      528         _ensured.__name__ = bytes_if_py2('{0}(ensured)'.format(fun.__name__))
      529         _ensured.__doc__ = fun.__doc__
  
  /usr/local/Cellar/python3/3.4.3_2/Frameworks/Python.framework/Versions/3.4/lib/python3.4/contextlib.py in __exit__(self, type, value, traceback)
       75                 value = type()
       76             try:
  ---&gt; 77                 self.gen.throw(type, value, traceback)
       78                 raise RuntimeError("generator didn't stop after throw()")
       79             except StopIteration as exc:
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _reraise_as_library_errors(self, ConnectionError, ChannelError)
      417         except self.recoverable_connection_errors as exc:
      418             reraise(ConnectionError, ConnectionError(text_t(exc)),
  --&gt; 419                     sys.exc_info()[2])
      420         except self.recoverable_channel_errors as exc:
      421             reraise(ChannelError, ChannelError(text_t(exc)),
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/vine/five.py in reraise(tp, value, tb)
      173         """Reraise exception."""
      174         if value.__traceback__ is not tb:
  --&gt; 175             raise value.with_traceback(tb)
      176         raise value
      177 
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _reraise_as_library_errors(self, ConnectionError, ChannelError)
      412             ChannelError=exceptions.OperationalError):
      413         try:
  --&gt; 414             yield
      415         except (ConnectionError, ChannelError):
      416             raise
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _ensured(*args, **kwargs)
      513                             remaining_retries,
      514                             interval_start, interval_step, interval_max,
  --&gt; 515                             reraise_as_library_errors=False,
      516                         )
      517                         channel = self.default_channel
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in ensure_connection(self, errback, max_retries, interval_start, interval_step, interval_max, callback, reraise_as_library_errors)
      403                             (), {}, on_error, max_retries,
      404                             interval_start, interval_step, interval_max,
  --&gt; 405                             callback)
      406         return self
      407 
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/utils/functional.py in retry_over_time(fun, catch, args, kwargs, errback, max_retries, interval_start, interval_step, interval_max, callback)
      331     for retries in count():
      332         try:
  --&gt; 333             return fun(*args, **kwargs)
      334         except catch as exc:
      335             if max_retries and retries &gt;= max_retries:
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in connect(self)
      259         """Establish connection to server immediately."""
      260         self._closed = False
  --&gt; 261         return self.connection
      262 
      263     def channel(self):
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in connection(self)
      800                 self.declared_entities.clear()
      801                 self._default_channel = None
  --&gt; 802                 self._connection = self._establish_connection()
      803                 self._closed = False
      804             return self._connection
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/connection.py in _establish_connection(self)
      755     def _establish_connection(self):
      756         self._debug('establishing connection...')
  --&gt; 757         conn = self.transport.establish_connection()
      758         self._debug('connection established: %r', self)
      759         return conn
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/kombu/transport/pyamqp.py in establish_connection(self)
      128         conn = self.Connection(**opts)
      129         conn.client = self.client
  --&gt; 130         conn.connect()
      131         return conn
      132 
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/connection.py in connect(self, callback)
      292             socket_settings=self.socket_settings,
      293         )
  --&gt; 294         self.transport.connect()
      295         self.on_inbound_frame = self.frame_handler_cls(
      296             self, self.on_inbound_method)
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/transport.py in connect(self)
      118 
      119     def connect(self):
  --&gt; 120         self._connect(self.host, self.port, self.connect_timeout)
      121         self._init_socket(
      122             self.socket_settings, self.read_timeout, self.write_timeout,
  
  /Users/user/virtualenvs/myapp/lib/python3.4/site-packages/amqp/transport.py in _connect(self, host, port, timeout)
      159                     pass
      160                 self.sock.settimeout(timeout)
  --&gt; 161                 self.sock.connect(sa)
      162             except socket.error:
      163                 self.sock.close()
  
  OperationalError: [Errno 61] Connection refused
  </code></pre>
  
  <p>Attempting to debug yields to following:</p>
  
  <p>I am able to successfully start the redis server and ping it. However, when I try to start the celery worker using <code>celery worker -A myapp -l info -c 5</code>, I get an error. I am guessing this is due to authentication? It looks like it is just trying to log in as an anonymous user, but I am not sure how to pass it a username and password.</p>
  
  <p>celery worker -A myapp -l info -c 5</p>
  
  <pre><code> -------------- celery@Users-iMac v4.0.2 (latentcall)
  ---- **** ----- 
  --- * ***  * -- Darwin-15.6.0-x86_64-i386-64bit 2017-01-02 19:58:38
  -- * - **** --- 
  - ** ---------- [config]
  - ** ---------- .&gt; app:         myapp:0x10dc15400
  - ** ---------- .&gt; transport:   amqp://guest:**@localhost:5672//
  - ** ---------- .&gt; results:     disabled://
  - *** --- * --- .&gt; concurrency: 5 (prefork)
  -- ******* ---- .&gt; task events: OFF (enable -E to monitor tasks in this worker)
  --- ***** ----- 
   -------------- [queues]
                  .&gt; celery           exchange=celery(direct) key=celery
  
  
  [tasks]
    . djcelery_email_send
    . myapp.celery.debug_task
  
  [2017-01-02 19:58:39,187: ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 61] Connection refused.
  Trying again in 2.00 seconds...
  
  [2017-01-02 19:58:41,199: ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 61] Connection refused.
  Trying again in 4.00 seconds...
  
  [2017-01-02 19:58:45,219: ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 61] Connection refused.
  Trying again in 6.00 seconds...
  
  [2017-01-02 19:58:51,245: ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 61] Connection refused.
  Trying again in 8.00 seconds...
  </code></pre>
  
  <p>I am using <code>djcelery_email</code>, have a file at <code>myapp/myapp/__init__.py</code> that is as follows:</p>
  
  <pre><code># This will make sure the app is always imported when
  # Django starts so that shared_task will use this app.
  from .celery import app as celery_app
  
  __all__ = ['celery_app']
  </code></pre>
  
  <p>as well as a <code>celery.py</code> file at the same level as <code>settings.py</code></p>
  
  <pre><code>import os
  from celery import Celery
  from celery.bin import Option
  
  # set the default Django settings module for the 'celery' program.
  os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')
  
  app = Celery('myapp')
  
  # Using a string here means the worker don't have to serialize
  # the configuration object to child processes.
  # - namespace='CELERY' means all celery-related configuration keys
  #   should have a `CELERY_` prefix.
  app.config_from_object('django.conf:settings', namespace='CELERY')
  
  
  # Load task modules from all registered Django app configs.
  app.autodiscover_tasks()
  
  
  @app.task(bind=True)
  def debug_task(self):
      print('Request: {0!r}'.format(self.request))
  </code></pre>
  
  <p>and have the following `settings.py:</p>
  
  <pre><code># Email
  
  CACHES = {
      "default": {
          "BACKEND": "django_redis.cache.RedisCache",
          "LOCATION": "redis://127.0.0.1:6379/1",
          "OPTIONS": {
              "CLIENT_CLASS": "django_redis.client.DefaultClient",
          }
      }
  }
  
  EMAIL_HOST = 'smtp.gmail.com'  # since you are using a gmail account
  EMAIL_PORT = 587  # Gmail SMTP port for TLS
  EMAIL_USE_TLS = True
  EMAIL_HOST_USER = 'myemail@gmail.com'
  EMAIL_HOST_PASSWORD = 'secret_password'
  EMAIL_BACKEND = 'djcelery_email.backends.CeleryEmailBackend' # Use Celery for sending emails
  CELERY_EMAIL_TASK_CONFIG = {
      'name': 'djcelery_email_send',
      'ignore_result': True,
  }
  
  BROKER_URL = 'redis://127.0.0.1:6379/1'
  </code></pre>
  
  <p>what changes do I need to make to be able to send emails using Redis, Celery, and Django?</p>