![](/img/trans.png)
[英]python requests: (SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)'))
[英]Flask-Mail [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)
我正在開發一個實現用戶注冊系統的 Flask 應用程序。 該應用程序使用 Flask-Mail 和 itsdangerous 來確認用戶的注冊並通過 email 重置他們的密碼。 我將 Flask-Mail 配置為使用我正在使用的 email 主機提供的推薦服務器設置。
MAIL_PORT = 587
MAIL_USE_SSL = False
MAIL_USE_TLS = True
起初,一切正常。 我可以毫無問題地提交電子郵件。 但是,似乎沒有更改任何配置設置,我現在在嘗試使用 Flask-Mail 提交 email 時收到以下錯誤:
[SSL: WRONG_VERSION_NUMBER] 錯誤的版本號 (_ssl.c:1123)
我不確定問題出在哪里,我想知道 email 提供商端是否發生了變化? 我嘗試使用MAIL_USE_SSL=False
和MAIL_USE_TLS=False
設置MAIL_PORT = 25
; 並且, MAIL_PORT = 465
,同時MAIL_USE_SSL=True
和MAIL_USE_TLS=False
。 使用前者,我收到與端口 587 相同的錯誤,但使用后者我收到STARTTLS extension not supported by server.
我在 localhost:5000 以開發模式運行 Flask 應用程序。 這是我的一些配置設置和代碼:
配置文件
SECRET_KEY = 'verysecret'
MAIL_SERVER = "smtp.mymailservice.com"
MAIL_PORT = 587
MAIL_USE_SSL = False
MAIL_USE_TLS = True
MAIL_USERNAME = "myemail@myhostname.com"
MAIL_PASSWORD = "mypassword"
MAIL_DEFAULT_SENDER = 'Brand <noreply@myhostname.com>'
應用程序/mailing.py
from flask_mail import Message
from flask import current_app
from .extensions import mail
def send_email(to, subject, template):
msg = Message(
subject,
recipients=[to],
html=template,
sender=current_app.config["MAIL_DEFAULT_SENDER"]
)
mail.send(msg)
應用程序/用戶/routes.py
(我收到錯誤的路線之一)
from flask import (
render_template, session, request, redirect, url_for, g, jsonify, flash
)
import uuid
from passlib.hash import sha256_crypt
from app.mailing import send_email
from app.extensions import db
from app.users import bp
from app.users.forms import *
from app.users.models import *
from app.users.token import *
@bp.route('/register', methods=['POST', 'GET'])
def register():
# Initialize the Register Form
form = RegisterForm()
# If the submitted form is valid
if form.validate_on_submit():
# Check to see if a user already exists with this email address
user = User.query.filter_by(email=form.email.data).first()
# If there is not a user with this email address, create a new user
if not user:
new_user = User(public_id=str(uuid.uuid4()),
email=form.email.data,
password=sha256_crypt.encrypt(
(form.password.data)),
first_name=form.firstname.data,
last_name=form.lastname.data
)
db.session.add(new_user)
db.session.commit()
token = generate_confirmation_token(new_user.email)
confirm_url = url_for("users.confirm_email",
token=token, _external=True)
html = render_template('confirm_email.html',
confirm_url=confirm_url)
subject = "Please confirm your email"
try:
send_email(new_user.email, subject, html)
flash("A confirmation email has been sent to you. Please verify your email address to activate your account.", category="success")
except Exception as e:
flash(
"There was a problem sending the confirmation email. Please try again later.", category="danger")
print(e)
session["user_id"] = new_user.public_id
session["email"] = new_user.email
session["name"] = new_user.first_name
flash("Thanks for registering!", category="success")
return redirect(url_for('users.unconfirmed'))
else:
flash("There is already an account associated with this email address. Log in, or use a different email address.")
return render_template("register_user.html", form=form)
應用程序/擴展程序.py
from flask_mail import Mail
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
bootstrap = Bootstrap()
mail = Mail()
應用程序/初始化.py
from flask import Flask
from config import Config, DevelopmentConfig
from .errors import (
page_not_found, forbidden, internal_server_error
)
from .extensions import (
db, mail, bootstrap
)
def create_app(config_class=DevelopmentConfig):
app = MyFlask(__name__)
# Set Configuration
app.config.from_object(config_class)
# Register extensions
# Initialize Boostrap-Flask
bootstrap.init_app(app)
# Initialize Flask-SQLAlchemy
db.init_app(app)
# Initialize Flask-Mail
mail.init_app(app)
# Register error views
app.register_error_handler(404, page_not_found)
app.register_error_handler(403, forbidden)
app.register_error_handler(500, internal_server_error)
with app.app_context():
# register blueprints
from app.main import bp as bp_main
app.register_blueprint(bp_main)
from app.users import bp as bp_users
app.register_blueprint(bp_users)
return app
這個答案幾乎就在那里,但對我來說並不完全。 更多 TL:DR。
把它放在你的config.py
文件中,忘記 rest...
class Config:
MAIL_USE_TLS = True
MAIL_USE_SSL = False
更多細節...
您可能有一個如下所示的config.py
文件:
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY')
SQLALCHEMY_DATABASE_URI = 'sqlite:///site.db' # os.environ.get('DATABASE_URI')
MAIL_SERVER = os.environ.get('MAIL_SERVER')
MAIL_PORT = os.environ.get('MAIL_PORT')
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS')
MAIL_USE_SSL = os.environ.get('MAIL_USE_SSL')
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
MAIL_DEFAULT_SENDER = os.environ.get('MAIL_DEFAULT_SENDER')
然后你認為你可以在你的 VSCode 調試配置或你的服務器環境中有這樣的東西:
"env": {
"MAIL_USE_SSL":"true",
"MAIL_USE_TLS":"true",
好吧,由於@serrobit 的回答,這不起作用,因為 VSCode 中的“true”變成了str
而不是 Python True
。
回到開頭,在 config.py 文件中將 TLS 硬編碼為 True,將 SSL 硬編碼為 False,go 將時間花在有用的東西上。
我弄清楚發生了什么事。 顯然,在從 Flask-Mail 初始化 Mail object 時,您可以為 MAIL_USE_TLS 和 MAIL_USE_SSL 傳入非布爾類型。 當 Connection object 調用 configure_host() 並有條件地檢查if self.mail.use_ssl
時,這將成為一個問題。
因此,只要self.mail.use_ssl
不是None
,該方法就會設置host = smtplib.SMTP_SSL(self.mail.server, self.mail.port)
,在我的情況下,這會導致 [SSL: WRONG_VERSION_NUMBER] 錯誤版本號 (_ssl.c:1123) 因為mail.port
設置為 587。
tl;dr 確保您的 Flask 應用程序的配置變量設置為適當的類型,尤其是在您使用環境變量時,因為當通過 os.environ dict 訪問它們時,它們將始終為 str 類型。
燒瓶郵件.py
class Connection(object):
"""Handles connection to host."""
def __init__(self, mail):
self.mail = mail
def __enter__(self):
if self.mail.suppress:
self.host = None
else:
self.host = self.configure_host()
self.num_emails = 0
return self
def __exit__(self, exc_type, exc_value, tb):
if self.host:
self.host.quit()
def configure_host(self):
## PROBLEM OCCURRED HERE BECAUSE type(self.mail.use_ssl) = <class 'str'> ##
if self.mail.use_ssl:
host = smtplib.SMTP_SSL(self.mail.server, self.mail.port)
else:
host = smtplib.SMTP(self.mail.server, self.mail.port)
host.set_debuglevel(int(self.mail.debug))
if self.mail.use_tls:
host.starttls()
if self.mail.username and self.mail.password:
host.login(self.mail.username, self.mail.password)
return host
在你的config.py
中改變它:
class Config:
MAIL_USE_TLS = bool(strtobool(os.environ.get('MAIL_USE_TLS', 'False')))
MAIL_USE_SSL = bool(strtobool(os.environ.get('MAIL_USE_SSL', 'False')))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.