简体   繁体   中英

Sending emails from Google Appengine fails because of missing api proxy

I am trying to send e-mails from a GAE application using this code:

from google.appengine.api.mail import send_mail

send_mail(
    "sender@nowhere.com",
    ["user@example.com"],
            "Subject",
            "Body",
)

I have configured usage of the apis in app.yaml with:

app_engine_apis: true

And deploy to App Engine is done with gcloud beta app deploy .

However, I get this error:

Traceback (most recent call last):   
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 2073, in wsgi_app      response = self.full_dispatch_request()    
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1518, in full_dispatch_request      rv = self.handle_user_exception(e)    
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1516, in full_dispatch_request      rv = self.dispatch_request()    
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1502, in dispatch_request      return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)    
File "/srv/infrastructure/view_modifiers.py", line 12, in view_method      response_val = f(*args, **kwargs)    
File "/srv/views/orders.py", line 25, in create_order      vm.create_order()    
File "/srv/viewmodels/orders/order_viewmodel.py", line 74, in create_order      self._send_order_email()    
File "/srv/viewmodels/orders/order_viewmodel.py", line 54, in _send_order_email      send_mail(    
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/api/mail.py", line 401, in send_mail      message.send(make_sync_call=make_sync_call)    
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/api/mail.py", line 1209, in send      make_sync_call('mail', self._API_CALL, message, response)    
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/api/apiproxy_stub_map.py", line 96, in MakeSyncCall      return stubmap.MakeSyncCall(service, call, request, response)    
File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/appengine/api/apiproxy_stub_map.py", line 348, in MakeSyncCall      assert stub, 'No api proxy found for service "%s"' % service  AssertionError: No api proxy found for service "mail"

This seems to suggest that even for the default behavior of the mail service, some kind of proxy needs to be configured. However, I cannot find any information about the setup of this proxy. And, my initial understanding was that setting up a proxy is only needed for unit-testing or local development.

I just tested this and it worked for me (ie I received the email I supplied for recipient_email_address in the code below). Note that sender must be a value specified under Email Senders in App Engine settings page

requirements.txt file

Flask
appengine-python-standard>=1.0.0

app.yaml file

runtime: python39
app_engine_apis: true

handlers:

- url: /static
  static_dir: static/

- url: /.*
  script: auto

main.py

    from flask import Flask
    from google.appengine.api import wrap_wsgi_app
    from google.appengine.api.mail import send_mail

    app = Flask(__name__)
    app.wsgi_app = wrap_wsgi_app(app.wsgi_app)

    @app.route("/")
    def sendMail():
        
        
        send_mail(sender= <authorized_email_sender>,
                  to= <recipient_email_address>,
                  subject="Testing Python3 sending mails",
                    body="""Dear Albert:
    
                        Your example.com account has been approved.  You can now visit
                        http://www.example.com/ and sign in using your Google Account to
                        access new features.
    
                        Please let us know if you have any questions.
    
                        The example.com Team
                        """)

            return "Mail was sent"

Here is an example that works with fastapi.

from google.appengine.api import mail
from fastapi.middleware.wsgi import WSGIMiddleware
from google.appengine.api import wrap_wsgi_app
from flask import Flask

app = create_app() // this is just app = FastAPI() and somes  middleware but but no relevance here
app_flask = Flask(__name__)
app_flask.wsgi_app = wrap_wsgi_app(app_flask.wsgi_app, use_deferred=True)


def send_approved_mail(sender_address):
    # [START send_message]
    message = mail.EmailMessage(
        sender=sender_address,
        subject="Your account has been approved")

    message.to = "test@gmail.com"
    message.body = """Dear Albert:
Your example.com account has been approved.  You can now visit
http://www.example.com/ and sign in using your Google Account to
access new features.
Please let us know if you have any questions.
The example.com Team
"""
    message.send()

@app_flask.route("/send_email", methods=['GET'])
def send_email():
    send_approved_mail("registred_email@domain.com")
    return "message sent"


app.mount("/v1", WSGIMiddleware(app_flask))

here app.yaml

runtime: python39
entrypoint: gunicorn -k uvicorn.workers.UvicornWorker app.main:app
instance_class: F1
app_engine_apis: true
inbound_services:
- mail
- mail_bounce

You will not see flask route on swagger. and for some reason, i could not sent email with app engine's default service account. I had to register my email ( with same domain) here: https://console.cloud.google.com/appengine/settings/emailsenders?project=your_project

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM