Flask - OSError: [Errno 99] Невозможно назначить запрошенный адрес
Я пытаюсь создать стандартную функцию "забыть пароль" для своего веб-приложения. Проблема в том, что когда пользователь вводит свой адрес электронной почты и нажимает кнопку "Отправить", чтобы получить токен, после чего он может изменить свой пароль, страница просто продолжает загружаться, пока не появится следующее сообщение об ошибке:
This page isn’t working
{{ URL }} didn’t send any data.
ERR_EMPTY_RESPONSE
Я понимаю, что Flask-Mail отправляет электронные письма синхронно, поэтому, скорее всего, это проблема с подключением к Gmail. Я попытался включить "менее безопасный доступ к приложениям" в учетной записи, из которой я настроил почтовый объект, я также попытался изменить этот набор параметров конфигурации:
app.config['MAIL_SERVER'] = 'smtp.googlemail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('EMAIL_USER')
app.config['MAIL_PASSWORD'] = os.environ.get('EMAIL_PASS')
mail = Mail(app)
К этому:
app.config["MAIL_SERVER"] = "smtp.gmail.com"
app.config["MAIL_PORT"] = 465
app.config["MAIL_USE_TLS"] = False
app.config["MAIL_USE_SSL"] = True
app.config["MAIL_USERNAME"] = os.environ.get("EMAIL_USER")
app.config["MAIL_PASSWORD"] = os.environ.get("EMAIL_PASS")
mail = Mail(app)
который я видел в Интернете, но ничего из этого не сработало.
Вот соответствующие маршруты и методы:
# Generate password reset token unique to user
def get_reset_token(current_user, expires_sec=1800):
s = Serializer(app.config["SECRET_KEY"], expires_sec)
return s.dumps({"user_id": current_user}).decode("utf-8")
# Send reset email
def send_reset_email(user):
rows = db.execute("SELECT * FROM users WHERE id = :current_user", current_user = user)
user_email = rows[0]["email"]
token = get_reset_token(user)
msg = Message("Password Reset Request", sender = "noreply@demo.com", recipients = [user_email])
msg.body = f"""To reset your password, visit the following link:
{url_for('new_password', token = token, _external = True)}
If you did not make this request simply ignore this email and no changes will be made.
"""
mail.send(msg)
@app.route("/reset", methods=["GET", "POST"])
def reset():
if request.method == "GET":
return render_template("reset.html")
else:
email = request.form.get("email")
# Check email exists in database
check_email = db.execute("SELECT * FROM users WHERE email = :email", email = email)
if len(check_email) != 1:
return apology("You must enter the email address you registered with", 403)
else:
user = check_email[0]["id"]
send_reset_email(user)
flash("An email has been sent with instructions to reset your password")
return render_template("login.html")
Что касается отладки, то пробовал запускать приложение без
mail.send(msg)
и все работало нормально, за исключением отправленного электронного письма, очевидно, подразумевая, что проблема действительно в отправляемом электронном письме. Кроме того, я попытался удалить
token = get_reset_token(user)
функция, чтобы узнать, была ли проблема в этом, но проблема не исчезла.
С терминала кажется, что приложение попадает в
check_email = db.execute("SELECT * FROM users WHERE email = :email", email = email)
после того, как электронное письмо отправлено без проблем, после чего оно просто продолжает загружаться, пока не истечет время ожидания.
* Изменить: это сообщение об ошибке терминала, когда время ожидания страницы истекает.
ERROR:application:Exception on /reset [POST]
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/ubuntu/pset8/finance/application.py", line 227, in reset
send_reset_email(user)
File "/home/ubuntu/pset8/finance/application.py", line 211, in send_reset_email
mail.send(msg)
File "/home/ubuntu/.local/lib/python3.7/site-packages/flask_mail.py", line 491, in send
with self.connect() as connection:
File "/home/ubuntu/.local/lib/python3.7/site-packages/flask_mail.py", line 144, in __enter__
self.host = self.configure_host()
File "/home/ubuntu/.local/lib/python3.7/site-packages/flask_mail.py", line 156, in configure_host
host = smtplib.SMTP_SSL(self.mail.server, self.mail.port)
File "/usr/local/lib/python3.7/smtplib.py", line 1031, in __init__
source_address)
File "/usr/local/lib/python3.7/smtplib.py", line 251, in __init__
(code, msg) = self.connect(host, port)
File "/usr/local/lib/python3.7/smtplib.py", line 336, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "/usr/local/lib/python3.7/smtplib.py", line 1037, in _get_socket
self.source_address)
File "/usr/local/lib/python3.7/socket.py", line 728, in create_connection
raise err
File "/usr/local/lib/python3.7/socket.py", line 716, in create_connection
sock.connect(sa)
OSError: [Errno 99] Cannot assign requested address
INFO:werkzeug:192.168.239.121 - - [15/Oct/2020 18:28:12] "POST /reset HTTP/1.0" 500 -
Это подтверждает, что последняя вызванная строка кода была
mail.send(msg)