Ask me anything
Ithy Logo
Sign in to save

Automating Email Verification Using Google Workspace and Flask API

A comprehensive guide to setting up automated email verifications with Flask and Google Workspace

gmail api flask application

Key Takeaways

  • Seamless Integration: Utilize the Gmail API for robust and secure email sending from your Flask application.
  • Secure Authentication: Implement OAuth 2.0 to ensure a secure connection between Flask and Google Workspace.
  • Scalable Solutions: Leverage Celery and Redis for asynchronous email processing to handle high volumes efficiently.

Introduction

Automating email verification is a crucial feature for web applications to ensure that users provide valid email addresses during registration. By integrating Google Workspace with a Flask API, developers can create a reliable system to send verification emails automatically. This guide provides an in-depth, step-by-step process to set up this integration, ensuring security, scalability, and efficiency.

1. Setting Up Google Cloud Project and Enabling Gmail API

To start automating email verifications, you first need to set up a project in the Google Cloud Console and enable the Gmail API.

a. Create a New Project

  1. Navigate to the Google Cloud Console.
  2. Click on the project dropdown and select New Project.
  3. Enter a project name, for example, "FlaskEmailVerification," and click Create.

b. Enable the Gmail API

  1. Within your newly created project, go to APIs & Services > Library.
  2. Search for "Gmail API" and select it.
  3. Click Enable to activate the API for your project.

2. Obtaining OAuth 2.0 Credentials

OAuth 2.0 is essential for securely accessing the Gmail API. Follow these steps to obtain the necessary credentials.

a. Configure OAuth Consent Screen

  1. In the Google Cloud Console, navigate to APIs & Services > OAuth consent screen.
  2. Select External for the user type and click Create.
  3. Fill in the required fields such as Application name, Support email, and add scopes if necessary.
  4. Save and continue through the remaining steps, adding any necessary information.

b. Create OAuth 2.0 Credentials

  1. Go to APIs & Services > Credentials.
  2. Click Create Credentials > OAuth client ID.
  3. Select Web application as the application type.
  4. Provide an appropriate name, such as "FlaskAppClient."
  5. Under Authorized redirect URIs, add `http://localhost:5000/callback`.
  6. Click Create and download the `credentials.json` file. Store this file securely as it contains sensitive information.

3. Installing Required Python Libraries

Ensure that your development environment has all the necessary libraries installed to interact with the Gmail API and build the Flask application.

a. Set Up a Virtual Environment

python -m venv venv
source venv/bin/activate  # On Windows use `venv\Scripts\activate`
    

b. Install Dependencies

pip install Flask Flask-Mail google-auth google-auth-oauthlib google-auth-httplib2 google-api-python-client celery redis
    

Explanation of Libraries:

  • Flask: Web framework for building the API.
  • Flask-Mail: Facilitates sending emails from Flask.
  • google-auth, google-auth-oauthlib, google-auth-httplib2: Handle authentication with Google APIs.
  • google-api-python-client: Allows interaction with Google APIs, including Gmail.
  • Celery: Task queue for managing asynchronous tasks.
  • Redis: In-memory data structure store, used as a broker for Celery.

4. Configuring Flask Application for Gmail API Integration

With the necessary libraries installed and credentials obtained, the next step is to configure your Flask application to interact with the Gmail API.

a. Setting Up the Flask App

import os
import base64
from flask import Flask, redirect, url_for, session, request, jsonify
from flask_mail import Mail, Message
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import Flow
from googleapiclient.discovery import build
from celery import Celery

app = Flask(__name__)
app.secret_key = 'your_secret_key'  # Replace with your secret key

# Flask-Mail Configuration
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = 'your_workspace_email@yourdomain.com'
app.config['MAIL_PASSWORD'] = 'your_app_specific_password'  # Use app password if two-factor is enabled
mail = Mail(app)

# Celery Configuration
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'

celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
    

b. Implementing OAuth 2.0 Flow

Set up the OAuth 2.0 flow to authenticate and authorize your Flask application to send emails on behalf of the user.

# Define the OAuth 2.0 scopes
SCOPES = ['https://www.googleapis.com/auth/gmail.send']

# Initialize the OAuth flow
flow = Flow.from_client_secrets_file(
    'path/to/credentials.json',  # Path to your credentials.json
    scopes=SCOPES,
    redirect_uri='http://localhost:5000/callback'
)

@app.route('/')
def index():
    authorization_url, state = flow.authorization_url(
        access_type='offline',
        include_granted_scopes='true'
    )
    session['state'] = state
    return redirect(authorization_url)

@app.route('/callback')
def callback():
    flow.fetch_token(authorization_response=request.url)

    if not flow.credentials:
        return 'Authorization failed', 400

    session['credentials'] = credentials_to_dict(flow.credentials)
    return 'Authentication successful. You can close this window.'

def credentials_to_dict(credentials):
    return {
        'token': credentials.token,
        'refresh_token': credentials.refresh_token,
        'token_uri': credentials.token_uri,
        'client_id': credentials.client_id,
        'client_secret': credentials.client_secret,
        'scopes': credentials.scopes
    }
    

c. Sending Emails via Gmail API

Implement the functionality to send emails using the Gmail API.

def send_email_via_gmail(to_email, subject, body):
    creds = Credentials(**session.get('credentials'))
    service = build('gmail', 'v1', credentials=creds)

    message = MIMEText(body)
    message['to'] = to_email
    message['from'] = app.config['MAIL_USERNAME']
    message['subject'] = subject

    raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()

    try:
        message = service.users().messages().send(userId='me', body={'raw': raw_message}).execute()
        print(f'Message sent: {message["id"]}')
        return True
    except Exception as e:
        print(f'An error occurred: {e}')
        return False
    

