python - (typo, closed) flask-mail google SSL " smtplib.SMTPServerDisconnected: Connection unexpectedly closed &quo

admin2025-04-17  2

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 :(

转载请注明原文地址:http://anycun.com/QandA/1744824801a88131.html