学习狗书flask web开发,没有报错,但是收不到邮件(第二弹)------TESTING = False 变量配置大坑!

上一篇文章,好不容易解决了跳转链接报错的问题,点了click here后,弹出顶部提醒:A new confirmation email has been sent to you.…但是,查看邮箱,垃圾邮件里面都看了好几遍,翻烂了都没看见邮件!
在这里插入图片描述

之前新用户注册,自动给管理员发送邮件,却收不到邮件,是因为pycharm读不到环境变量:上次收不到邮件的全过程记录
这次是代码重构以后,需要用户验证,又收不到邮件了


  • 检查了邮箱开启SMTP服务

  • 为重构后的启动文件flasky.py在Run -> Edit Configurations -> Environment variables重新配置MAIL_USERNAME等等信息

  • 检查了confirmed字段的默认值和类型,期间还弄清楚了pycharm的SQLite界面Boolean类型的操作,横线表示FALSE,√表示TRUE,空的表示还没定义。若需要直接在数据库中更改,在更改处点击右键,-Edit,更改完后,再右键-Submit才算成功
    在这里插入图片描述

  • 检查了代码拼写错误、捋顺逻辑

全部都没问题。邮件发不出去,肯定是邮件那部分的问题。
打印了send_email函数的各个变量,也没问题,那为什么一切准备就绪,就是不发邮件呢?

各种花式描述问题,最终在Stack Overflow上找到了答案 Flask-Mail not sending emails, no error is being reported

应该设置TESTING = False !想起来了,我就是在config.py中默认用的这个

config = {

	 ......
	
   	'default': TestingConfig
}

而TestingConfig中这个字段我设置的是True :

class TestingConfig(Config):
    TESTING = True  # 不发送邮件
    SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or 'sqlite://'
 

TESTING = True 就是默认不发送邮件,怪不得一直收不到。
改成False,这下肯定会成功了!!!!!


但是,现在又报了验证错误?????
在这里插入图片描述
之前用的时候MAIL_USERNAME 和 MAIL_PASSWORD 是有效的呀?难道由于时间太长失效了?
于是从网上找了一篇demo,测试了一下这俩参数的有效性:

from flask import Flask
from flask_mail import Mail, Message

app = Flask(__name__)

mail_config = {
    "MAIL_SERVER": "smtp.163.com",
    "MAIL_PORT": 465,
    "MAIL_USE_SSL": True,
    "MAIL_USERNAME": "xxx@163.com", # 发送邮箱
    "MAIL_PASSWORD": "这里填你的授权码" # 客户端授权码
}

app.config.update(mail_config)

mail = Mail(app)

@app.route("/send_mail")
def send_mail():
    """
    发送邮件
    """
    message = Message("标题", sender=app.config["MAIL_USERNAME"], recipients=["xxx@163.com"])
    message.body = "内容"
    mail.send(message)
    print(message.sender,message.recipients)
    return "发送成功"


if __name__ == "__main__":
    app.run()

测试了两遍,都收到了邮件
在这里插入图片描述

说明我这两个环境变量是有效的,那问题在哪儿?

算了,我不沾惹TESTING这个参数了,我把默认config换成DevelopmentConfig算了,去config.py 中设置:

config = {

	 ......
	
   	'default': DevelopmentConfig
}

class DevelopmentConfig(Config):
    DEBUG = True
     # 注意!!!注意!!
     # TestingConfig 和 DevelopmentConfig 千万不能用同一个数据库!!!
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')
 

这下应该成功了吧!!!
但是,跟上面一模一样地报了验证错误???
在这里插入图片描述

为什么???!!!
继续去Stack Overflow上看看
找到了这篇Flask-Mail Cannot read configurations when config.from_object() is used

跟着答案在config.py更新了我的配置参数,重要的是,为了方便,直接把用户名,授权码贴了上去,而不是从环境中读取

    # MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
    # MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
    MAIL_USERNAME = 'xxx@163.com'
    MAIL_PASSWORD = '这里填授权码'

然后,竟然成功了!!!!

在这里插入图片描述

看着还挺像那么一回事儿哈哈哈哈哈哈哈

讲道理TestingConfig也不应该有问题,我把配置文件又改回 TestingConfig,注意TESTING = False

