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)