DEV Community

Cover image for Messaging System with Flask App and RabbitMQ/Celery for Email Handling 🚀
akintola abdulazeez oladele
akintola abdulazeez oladele

Posted on

Messaging System with Flask App and RabbitMQ/Celery for Email Handling 🚀

Overview

Welcome to the Messaging System!. This system is designed to handle two main tasks: sending emails and logging requests. It’s built using Flask for the web application and Celery for asynchronous task management, ensuring efficient and scalable processing.

Prerequisites

  • Python 3.12+
  • Virtualenv
  • RabbitMQ/Celery
  • An SMTP email account
  • Nginx
  • Ngrok for external access

Key Components:

  • app.py: This is the main entry point of our web application. It handles incoming HTTP requests, routes them appropriately, and interacts with the Celery tasks for sending emails or logging requests.

  • tasks.py: This file contains the Celery task for sending emails. It ensures that email sending is handled asynchronously, allowing the web application to remain responsive.

  • Celery: An asynchronous task queue/job queue that distributes tasks to multiple workers, making the system scalable and efficient.

app.py 📄

This file sets up the Flask web application. It includes routes to handle sending emails and logging requests.

  • Logging Setup: Ensures the logging directory and log file exist.

  • Route Handling: Defines a route (/) that can handle two types of requests: sendmail to send an email and talktome to log a message with a timestamp.

import os
import logging
import time  # Import the time module
from flask import Flask, request
from tasks import send_email

app = Flask(__name__)

# Ensure logging directory exists
log_dir = "/var/log"
log_file = os.path.join(log_dir, "messaging_system.log")
if not os.path.exists(log_dir):
    os.makedirs(log_dir)
if not os.path.exists(log_file):
    open(log_file, 'a').close()

logging.basicConfig(filename=log_file, level=logging.INFO)

@app.route('/')
def index():
    sendmail = request.args.get('sendmail')
    talktome = request.args.get('talktome')

    try:
        if sendmail:
            recipient_email = sendmail.replace('mailto:', '')
            send_email.delay(recipient_email)
            return "Email sent!"

        if talktome:
            logging.info(f"Talk to me request at {time.strftime('%Y-%m-%d %H:%M:%S')}")
            return "Logged time!"

        return "Welcome to the messaging system!"
    except Exception as e:
        logging.error(f"Error occurred: {e}")
        return "An error occurred. Check the logs for details.", 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Enter fullscreen mode Exit fullscreen mode

tasks.py 📄

This file contains the Celery task for sending emails.

  • Celery Setup: Configures Celery to use RabbitMQ as the message broker.

  • send_email Task: Defines a task to send an email asynchronously using SMTP.

import os
from celery import Celery
from smtplib import SMTP_SSL
from email.mime.text import MIMEText

celery = Celery('tasks', broker='amqp://guest@localhost//')

@celery.task
def send_email(recipient_email):
    email_password = os.environ.get("EMAIL_PASSWORD")
    if not email_password:
        raise ValueError("EMAIL_PASSWORD not set")

    msg = MIMEText('This is a test email.')
    msg['Subject'] = 'Test Email'
    msg['From'] = 'akintola130@gmail.com'
    msg['To'] = recipient_email

    try:
        with SMTP_SSL('smtp.gmail.com', 465) as server:
            server.login('akintola130@gmail.com', email_password)
            server.sendmail('akintola130@gmail.com', recipient_email, msg.as_string())
        print("Email sent successfully!")
    except Exception as e:
        print(f"Failed to send email: {e}")

Enter fullscreen mode Exit fullscreen mode

Setup

1. Clone the Repository

git clone https://github.com/hayzedak/HNG3.git
cd HNG3/messaging_system
Enter fullscreen mode Exit fullscreen mode

2. Create and Activate a Virtual Environment

python3 -m venv venv
source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

3. Install Dependencies

pip install Flask celery
Enter fullscreen mode Exit fullscreen mode

4. Configure Environment Variable
Set the EMAIL_PASSWORD environment variable:

export EMAIL_PASSWORD=your_email_password
Enter fullscreen mode Exit fullscreen mode

Make sure to replace your_email_password with your actual email app password.

5. Initialize RabbitMQ 🐇
Ensure that RabbitMQ is running on your system. You can start RabbitMQ with:

sudo systemctl start rabbitmq-server
Enter fullscreen mode Exit fullscreen mode

6. Ensure Log Directory Exists
Ensure the /var/log/messaging_system.log file exists and set the appropriate permissions:

sudo touch /var/log/messaging_system.log
sudo chmod 666 /var/log/messaging_system.log
Enter fullscreen mode Exit fullscreen mode

7. Configure Nginx
Install Nginx if it's not already installed:

sudo apt update
sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode

Create an Nginx configuration file for your Flask application. For example, create /etc/nginx/sites-available/messaging_system:

sudo nano /etc/nginx/sites-available/messaging_system
Enter fullscreen mode Exit fullscreen mode

Add the following configuration, remember to replace your_domain_or_ip with your actual IP address or domain:

server {
    listen 80;
    server_name your_domain_or_ip;

    location / {
        proxy_pass http://your_domain_or_ip:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    error_log /var/log/nginx/messaging_system_error.log;
    access_log /var/log/nginx/messaging_system_access.log;
}

Enter fullscreen mode Exit fullscreen mode

Enable the configuration by creating a symlink:

sudo ln -s /etc/nginx/sites-available/messaging_system /etc/nginx/sites-enabled
Enter fullscreen mode Exit fullscreen mode

Test the Nginx configuration and restart Nginx:

sudo nginx -t
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

Now, your Flask application should be accessible via your domain or IP.

Running the Application 🚀

  1. Start the Flask Application

Remember to activate the virtual environment.

python3 app.py
Enter fullscreen mode Exit fullscreen mode
  1. Start the Celery Worker: In another terminal, ensure you activate the virtual env.
celery -A tasks worker --loglevel=info
Enter fullscreen mode Exit fullscreen mode

Exposing with ngrok 🌍

To expose your local server to the internet using ngrok, follow these steps:

  • Download and install ngrok from ngrok.com.

  • Start ngrok with the following command:

ngrok http 5000
Enter fullscreen mode Exit fullscreen mode
  • Copy the generated ngrok URL and use it to access your Flask application from the internet.

Usage

Troubleshooting 🛠️

If you encounter any issues, check the logs for more information:

  • Flask application logs: /var/log/messaging_system.log

  • Celery worker logs: Run sudo journalctl -u celery.service -f to view real-time logs.

  • Nginx logs: /var/log/nginx/error.log and /var/log/nginx/access.log

By following these steps, you can set up and run your own messaging system with Flask and Celery. Enjoy! 🎉

Top comments (0)