config = {

	 ......
	
   	'default': TestingConfig
}
class TestingConfig(Config):
    TESTING = False  # 注意这里改成 False才能发送邮件
     # 注意!!!注意!!
     # TestingConfig 和 DevelopmentConfig 千万不能用同一个数据库!!!
    SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or 'sqlite://'

竟然也成功了!!!!!


说明我一开始改 TESTING = False 理论上就能解决问题了 T^T

但还是报了验证错误,是因为MAIL_USERNAME 和MAIL_PASSWORD 从环境中读取不进来

我还饶了这么一大圈才发现…


行,现在就解决为什么读不进来环境变量。
上次收不到邮件的全过程记录 我应该是弄清楚了pycharm怎么配置环境变量的问题,为运行代码的文件(flasky.py)设置了环境变量,Run -> Edit Configurations -> Environment variables
在这里插入图片描述

为什么还不对? 难道只是我以为我弄清楚了?

  • 猜想1: 是不是应该在flasky.py 的上一级设置环境变量,上次成功是因为代码没重构,所有东西都在那一个文件里面,所以只需要设置那个文件的环境变量就行了。这次代码重构以后,分散成了很多文件,应该给最高级的文件夹设置。
    在这里插入图片描述
    失败…

  • 猜想2: 是不是在哪个文件中读取的环境变量,就应该去设置那个文件。本项目由是在config.py 内执行MAIL_USERNAME = os.environ.get('MAIL_USERNAME') 等等环境变量的读取。
    在这里插入图片描述
    失败…

那是什么原因呢??
为什么读不进来呢??
是读不进来还是读错了
去send_email 函数中打印看看到底啥情况

def send_email(to, subject, template, **kwargs):
    app = current_app._get_current_object()
    
    print(app.config['MAIL_USERNAME'])
    print(app.config['MAIL_PASSWORD'])      # 打印看看情况


    msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + ' ' + subject,
                  sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to])
    msg.body = render_template(template + '.txt', **kwargs)
    msg.html = render_template(template + '.html', **kwargs)
    # thr = Thread(target=send_async_email, args=[app, msg])
    # thr.start()
    # return thr
    mail.send(msg)

在这里插入图片描述
等等,前面怎么没对齐? 多了个空格??
原来是环境变量输错了,前面多输入了个空格导致授权码有误。上次我的实验验证没有错,我是真的弄清楚了!开心!
收到邮件!
在这里插入图片描述
点击链接跳转,验证成功!
在这里插入图片描述
刷新数据库:看到confirmed字段已经打上勾!
在这里插入图片描述

末尾附上我的配置文件config.py,感觉在查资料的时候还挺需要这个(大部分都是原封不动搬运本书配套的GitHub上的配置

import os
basedir = os.path.abspath(os.path.dirname(__file__))


class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'
    MAIL_SERVER = os.environ.get('MAIL_SERVER', 'smtp.163.com')
    MAIL_PORT = int(os.environ.get('MAIL_PORT', '465'))
    MAIL_USE_SSL = True
    MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
    MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
    FLASKY_MAIL_SUBJECT_PREFIX = '[Flasky]'
    FLASKY_MAIL_SENDER = '发送方的邮箱@163.com'
    FLASKY_ADMIN = os.environ.get('FLASKY_ADMIN')
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    TESTING = False
    DEBUG = False

    @staticmethod
    def init_app(app):
        pass


class DevelopmentConfig(Config):
    DEBUG = True
     # 注意!!!注意!!
     # TestingConfig 和 DevelopmentConfig 不要用同一个数据库!!!
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')


class TestingConfig(Config):
    TESTING = True  # True默认不发送邮件
     # TestingConfig 和 DevelopmentConfig 不要用同一个数据库!!!
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data-test.sqlite')

class ProductionConfig(Config):
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'data.sqlite')


config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,

    'default': DevelopmentConfig
}

总结:

终于解决了这两个bug。第一个bug的原因是TESTING 变量值设置错误。第二个bug原因是粗心大意填错了授权码。
原因都很简单,但还是写了这么多,是为了记录自己的思考过程。

and,谨慎修改代码!!!改动一个地方可能当时是跑通了,但是可能为日后别的功能埋下了雷。
and,改代码要遵循控制变量法,一次只改一处!

Attention:

在本文的代码注释中我总计强调了四次TestingConfig 和 DevelopmentConfig 不要用同一个数据库,是有原因的:
详情查看另一篇文章:偷懒用同一个数据库会在单元测试的时候踩大坑

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值