Pull requests

#2 Merged
Repository
ftyurin
Branch
default
Repository
pmclanahan
Branch
default

Save backend constructor kwargs in the init_kwargs and use them in the task when calling get_connection

Author
  1. Fedor Tyurin
Reviewers
Description

This fixes the issue, which i've reported.

  • Learn about pull requests

Comments (6)

  1. Paul McLanahan repo owner

    This looks interesting. I didn't realize that it was common to use the constructor args of the SMTP backend to setup auth. This will need some tests to ensure that the args really are making it to the SMTP backend. Add some and I'll get it merged and released.

    Thanks for the contribution!

    1. Fedor Tyurin author

      It's very good that you asked me to write tests :) Now I realized that there is a bug in my code caused by the inconsistent behavior of django core mail functionality (you must have received notification about the issue https://code.djangoproject.com/ticket/17811, which i created in django trac system). There are two possible workarounds for this. The first one would be to add extra parameter to the task function to pass init_kwargs (keyword arguments passed to the original backend constructor). And the second one would be to put init_kwargs into the message object just before passing it to the task function. The second one is dirty in my opinion, but doesn't require changes in the interface of the task. The third option would be just to replace **message.connection.init_kwargs with **getattrs(message.connection, 'init_kwargs', {}), which means that celery email backend will correctly work only when connection is set in the message. Please share your opinion.

      1. Paul McLanahan repo owner

        I like what you've done, but I think I like your first option best. Since the task already accepts **kwargs, we could just do something like:

            def send_messages(self, email_messages, **kwargs):
                results = []
                kwargs['backend_kwargs'] = self.init_kwargs
                for msg in email_messages:
                    results.append(send_email.delay(msg, **kwargs))
                return results
        

        then in the task:

            conn = get_connection(backend=BACKEND, **kwargs.get('backend_kwargs', {}))
        

        I think that's the most strait-forward, readable, and reliable.

        Thanks for the options, and for CCing me on the django bug.