Я пишу небольшое веб-приложение на основе Flasky Мигеля Гринберга. Я использую точно такой же код для отправки пользователем почты для сброса пароля с помощью gmail.
В качестве моего файла email.py здесь я могу реализовать функцию отправки почты.
def send_password_reset_email(user):
token = user.get_reset_password_token()
send_email(_('[Microblog] Reset Your Password'),
sender=current_app.config['ADMINS'][0],
recipients=[user.email],
text_body=render_template('email/reset_password.txt',
user=user, token=token),
html_body=render_template('email/reset_password.html',
user=user, token=token))
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
def send_email(subject, sender, recipients, text_body, html_body):
msg = Message(subject, sender=sender, recipients=recipients)
msg.body = text_body
msg.html = html_body
Thread(target=send_async_email,
args=(current_app._get_current_object(), msg)).start()
В файле route.py я получаю электронное письмо от пользователя, и если адрес электронной почты пользователя совпадает, я отправляю токен пользователю по почте.
@bp.route('/reset_password_request', methods=['GET', 'POST'])
def reset_password_request():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = ResetPasswordRequestForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user:
send_password_reset_email(user)
flash(
_('Check your email for the instructions to reset your password'))
return redirect(url_for('auth.login'))
return render_template('auth/reset_password_request.html',
title=_('Reset Password'), form=form)
@bp.route('/reset_password/<token>', methods=['GET', 'POST'])
def reset_password(token):
if current_user.is_authenticated:
return redirect(url_for('main.index'))
user = User.verify_reset_password_token(token)
if not user:
return redirect(url_for('main.index'))
form = ResetPasswordForm()
if form.validate_on_submit():
user.set_password(form.password.data)
db.session.commit()
flash(_('Your password has been reset.'))
return redirect(url_for('auth.login'))
return render_template('auth/reset_password.html', form=form)
В файле model.py в модели пользователя я создаю токен для пользователя, а также проверяю токен пользователя.
def get_reset_password_token(self, expires_in=600):
return jwt.encode(
{'reset_password': self.id, 'exp': time() + expires_in},
current_app.config['SECRET_KEY'],
algorithm='HS256').decode('utf-8')
@staticmethod
def varify_reset_password_token(token):
try:
id = jwt.decode(token, current_app.config['SECRET_KEY'],
algorithms=['HS256'])['reset_password']
except:
return
return User.query.get(id)
моя настройка фляжной почты выглядит следующим образом: файл config.py
MAIL_SERVER = os.environ.get('MAIL_SERVER')
MAIL_PORT = int(os.environ.get('MAIL_PORT') or 25)
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
ADMINS =['[email protected]']
Следующая ошибка, которую я получаю в терминале
Traceback (most recent call last):
File "c:\python38\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "c:\python38\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Ijaz Bacha\project\microblog1\app\email.py", line 9, in send_async_email
mail.send(msg)
File "c:\users\ijaz bacha\project\microblog1\venv\lib\site-packages\flask_mail.py", line 492, in send
message.send(connection)
File "c:\users\ijaz bacha\project\microblog1\venv\lib\site-packages\flask_mail.py", line 152, in __exit__
self.host.quit()
File "c:\python38\lib\smtplib.py", line 988, in quit
res = self.docmd("quit")
File "c:\python38\lib\smtplib.py", line 424, in docmd
self.putcmd(cmd, args)
File "c:\python38\lib\smtplib.py", line 371, in putcmd
self.send(str)
File "c:\python38\lib\smtplib.py", line 363, in send
raise SMTPServerDisconnected('please run connect() first')
smtplib.SMTPServerDisconnected: please run connect() first
По моему опыту, некоторое время назад у меня была очень похожая проблема, с которой вы столкнулись. После устранения неполадок я обнаружил, что мой код работает, когда я создаю почтовый класс и вызываю функцию, например $mailclass.ehlo и т. д.
Судя по ошибке, возникают проблемы с подключением или сохранением подключения. Попробуйте вызывать методы подключения в самой функции и закрывать соединение после каждого письма.
Я также делаю тот же учебник и столкнулся с той же проблемой. Я нашел ответ в Блоге Мигеля:
Вам нужно два окна терминала. Первый терминал, на котором запущен ваш локальный почтовый сервер, который эмулирует отправку ваших писем:
$(venv) python -m smtpd -n -c DebuggingServer localhost:8025
Главное окно терминала фляги со следующими обязательными командами (FLASK_DEBUG=1 не является обязательным, но настоятельно рекомендуется для устранения неполадок):
$ export FLASK_APP=microblog.py
$ export FLASK_DEBUG=1
$ export MAIL_SERVER=localhost
$ export MAIL_PORT=8025
$ flask run
Это решило мои проблемы.
Я решил изменить следующую строку в файле app/__init__.py
:
mail = Mail(app)
с:
mail = Mail()
mail.init_app(app)
Решил проблему для меня
Сэр, спасибо за комментарий, можете ли вы дать мне какую-нибудь подсказку или определить для меня функцию подключения?