Ad

Flask CORS Not Working On Live Deployment

- 1 answer

I have been struggling for dozens of hours trying to figure out why is the application producing a CORS (Cross Origin Resource Sharing) error

Access to XMLHttpRequest at 'https://api-client.herokuapp.com/retrieve_email' from origin 'https://front-application.firebaseapp.com' has been blocked by 
CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Although I have added CORS to my backend application and works perfectly on the localhost for testing. Once I deploy both the front end and backend to hosting servers, I get the CORS error. What is more interesting it only applies to the /retrieve_email path, but works on the login - both paths require CORS though. The / path works fine, it displays the JSON from it, which I also tested using Postman.

from flask import Flask, jsonify, request
from flask_cors import CORS
from email_receive import EmailReceive
from email_send import EmailSend


app = Flask(__name__)
CORS(app)

email_test = EmailReceive()


@app.route('/', methods=['GET'])
def index():
    return jsonify({'key': 'value'})


@app.route('/retrieve_email', methods=['GET'])
def retrieve_email():
    if request.method == 'GET':
        email_test.email_receive()
        return jsonify(email_test.get_email_data())


@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        data = request.get_json()
        email_test.set_credentials(data)
        return jsonify(data)
    elif request.method == 'GET':
        return jsonify(email_test.get_email_data())


@app.route('/send_email', methods=['POST', 'GET'])
def send_email():
    sending = EmailSend()
    if request.method == 'POST':
        data = request.get_json()
        sending.set_information(data)
        sending.email_send()
        return jsonify(data)
    elif request.method == 'GET':
        return jsonify({'key': 'value'})


if __name__ == '__main__':
    app.run(debug=True)

Above is a snippet of my code using CORS. Please don't laugh at the structure of the code, this is the first time using an API and using GET, and POST requests. Frontend(Angular) is hosted on Firebase, backend(Flask) hosted on Heroku.

EDIT 1: I ran heroku logs --tail, basically just looking at some logs through the terminal, the following is what I got:

2019-03-14T19:03:35.999761+00:00 app[web.1]: [2019-03-14 19:03:35,999] ERROR in app: Exception on /retrieve_email [GET]
2019-03-14T19:03:35.999772+00:00 app[web.1]: Traceback (most recent call last):
2019-03-14T19:03:35.999774+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
2019-03-14T19:03:35.999776+00:00 app[web.1]: response = self.full_dispatch_request()
2019-03-14T19:03:35.999778+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
2019-03-14T19:03:35.999779+00:00 app[web.1]: rv = self.handle_user_exception(e)
2019-03-14T19:03:35.999780+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask_cors/extension.py", line 161, in wrapped_function
2019-03-14T19:03:35.999782+00:00 app[web.1]: return cors_after_request(app.make_response(f(*args, **kwargs)))
2019-03-14T19:03:35.999783+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
2019-03-14T19:03:35.999785+00:00 app[web.1]: reraise(exc_type, exc_value, tb)
2019-03-14T19:03:35.999787+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
2019-03-14T19:03:35.999790+00:00 app[web.1]: raise value
2019-03-14T19:03:35.999791+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
2019-03-14T19:03:35.999793+00:00 app[web.1]: rv = self.dispatch_request()
2019-03-14T19:03:35.999794+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
2019-03-14T19:03:35.999796+00:00 app[web.1]: return self.view_functions[rule.endpoint](**req.view_args)
2019-03-14T19:03:35.999798+00:00 app[web.1]: TypeError: decorator() missing 1 required positional argument: 'f'
2019-03-14T19:03:36.001321+00:00 app[web.1]: 10.45.158.146 - - [14/Mar/2019:19:03:35 +0000] "GET /retrieve_email HTTP/1.1" 500 291 "-" "PostmanRuntime/7.6.0"
2019-03-14T19:03:36.063632+00:00 heroku[router]: at=info method=GET path="/retrieve_email" host=email-client-live.herokuapp.com request_id=3dd5bc4a-0f57-4a82-b5f7-1bcccc64f263 fwd="73.210.197.125" dyno=web.1 connect=1ms service=73ms status=500 bytes=488 protocol=https

The following is the code for the email_receive() function:

import email
import email.header
import imaplib
import sys


class EmailReceive:
    imap_host = ''
    imap_user = ''
    imap_pass = ''

    email_package = []

    def __init__(self):
        self.imap_host = 'imap.gmail.com'
        self.imap_user = '[email protected]'
        self.imap_pass = 'xxxxxxxxxx'

    def set_credentials(self, data):
        self.imap_user = data['email']
        self.imap_pass = data['password']

    def email_receive(self):
        self.email_package = []
        email_instance = imaplib.IMAP4_SSL(self.imap_host)

        try:
            print(self.imap_user, self.imap_pass)
            rv, data = email_instance.login(self.imap_user, self.imap_pass)
        except imaplib.IMAP4.error:
            print('[*] email_receive.py: LOGIN FAILED')
            sys.exit(1)

        print(rv, data)

        rv, data = email_instance.list()
        if rv == 'OK':
            print('Mailboxes: ')
            print(data)

        rv, data = email_instance.select('Inbox')
        if rv == 'OK':
            print('Processing mailbox...')
            print(data)

        rv, data = email_instance.search(None, 'ALL')
        if rv != 'OK':
            print('[*] email_receive.py: No messages found!')
            return

        for num in data[0].split():
            rv, data = email_instance.fetch(num, '(RFC822)')
            if rv != 'OK':
                # print('[*] email_receive.py: ERROR getting message', num)
                return

            # print(data[0][1])

            message = email.message_from_bytes(data[0][1])
            subject = email.header.make_header(email.header.decode_header(message['Subject']))
            # print(message.keys())
            message_id = message['Message-ID']

            # print(header)
            sender = message['From']

            for part in message.walk():
                if part.get_content_type() == 'text/html':
                    self.email_package.append({'body': part.get_payload(decode=True).decode('utf-8'),
                                               'subject': str(subject),
                                               'from': str(sender),
                                               'messageid': str(message_id)})

    def get_email_data(self):
        return self.email_package
Ad

Answer

try this:

from flask_cors import cross_origin

then add @cross_origin() decorator to your api route like this

@app.route('/', methods=['GET'])
@cross_origin()
def index():
    ...
Ad
source: stackoverflow.com
Ad