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)
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}")
Setup
1. Clone the Repository
git clone https://github.com/hayzedak/HNG3.git
cd HNG3/messaging_system
2. Create and Activate a Virtual Environment
python3 -m venv venv
source venv/bin/activate
3. Install Dependencies
pip install Flask celery
4. Configure Environment Variable
Set the EMAIL_PASSWORD environment variable:
export EMAIL_PASSWORD=your_email_password
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
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
7. Configure Nginx
Install Nginx if it's not already installed:
sudo apt update
sudo apt install nginx
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
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;
}
Enable the configuration by creating a symlink:
sudo ln -s /etc/nginx/sites-available/messaging_system /etc/nginx/sites-enabled
Test the Nginx configuration and restart Nginx:
sudo nginx -t
sudo systemctl restart nginx
Now, your Flask application should be accessible via your domain or IP.
Running the Application 🚀
- Start the Flask Application
Remember to activate the virtual environment.
python3 app.py
- Start the Celery Worker: In another terminal, ensure you activate the virtual env.
celery -A tasks worker --loglevel=info
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
- Copy the generated ngrok URL and use it to access your Flask application from the internet.
Usage
To send an email, navigate to http://your_ngrok_endpoint/?sendmail=mailto:recipient@example.com.
To log a request, navigate to http://your_ngrok_endpoint/?talktome.
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)