To prevent bot signups and reduce spam, you can require that users click a link in an email they receive when they register to your web apps. Flask-Security-Too can take care of this with some configuration.
This is article 2 of 3 in this series covering Flask-Security-Too:
- User authentication in Flask with Flask-Security-Too
- User email confirmations with Flask-Security-Too (this article)
- Customising templates and emails of Flask-Security-Too
Let's get started!
The tricky bit about user confirmation is the email delivery. To actually send emails and have them reach the user's inbox (and not end up in spam), you need a few things: a domain name, an email delivery service, and proper configuration. We talk about this in depth in our REST APIs with Flask and Python course, and you can read that section of the course e-book here.
I like the email delivery service Mailgun. Create an account with them, and you'll be given a sandbox domain. You can use this domain to send emails to "authorised recipients". You can add yourself as an authorised recipient, so you can test out the email confirmation functionality of Flask-Security-Too. A step-by-step guide on how to do this is here. Read the "Setting up for Mailgun" section before continuing!
In the future, if you want to purchase a domain, you can use it to send emails with Mailgun (though that isn't free).
Now that you've got your Mailgun account, let's get the SMTP details. You can do this by clicking the "Select" button under "SMTP":
Let's add these to our
DATABASE_URL="sqlite:///data.db" MAIL_SERVER=smtp.mailgun.org MAIL_PORT=587 MAIL_USERNAME= MAIL_PASSWORD=
Now we can tell Flask-Security-Too to use email confirmation with one configuration setting:
app.config["SECURITY_CONFIRMABLE"] = True
Doing this makes it so user accounts aren't valid until they are marked as
confirmed (this is a column in our
UserModel class, which you can see in
models/auth.py). User accounts will be
confirmed when the user clicks a link in an email they receive after registration.
Next, we'll configure the Flask-Mailman library, which Flask-Security-Too uses to send emails. In
# At top of file from flask_mailman import Mail # After 'Create app' app.config["MAIL_SERVER"] = os.getenv("MAIL_SERVER") app.config["MAIL_PORT"] = os.getenv("MAIL_PORT") app.config["MAIL_USE_SSL"] = False app.config["MAIL_USE_TLS"] = True app.config["MAIL_USERNAME"] = os.getenv("MAIL_USERNAME") app.config["MAIL_PASSWORD"] = os.getenv("MAIL_PASSWORD") mail = Mail(app)
Note that the
MAIL_USE_TLS values will depend on which provider you use. Mailgun uses TLS, so that's why we set SSL to
False and TLS to
Now, when you register an account, you'll get a confirmation email with a link you must click. If you don't click the link, the account will not count as valid.
We can test this out by creating a protected endpoint (one that requires login). We can then register but not click the email link, and see if we can access it.
To create a protected endpoint, we use the
# At top of file from flask_security import login_required # At bottom of file @app.route("/protected") @login_required def protected(): return "You're logged in!"
Now let's try it out. Delete your
data.db file and re-create it using
>>> from app import app, db >>> with app.app_context(): db.create_all()
Then start the app with
flask run and fill in your registration form. It's interesting to note that when we enable email confirmation, Flask-Security-Too automatically disables password confirmation in the signup form. Now there's just one password field instead of two:
Fill this in, making sure to use the email address that you used in your "authorised recipients" for Mailgun.
Then you should get an email (which might be in your Spam folder since we're using the Mailgun sandbox domain):
Don't click the link yet. Instead, navigate to the
/protected endpoint with your browser: http://127.0.0.1:5000/protected. You should get redirected to the login page and you should see an error:
These errors use Flask's flashed messages, and you can see there are two messages:
- Thank you. Confirmation instructions have been sent to (my email).
- Please log in to access this page.
They both look like errors, but the first one is just a message that Flask-Security-Too flashes when registration is successful. Flashed messages must be displayed once, and since there was no place for it to be shown until now, it stuck around. Ideally, you would use message flashing in the page that you redirect the user to after registration to show this message.
The second message is the error we were expecting!
Now click the confirmation link in your email, and try again. It should work!
This is how you can use Flask-Security-Too to easily add use registration and confirmation to your Flask applications. Naturally, you'd want to style the login, register, and confirmation pages to match the rest of your application. We'll look at that in part 3 of this series.
Thank you for reading! If you'd like to learn more about web development using Flask, consider enrolling in our Web Developer Bootcamp with Flask and Python! It's a complete video course that covers building multiple web apps and deploying them, all using Flask.