5. Implementing Email Verification Logic

With the email sending functionality in place, the next step is to implement the logic for email verification.

a. Creating Verification Tokens

Generate unique verification tokens to securely verify user email addresses.

import jwt
import datetime

SECRET_KEY = 'your_jwt_secret_key'  # Replace with your JWT secret key

def generate_verification_token(email):
    payload = {
        'email': email,
        'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=24)  # Token expires in 24 hours
    }
    token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
    return token

def verify_token(token):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
        return payload['email']
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None
    

b. Setting Up Verification Routes

Create routes in your Flask application to handle user registration and email verification.

@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    email = data.get('email')
    
    if not email:
        return jsonify({'error': 'Email is required'}), 400
    
    token = generate_verification_token(email)
    verification_link = url_for('verify_email', token=token, _external=True)
    
    subject = 'Email Verification'
    body = f'Please click the link below to verify your email address:\n{verification_link}'
    
    # Send the verification email asynchronously
    send_verification_email.delay(email, subject, body)
    
    return jsonify({'message': 'Verification email sent'}), 200

@celery.task
def send_verification_email(to_email, subject, body):
    send_email_via_gmail(to_email, subject, body)

@app.route('/verify/')
def verify_email(token):
    email = verify_token(token)
    if email:
        # Update user status in the database to verified
        # Example: User.query.filter_by(email=email).update({'is_verified': True})
        # db.session.commit()
        return 'Email verified successfully!', 200
    else:
        return 'Verification link is invalid or has expired.', 400
    

6. Handling SMTP as an Alternative

If you prefer not to use the Gmail API, you can configure your Flask application to send emails using the SMTP protocol via Flask-Mail.

a. Configuring Flask-Mail

from flask_mail import Mail, Message

# Flask-Mail configuration is already set in the earlier Flask app setup
mail = Mail(app)

@app.route('/send-smtp-email', methods=['POST'])
def send_smtp_email():
    data = request.get_json()
    recipient = data.get('email')
    subject = 'SMTP Email Verification'
    body = 'Please verify your email address using the SMTP method.'

    msg = Message(subject, sender=app.config['MAIL_USERNAME'], recipients=[recipient])
    msg.body = body

    try:
        mail.send(msg)
        return jsonify({'message': 'SMTP Verification email sent'}), 200
    except Exception as e:
        return jsonify({'error': str(e)}), 500
    

b. Advantages of Using SMTP

  • Simplicity in setup without needing OAuth 2.0.
  • Suitable for applications with lower email sending requirements.

7. Ensuring Application Security

Security is paramount when handling user data and integrating with external APIs. Implement the following best practices to secure your application.

a. Protect Sensitive Information

  • Store sensitive credentials, such as `credentials.json` and `SECRET_KEY`, in environment variables or secure configuration files.
  • Never expose these credentials in your source code repositories.

b. Implement HTTPS

Use HTTPS to encrypt data in transit between your Flask application and users.

c. Rate Limiting

Prevent abuse by limiting the number of requests a user can make within a specific timeframe.

from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["200 per day", "50 per hour"]
)
    

8. Managing Email Sending Limits

Google Workspace imposes daily email sending limits based on your subscription plan. It is essential to manage these limits to prevent your application from exceeding them.

a. Understand Email Limits

  • Standard Gmail accounts: Up to 100 emails per day.
  • Google Workspace accounts: Ranges from 100 to 5,000 emails per day depending on the plan.

b. Implement Queue Management

Use Celery with Redis to queue email sending tasks, allowing you to control the rate of emails being sent and handle retries in case of failures.

@celery.task(bind=True, max_retries=3)
def send_email_task(self, to_email, subject, body):
    try:
        send_email_via_gmail(to_email, subject, body)
    except Exception as exc:
        raise self.retry(exc=exc, countdown=60)
    

c. Monitoring and Alerts

Set up monitoring to track email sending rates and receive alerts when approaching or exceeding limits.


9. Optional: Asynchronous Email Sending with Celery and Redis

For applications that require sending a high volume of emails, it's advisable to handle email sending asynchronously to improve performance and reliability.

a. Setting Up Celery with Flask

# tasks.py
from your_flask_app import celery

@celery.task
def send_async_email(to_email, subject, body):
    send_email_via_gmail(to_email, subject, body)
    

b. Starting the Celery Worker

celery -A your_flask_app.celery worker --loglevel=info
    

c. Integrating with Flask Routes

@app.route('/send-async-email', methods=['POST'])
def send_async():
    data = request.get_json()
    to_email = data.get('email')
    subject = 'Asynchronous Email Verification'
    body = 'This is an asynchronously sent verification email.'

    send_async_email.delay(to_email, subject, body)
    return jsonify({'message': 'Async Verification email sent'}), 200
    

10. Testing the Email Verification System

Before deploying your application, thoroughly test the email verification system to ensure reliability and functionality.

a. Local Testing

  • Run your Flask application locally and perform registration to trigger email sending.
  • Use tools like Mailtrap to capture and inspect outgoing emails without sending them to actual users.

b. Deployment Testing

  • Deploy your Flask application to a staging environment.
  • Perform end-to-end testing to ensure that emails are sent and verification links function correctly.

11. Recap

Automating email verification in a Flask API using Google Workspace involves setting up a Google Cloud project, enabling the Gmail API, and securing OAuth 2.0 credentials. Integrating these with Flask, along with tools like Celery and Redis, ensures a scalable and secure email verification system. By following best practices in security and managing email sending limits, you can create a reliable verification process that enhances user trust and application integrity.


References


Last updated January 11, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI