So, now that I added SSL instead of TLS there's at least some progress, but it still doesn't work.
I click the button, it processes for a 5-10 seconds and I get the error that connection unexpectedly closed.
python version is 3.12.4
init.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
from flask_mail import Mail
app = Flask(__name__)
SECRET_KEY = "SECRET_KEY"
app.config["SECRET_KEY"] = SECRET_KEY
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///site.db"
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = "login"
login_manager.login_message_category = "danger"
app.config["MAIL_SERVER"] = "smtp.gmail"
app.config["MAIL_PORT"] = 465
# tls is 587, ssl is 465
app.config["MAIL_USER_TLS"] = False
app.config["MAIL_USER_SSL"] = True
app.config["MAIL_USERNAME"] = "myemail"
app.config["MAIL_PASSWORD"] = "myapppassword"
mail = Mail(app)
.
routes.py
from myapp import app, db, bcrypt, mail
from myapp.forms import (RegistrationForm, LoginForm, UpdateAccountForm, PostForm, SearchForm, RequestResetForm,
ResetPasswordForm)
from flask import render_template, redirect, flash, url_for, request
from myapp.models import Post, User
from flask_login import login_user, current_user, logout_user, login_required
import secrets
import os
from PIL import Image
from sqlalchemy import desc, asc, select
from flask_mail import Message
def send_reset_email(user):
token = user.get_reset_token()
msg = Message(subject="Password Reset Request", sender="[email protected]", recipients=[user.email])
msg.body = f"""To reset your password, visit the following link
{url_for("reset_token", token=token, _external=True)}
If you did not make this request, then simply ignore this email.
"""
mail.send(msg)
@app.route("/reset_password", methods=["GET", "POST"])
def reset_request():
if current_user.is_authenticated:
flash("You already are authenticated. Please log out in order to get to that page.", "info")
return redirect(url_for("home"))
request_form = RequestResetForm()
if request_form.validate_on_submit():
user = User.query.filter_by(email=request_form.email.data).first()
send_reset_email(user)
flash("An email has been sent with instructions to reset the password.", "info")
return redirect(url_for("login"))
return render_template("reset_request.html", title="Reset Password", request_form=request_form)
@app.route("/reset_password/<token>", methods=["GET", "POST"])
def reset_token(token):
if current_user.is_authenticated:
flash("You already are authenticated. Please log out in order to get to that page.", "info")
return redirect(url_for("home"))
user = User.verify_reset_token(token)
if user is None:
flash("That is an invalid or expired token", "warning")
return redirect(url_for("reset_request"))
reset_form = ResetPasswordForm()
if reset_form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(reset_form.password.data).decode("utf-8")
user.password = hashed_password
db.sessionmit()
flash(f"Your password has been updated", "info")
return redirect(url_for('login'))
return render_template("reset_token.html", title="Reset Password", reset_form=reset_form)
.
models.py
from myapp import db, login_manager, app
from datetime import datetime, timezone
from flask_login import UserMixin
from itsdangerous import URLSafeTimedSerializer as Serializer
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default="default.jpg")
password = db.Column(db.String(60), nullable=False)
posts = db.relationship("Post", backref="author", lazy="subquery")
def get_reset_token(self, expires_sec=300):
s = Serializer(app.config["SECRET_KEY"], "salty")
return s.dumps({'user_id': self.id})
@staticmethod
def verify_reset_token(token):
s = Serializer(app.config["SECRET_KEY"])
try:
user_id = s.loads(token)["user_id"]
except:
return None
return User.query.get(user_id)
def __repr__(self):
return f"User('id={self.id}', '{self.username}', '{self.email}', '{self.image_file}')"
and in the html page I just enter the email I want the message to be sent to.
The error after 5-10 second wait:
File "-\venv\Lib\site-packages\flask\app.py", line 1536, in __call__
return self.wsgi_app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "-\venv\Lib\site-packages\flask\app.py", line 1514, in wsgi_app
response = self.handle_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^
File "-\venv\Lib\site-packages\flask\app.py", line 1511, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "-\venv\Lib\site-packages\flask\app.py", line 919, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "-\venv\Lib\site-packages\flask\app.py", line 917, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "-\venv\Lib\site-packages\flask\app.py", line 902, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "-\routes.py", line 155, in reset_request
send_reset_email(user)
File "-\bungee_gum\routes.py", line 142, in send_reset_email
mail.send(msg)
File "-\venv\Lib\site-packages\flask_mail\__init__.py", line 539, in send
with self.connect() as connection:
File "-\venv\Lib\site-packages\flask_mail\__init__.py", line 127, in __enter__
self.host = self.configure_host()
^^^^^^^^^^^^^^^^^^^^^
File "-\venv\Lib\site-packages\flask_mail\__init__.py", line 144, in configure_host
host = smtplib.SMTP(self.mail.server, self.mail.port)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "-\AppData\Local\Programs\Python\Python312\Lib\smtplib.py", line 255, in __init__
(code, msg) = self.connect(host, port)
^^^^^^^^^^^^^^^^^^^^^^^^
File "-\AppData\Local\Programs\Python\Python312\Lib\smtplib.py", line 343, in connect
(code, msg) = self.getreply()
^^^^^^^^^^^^^^^
File "-\AppData\Local\Programs\Python\Python312\Lib\smtplib.py", line 405, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
What might be the problem? Before, when I was using TLS, the error was something like server refused to connect, now it's this. The port seems to be correct, 465 for SSL. MAIL_USERNAME is my email address, MAIL_PASSWORD is the app password for a newly created app in google "App passwords". My google account should be fine since I used this app email stuff a while ago.
p.s. I just made a typo in app.config["MAIL_USER_TLS"] because it should've been MAIL_USE_TLS instead. Though something is wrong with my token stuff still. sorry for your time if you tried to help :(