Search code examples
pythongoogle-app-enginesendmailtask-queue

Google AppEngine unable to defer a sendmail job to default taskqueue , receives unauthorized sender error


Hi am trying to defer sending mail via sendmail. Am able to send mail no problem. As soon as I try deferred.defer(send_invitation,recipient), it stops working.

I can see the tasks retrying to max allowed limit, and the logs show:

File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/mail.py", line 1136, in send
    raise ERROR_MAP[e.application_error](e.error_detail)
InvalidSenderError: Unauthorized sender

Does this mean that if a sendmail job is sent to the default queue (or any queue), it is no longer considered as being sent from the original sender, and that the new sender (i.e. the queue) is not authorized??

Without using deferred.defer the mail is sent, both with project owner's email, and default appengine service account. Both accounts have needed permissions/roles.

    import webapp2
    from google.appengine.ext import deferred
    import jinja2
    import os
    import datetime
    from google.appengine.api import users, mail


    recipient ='[email protected]'

    user = users.GetCurrentUser().email()

    print "THIS IS THE CURRENT USER %s" %user


    def send_invitation(recipient):
                print "In the def user email is %s" %user

                mail.send_mail(sender=user,to=recipient, subject='You\'re invited!',body='''You have been invited to join our community...''')



    class SendInvitationHandler(webapp2.RequestHandler):
        print "This is user within the class %s" %user
        def get(self):
            user = users.GetCurrentUser().email()
            tempalte_env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.getcwd()))
            current_time =  datetime.datetime.now()
            template = tempalte_env.get_template('invitation.html')
            message = "<p>%s, and an invitation to %s has been deferred from %s</p>" % (datetime.datetime.now(),recipient, user)
            context = {'recipient': recipient,
                        'message': message,
                        'current_time': current_time,
                        'user': user
                        }
            self.response.out.write(template.render(context))

            deferred.defer(send_invitation,recipient)

app = webapp2.WSGIApplication([('/sendinvite', SendInvitationHandler)], debug=True)

Change line deferred.defer(send_invitation,recipient) to send_invitation(recipient) and it works ...


Solution

  • The deferred task executes on a different handler in response to a different request, it no longer has the context of the original request. So basically you no longer have the user set.

    You need to collect all the info required to send the message in the original context and pass it as parameter(s) to the deferred task. In your particular case you need to pass user as well, in addition to recipient, something like this:

    def send_invitation(recipient, sender):
    
        mail.send_mail(sender=sender, to=recipient, 
                       subject='You\'re invited!',
                       body='''You have been invited to join our community...''')
    

    and defer it with:

            deferred.defer(send_invitation, recipient, user)