#python-3.x #firebase #heroku #flask #cors
#python-3.x #firebase #heroku #flask #cors
Вопрос:
Я десятки часов пытался выяснить, почему приложение выдает ошибку CORS (совместное использование ресурсов разных источников)
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.
Хотя я добавил CORS в свое серверное приложение и он отлично работает на локальном хостинге для тестирования. Как только я развертываю как интерфейс, так и серверную часть на серверах размещения, я получаю ошибку CORS. Что более интересно, это относится только к /retrieve_email
пути, но работает на login
— хотя для обоих путей требуется CORS. /
Путь работает нормально, он отображает JSON
из него, который я также тестировал с помощью 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)
Выше приведен фрагмент моего кода с использованием CORS. Пожалуйста, не смейтесь над структурой кода, это первый раз, когда используется API и используются запросы GET и POST. Интерфейс (Angular) размещен на Firebase, серверная часть (Flask) размещена на Heroku.
РЕДАКТИРОВАТЬ 1: Я запустил heroku logs --tail
, в основном просто просматривая некоторые журналы через терминал, вот что я получил:
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
Ниже приведен код для функции email_receive():
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 = 'xxxxxxxx@gmail.com'
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
Ответ №1:
попробуйте это:
from flask_cors import cross_origin
затем добавьте декоратор @cross_origin() в свой маршрут api следующим образом
@app.route('/', methods=['GET'])
@cross_origin()
def index():
...
Комментарии:
1. HttpErrorResponse {заголовки: HttpHeaders, статус: 500, statusText: «ВНУТРЕННЯЯ ОШИБКА СЕРВЕРА», URL: » email-client-live.herokuapp.com/retrieve_email «, ok: false, …} Я предполагаю, что проблема с хостинговым сервером Heroku, потому что собираюсь api-client.herokuapp.com возвращает json, но api-client.herokuapp.com/retrieve_email выдает ошибку, упомянутую выше. Я пытаюсь получить электронные письма из gmail, используя IMAP, поэтому мне интересно, является ли проблемой проверка учетных данных (информация для входа).
2. Я также пытался получить доступ к api-client.herokuapp.com/retrieve_email URL через среду разработки выдает ту же ошибку. Хотя api-client.herokuapp.com/login отлично работает как в реальных средах, так и в средах разработки.
3. Tbh, я думаю, что декоратор @cross_origin вызывает больше проблем. Изменение маршрута возврата для / retrieve_email на jsonify({‘key’: ‘value’}) больше не работает (я тестировал это с Postman). Удаление декоратора устраняет проблему.
4. @ElonasMarkauskas, ошибка 500 — это что-то не так в ваших кодах, вы получили ошибку интервала, затем она выдает ошибку 500. Итак, я предлагаю вам проверить этот метод email_test.email_receive() 1st (одна из причин, которая может вызвать эту ошибку, заключается в том, что Gmail блокирует ваш сервер как доступ третьей стороны по соображениям безопасности). Что касается декоратора, я использую этот декоратор для своего проекта, и пока у меня нет никаких ошибок по этому поводу. Для jsonify это просто метод, который преобразует ваш ответ в формат json (например, json.dumps), но с соответствующим заголовком типа содержимого ‘application / json’ для использования с ответами json.
5. Хорошо, я посмотрю на код, я опубликую его, как только у меня будет такая возможность. У меня возникли проблемы с Gmail, блокирующим мое соединение и получение электронных писем.