Flask-Mail on Google App Engine Flexible ENV - python

I'm trying to get Flask-Mail setup on in Flexible ENV on Google App Engine. Flask-Mail works on my localhost using the credentials for a domain I am trying to use to send the mail. However, when using it on GAE through my API it returns a 502 error, however it shows no error messages in the logs or console. Going through the documentation for GAE Flexible it doesn't mention anything about NOT being able to use it, however it doesn't show how one would setup Flask-Mail either.
I have this..
mail = Mail()
print('1') // We Get here
msg = Message("Hello",
sender="me#mydomain.com",
recipients=["me#mydomain.com"])
print('2') // We get here
msg.body = 'Testing'
print('3') // We get here
mail.send(msg)
print('4') // This never gets call because I timeout on a 502 before this
I can tell I am not getting any fatal errors because the app stays working. However this fails with the 502. I have tried adding my email to the list of authorized senders but it doesn't seem to have helped.
I would appreciate any feedback. If I forced to use a 3rd party service to send mail it may cause me to move the project off of GAE.

As Ivan posted on his comment, to send email from a GAE app you need to use a mail service. Right now there are 3 options for apps on a flexible environment: Mailgun, MailJet and SendGrid. Choose the one you see better for your app.
After setting up an account on the mail service you have chosen, you have to prepare your code by integrating the parts related to the mail service.
These tutorials should help you establish the mail service for your app:
Mailgun
MailJet
SendGrid

I've had the same error but on a virtual machine on the internet ( linode service ) and it turned out that it has some thing to do with rDNS and some domain name config that you have to set up for your Ip address to get things working correctly , check this
https://www.linode.com/community/questions/19082/i-just-created-my-first-linode-and-i-cant-send-emails-why

Related

smtplib.SMTPNotSupportedError: SMTP AUTH extension not supported by server. Python

