okcapp
okcapp

Reputation: 405

Email confirmation in Flask fails

The below code successfully generates a token and sends a link to the user's inbox for confirmation. But when the user clicks on it, Flask is not recognizing the token it just created. Here is the error message:

"Got exception from ts.loads: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."

The bottom line is that this is what should execute if I could make the confirmation procedure work properly:

return redirect(url_for('tutorials'))

But, as you can piece together by noting the error message that is coming out of @app.errorhandler(404), something is going wrong. I'm really stuck. These tests are being done way before the max_age of 86400 seconds is reached. Any help would be much appreciated!!!

from itsdangerous import URLSafeTimedSerializer

ts = URLSafeTimedSerializer(SECRET_KEY, salt='email-confirm-key')

@app.route('/signup', methods=['GET', 'POST'])
def signup():

#skipping unrelated lines of code

        token = ts.dumps(form.email.data, salt='email-confirm-key')
        subject = 'subject goes here'
        msg = Message(subject=subject, sender='[email protected]', recipients=form.email.data.split())
        link = url_for('confirm_email', token=token, _external=True)
        msg.html = render_template("email_confirmationemail.html", link=link, name=request.form['first_name'])
        with app.app_context():
            mail.send(msg)
        return redirect(url_for('checkyouremail'))


@app.route('/confirmemail/<token>')
def confirm_email(token):
    try:
        email = ts.loads(token, salt='email-confirm-key', max_age=86400)

    #skipping unrelated lines of code

    return redirect(url_for('tutorials'))

@app.errorhandler(404)
def not_found(e):
    print('Got exception from ts.loads: {}'.format(e))
    return render_template('404.html')

Upvotes: 2

Views: 1527

Answers (1)

okcapp
okcapp

Reputation: 405

In models.py, my __init__ method for the User class has this line:

self.email = email.lower()

When users create a profile on a phone, their email address often starts with an uppercase letter.

So I just needed to change

token = ts.dumps(form.email.data, salt='email-confirm-key')

to

token = ts.dumps(form.email.data.lower(), salt='email-confirm-key')

so that the email held in the token matched with the email in the database when the user clicked on the confirmation link I sent them. (In short, adding .lower() as shown above in my call do dumps solved my problem).

Upvotes: 1

Related Questions