Introduction:
The ability to send emails to either the users of your application or to yourself is a very nice feature to have in your web application. This blog post will demonstrate how to incorporate the sending of emails to users when they create a new account. how to confirm users’ email address.
This blog post introduces to the Flask extension called Flask-Mail which make sending email very easy in Flask.
Before we get into the configuration steps, I’d like to point out an optional step: creating a new email address for your web application. I’ve found it very convenient to create a new Gmail email address for each web application that I’m building. This will allow you to have a separate email account, not just your personal email account, for sending out notifications to your users.
At this point, it’s also important to understand what is Flask-mail and what flask-mail do means if you are not already aware of it.
https://flask-mail.readthedocs.io/en/latest/
Now let’s get started with requirements installation
Installing Flask-Mail:
Install with pip:
pip install Flask-Mail
pip install smtplib
Step 1:Configuring Flask-Mail
Now we setup our default email configuration. we can change this as per requirement.
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME']='This is sender email'
app.config['MAIL_PASSWORD']= '*********'
app.config['MAIL_USE_TLS']=False
app.config['MAIL_USE_SSL']=True
We also need to initialize anMail
object, as this will be the object that will connect to the SMTP server and send the emails for us.
from flask_mail import Mail
app = Flask(__name__)
mail = Mail(app)
we also need to import some more library. which library is used in our code. we used
from flask import Flask,request,abort,jsonify
from flask_mail import Mail,Message
from flask_pymongo import PyMongo , pymongo
from smtplib import SMTP
import uuid
app = Flask(__name__)
mail=Mail(app)
app.config["MONGO_URI"] = "mongodb://localhost:27017/sendmails"
mongo = PyMongo(app)
Step 2:Make route
Set up a Message object in a Python function mapped by URL route (‘/register’).
@app.route("/register",methods=["POST"])
def email_register():
if not request.json:
abort(500)
user_id = uuid.uuid4().hex
name = request.json.get("name")
username = request.json.get("username")
email = request.json.get("email")
password = request.json.get("password")
user = mongo.db.exam_results.insert_one({
"user_id": user_id,
"name":name,
"username": username,
"email": email,
"password": password
}).inserted_id
if email and username and name and password is not None:
msg = Message('You are registered',
sender='[email protected]',recipients=[email])
msg.body = "Confirm your email"
mail.send(msg)
return "you are registered"
return jsonify(str(user))
Note:
Before the run our code we need to do one thing that the built-in security features in Gmail service may block this login attempt. You may have to decrease the security level. Please log in to your Gmail account and visit https://myaccount.google.com/lesssecureapps link to decrease the security.
Allow less secure apps:On is default disable do this enable.
Let’s send an email!
we do this by Postman.
and we get a registered mail.
This finishes our basic email
Here is the entire final code for reference
from flask import Flask,request,abort,jsonify
from flask_mail import Mail,Message
from flask_pymongo import PyMongo , pymongo
from smtplib import SMTP
import uuid
app = Flask(__name__)
mail=Mail(app)
app.config["MONGO_URI"] = "mongodb://localhost:27017/sendmails"
mongo = PyMongo(app)
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME']='this is sender email'
app.config['MAIL_PASSWORD']= '*******'
app.config['MAIL_USE_TLS']=False
app.config['MAIL_USE_SSL']=True
Mail = Mail(app)
#Api for registration
@app.route("/register",methods=["POST"])
def email_register():
if not request.json:
abort(500)
user_id = uuid.uuid4().hex
name = request.json.get("name")
username = request.json.get("username")
email = request.json.get("email")
password = request.json.get("password")
user = mongo.db.exam_results.insert_one({
"user_id": user_id,
"name":name,
"username": username,
"email": email,
"password": password
}).inserted_id
if email and username and name and password is not None:
msg = Message('You are registered', sender='[email protected]',recipients=[email])
msg.body = "Confirm your email"
mail.send(msg)
return "you are registered"
return jsonify(str(user))
if __name__ == '__main__':
app.run(debug = True)
Step 3:Update the current app
First, let’s add the fieldconfirmed
to our database. And this field default is False.
user = mongo.db.user.insert_one({
"user_id": user_id,
"name":name,
"username": username,
"email": email,
"password": pbkdf2_sha256.hash(password),
"confirmed":False
}).inserted_id
purpose of the add this field is only for registered user verification. if a user clicks on the registration confirmation link then the confirmed field value is updated to true else is still false.
Step 4: Add email confirmation
Generate
For the generate email confirmation token, we need to import some more library. The email confirmation should contain a unique URL that a user simply needs to click in order to confirm his/her account.
from itsdangerous import URLSafeTimedSerializer,SignatureExpired
here SignatureExpired is import for the exception handling.if token is expired
Step 5: Update register route
we update some changes in our current register code.
@app.route("/register",methods=["POST"])
def email_register():
if not request.json:
abort(500)
user_id = uuid.uuid4().hex
name = request.json.get("name")
username = request.json.get("username")
email = request.json.get("email")
password = request.json.get("password")
user = mongo.db.user.insert_one({
"user_id": user_id,
"name":name,
"username": username,
"email": email,
"password": pbkdf2_sha256.hash(password),
"confirmed":False
}).inserted_id
if email and username is not None:
token = s.dumps(email, salt='email-confirm')
msg = Message('confirm email', sender='[email protected]',recipients=[email])
link = url_for('confirm_email', token=token, _external=True)
msg.body = 'Confirmation link is {}'.format(link)
mail.send(msg)
return "registration confirmation link is send"
return jsonify(str(user))
Step 6: Handle Email Confirmation
Next, let’s add a new route to handle the email confirmation:
@app.route('/confirm_email/<token>')
def confirm_email(token):
try:
email = s.loads(token, salt='email-confirm', max_age=3600)
except SignatureExpired:
return "Token is expired"
user= mongo.db.user.update({"email": email},
{ "$set":{ "confirmed":True}})
return "you are registered"
if __name__ == '__main__':
app.run(debug = True)
Now run the code in windows by this -
set FLASK_APP=file name
flask run
and run in linux/ubuntu
export FLASK_APP=file name
flask run
now lets run the our code .First we register an user.
we register a user and get in response “registration confirmation link is send” . We get a link on registered email.
Now we confirm the our registered email address. For the email confirmation we use our another route ‘/confirm_email/ .
after the link confirmation we get response you are registered.now we check our confirmation status in database.
see here our confirmed status is true.. that means we successfully confirmed our account.
Here is the entire final code for reference .
from flask import Flask,request,abort,jsonify,url_for
from flask_mail import Mail,Message
from flask_pymongo import PyMongo , pymongo
from smtplib import SMTP
import uuid
from bson.json_util import dumps
from itsdangerous import URLSafeTimedSerializer,SignatureExpired
from passlib.hash import pbkdf2_sha256
app = Flask(__name__)
mail=Mail(app)
app.config["MONGO_URI"] = "mongodb://localhost:27017/sendmails"
mongo = PyMongo(app)
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME']='this is sender email'
app.config['MAIL_PASSWORD']= '*******'
app.config['MAIL_USE_TLS']=False
app.config['MAIL_USE_SSL']=True
Mail = Mail(app)
s = URLSafeTimedSerializer('Thisisecret')
#Api for registration
@app.route("/register",methods=["POST"])
def email_register():
if not request.json:
abort(500)
user_id = uuid.uuid4().hex
name = request.json.get("name")
username = request.json.get("username")
email = request.json.get("email")
password = request.json.get("password")
user = mongo.db.user.insert_one({
"user_id": user_id,
"name":name,
"username": username,
"email": email,
"password": pbkdf2_sha256.hash(password),
"confirmed":False
}).inserted_id
if email and username and name and password is not None:
token = s.dumps(email, salt='email-confirm')
msg = Message('confirm email', sender='[email protected]',recipients=[email])
link = url_for('confirm_email', token=token, _external=True)
msg.body = 'Confirmation link is {}'.format(link)
mail.send(msg)
return "registration confirmation link is send"
return jsonify(str(user))
#Api for email confirmation
@app.route('/confirm_email/<token>')
def confirm_email(token):
try:
email = s.loads(token, salt='email-confirm', max_age=3600)
except SignatureExpired:
return "Token is expired"
user= mongo.db.user.update({"email": email}, { "$set":{ "confirmed":True}})
return "you are registered"
if __name__ == '__main__':
app.run(debug = True)