I am attempting to run a python script to automate sending emails but I keep running into this error.
Any suggestions on how to fix this?
import smtplib
from email import message
from_addr = 'myemail#gmail.com'
to_addr = 'myemail#gmail.com'
subject = 'Test Email'
body = 'Test'
msg = message.Message()
msg.add_header('from', from_addr)
msg.add_header('to', to_addr)
msg.add_header('subject', subject)
msg.set_payload(body)
server = smtplib.SMTP('smtp.gmail.com', 587)
server.login(from_addr, 'password')
The error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program `Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1264.0_x64__qbz5n2kfra8p0\lib\smtplib.py", line 716, in login`
raise SMTPNotSupportedError(
smtplib.SMTPNotSupportedError: SMTP AUTH extension not supported by server.
I'm not shure, but for gmail you need https://myaccount.google.com/lesssecureapps Allow less secure apps: ON setting.
Or you need Google APIs for authentication: https://developers.google.com/gmail/api/quickstart/python
I was having the same issue. Google recent ended support for "allow less secure apps" and the commonly recommended answer of using an app password also does not appear to work reliably either (it will work sometimes, but then gmail will start rejecting the authentication a day or two later).
Google's suggested quickstart guide (https://developers.google.com/gmail/api/guides/sending) is incomplete but does eventually work. In that process, you will get an error because you did not redirect the URI. You'll need to add this to the approved URIs within your google API console and then follow the link again.
You will hit a 2nd issue because your user will not be approved to use your own project. You will need to add your gmail account as a test user.
Once you have the URI forwarding correctly and you are approved to use your own app, you will then get an error (HTTP Error 403) because the Gmail API will not be activated. Go back to the google API console and enable the Gmail API. Finally, you can run the quickstart.py file again and it will complete without errors.
I have not yet tested this solution for actually sending email, but it does appear to grant your app full access to the email account that you set up. I also do not know if this is a long term solution or if there are tokens which will time out.
Based on the difficulty of this, it seems that finding another email SMTP service may be a better solution if that's possible for your situation.
You can get your app password to login your account via smtp. This solves the issue for less secure app feature.
Coming towards your error it might be due to something is not supported but here I see you have not started TLS connection. Starting TLS connection can solve this error if there's no other issue.
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(from_addr, 'password') # here you can need to use app password
This should solve the error most of the time if other things are correct.

How to send mails from gmail account using heroku?

I'm trying to build a simple app in python which sends emails if stock/crypto prices increase or decrease by x percent. I'm using yagmail to send these emails through a Gmail account. I have already tested the code locally and now I want to move it to Heroku. I have created GitHub secrets for the email addresses and for the Google App Password for yagmail's SMTP server and now I can deploy the app by connecting it to my Github repo. As far as I can tell it runs just fine, but the emails are not being sent.
I'm thinking that the problem stems from the Google App Password for yagmail's SMTP server, but I'm not sure. This is my first app so it could be that I'm missing something really basic.
Here is a simple code sample which is working on my desktop but not through Heroku:
SENDER_EMAIL = os.getenv("SENDER_EMAIL")
SENDER_APP_PASSWORD = os.getenv("SENDER_APP_PASSWORD")
RECEIVER_EMAIL = os.getenv("RECEIVER_EMAIL")
test_sub = "Test mail"
test_cont = "Test content"
with yagmail.SMTP(SENDER_EMAIL, SENDER_APP_PASSWORD) as yag:
yag.send(RECEIVER_EMAIL, test_sub, test_cont)
You need to define the configuration parameters (SENDER_EMAIL, SENDER_APP_PASSWORD, RECEIVER_EMAIL) as Config Vars.
They will be injected at runtime in your Heroku Dyno (on GitHubActions your secrets can be use for your GitHubActions pipeline for example) where you can grab them using Python os package.

Azure active directory SAML SSO configuration issue with Django backend

I am trying to set up SAML Single Sign-On (SSO) with my Django app, but I am getting an error when I try to login to my app.
I go to the app url, Microsoft processes the request (the url displays microsoft.loginonline.com/etc briefly), and then I get redirected to this page:
https://my-app.azurewebsites.net/.auth/login/aad/callback
which displays this error:
{"code":400,"message":"IDX10501: Signature validation failed. Unable to match keys: \nkid: '[PII is hidden]', \ntoken: '[PII is hidden]'."}
The reply url is set to:
https://my-app.azurewebsites.net/.auth/login/aad/callback
I did the set-up following both the Azure docs and following this documentation: https://django-auth-adfs.readthedocs.io, it's ostensibly working on my localhost, just not on the actual azure app service... I am unsure of what I am doing wrong, and the error message is not very informative for me as I am new to back-end programming and cloud.
Any help is appreciated, thanks!
As stated by you, you have configured SAML SSO with Django app in the backend and encountering the said error while logging in. As per the error reported, the ‘PII value is hidden’ due to which the signature keys couldn’t be validated by the AAD. So, you will need to add some strings to your ‘settings.py’ file to notify the Django web app the returned value of token from AAD. Please find the below strings to be added to the respective file: -
Please add the below string to AUTHENTICATION_BACKENDS section in ‘settings.py’ file.
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
After adding the above string to the said file, the app should work and so the SSO too.
Also, please find the below link to a similar thread for your reference: -
JWT token authentication fails with message "PII is hidden"
Thanks

appcfg.py shows You must be logged in as an administrator

When I try to upload a sample csv data to my GAE app through appcfg.py, it shows the below 401 error.
2015-11-04 10:44:41,820 INFO client.py:571 Refreshing due to a 401 (attempt 2/2)
2015-11-04 10:44:41,821 INFO client.py:797 Refreshing access_token
Error 401: --- begin server output ---
You must be logged in as an administrator to access this.
--- end server output ---
Here is the command I tried,
appcfg.py upload_data --application=dev~app --url=http://localhost:8080/_ah/remote_api --filename=data/sample.csv
This is how we do it in order to use custom authentication.
Custom handler in app.yaml
- url: /remoteapi.*
script: remote_api.app
Custom wsgi app in remote_api.py to override CheckIsAdmin
from google.appengine.ext.remote_api import handler
from google.appengine.ext import webapp
import re
MY_SECRET_KEY = 'MAKE UP PASSWORD HERE' # make one up, use the same one in the shell command
cookie_re = re.compile('^"?([^:]+):.*"?$')
class ApiCallHandler(handler.ApiCallHandler):
def CheckIsAdmin(self):
"""Determine if admin access should be granted based on the
auth cookie passed with the request."""
login_cookie = self.request.cookies.get('dev_appserver_login', '')
match = cookie_re.search(login_cookie)
if (match and match.group(1) == MY_SECRET_KEY
and 'X-appcfg-api-version' in self.request.headers):
return True
else:
self.redirect('/_ah/login')
return False
app = webapp.WSGIApplication([('.*', ApiCallHandler)])
From here we script the uploading of data that was exported from our live app. Use the same password that you made up in the python script above.
echo "MAKE UP PASSWORD HERE" | appcfg.py upload_data --email=some#example.org --passin --url=http://localhost:8080/remoteapi --num_threads=4 --kind=WebHook --filename=webhook.data --db_filename=bulkloader-progress-webhook.sql3
WebHook and webhook.data are specific to the Kind that we exported from production.
I had a similar issue, where appcfg.py was not giving me any credentials dialog, so I could not authenticate. I downgraded from GAELauncher 1.27 to 1.26, and the authentication started working again.
Temporary solution: go to https://console.developers.google.com/storage/browser/appengine-sdks/featured/ to get version 1.9.26
Submitted bug report: https://code.google.com/p/google-cloud-sdk/issues/detail?id=340
You cannot use the appcfg.py upload_data command with the development server [edit: as is; see Josh J's answer]. It only works with the remote_api endpoint running on App Engine and authenticated with OAuth2.
An easy way to load data into the dev server's datastore is to create an endpoint that reads a CSV file and creates the appropriate datastore entities, then hit it with the browser. (Be sure to remove the endpoint before deploying the app, or restrict access to the URL with login: admin.)
You must have an oauth token for a google account that is not an admin of that project. Try passing the --no_cookies flag so that it prompts for authentication again.
Maybe this has something to do with it? From the docs
Connecting your app to the local development server
To use the local development server for your app running locally, you
need to do the following:
Set environment variables. Add or modify your app's Datastore
connection code. Setting environment variables
Create an environment variable DATASTORE_HOST and set it to the host
and port on which the local development server is listening. The
default host and port is http://localhost:8080. (Note: If you use the
port and/or host command line arguments to change these defaults, be
sure to adjust DATASTORE_HOST accordingly.) The following bash shell
example shows how to set this variable:
export DATASTORE_HOST=http://localhost:8080 Create an environment
variable named DATASTORE_DATASET and set it to your dataset ID, as
shown in the following bash shell example:
export DATASTORE_DATASET= Note: Both the Python and Java
client libraries look for the environment variables DATASTORE_HOST and
DATASTORE_DATASET.
Link to Docs
https://cloud.google.com/datastore/docs/tools/devserver

Need to send a HTTP request in Python that'll authenticate with Google Accounts

I have an app which amounts to a Python script, running on the user's phone, and a JS client, running in the user's browser. The Python script sends messages to App Engine as HTTP requests. The server then pushes the messages to the JS client.
The problem is authentication: The server can easily use Google Accounts to authenticate anything coming from the JS client as being sent by a particular user, but I do not know how to get the Python script to make HTTP requests which will also authenticate.
Any ideas?
According to its homepage, httplib2 has support for Google Account authentication, maybe that may help you?
Can you use OAUth to authenticate with Google, then use the OAuth token to ensure the messages are legitimate?

Categories