Boosting Python Email Tasks with Celery, Pipenv, and Python-dotenv

Search for a command to run...

No comments yet. Be the first to comment.
A few months ago, my product manager dropped something in the team channel. "We are adding an AI agent to the platform next quarter. It will handle follow-ups automatically." Just like that. One messa

f you’re diving into React, you’ve likely come across the useRef hook. But what exactly is useRef(), and how can it make your life easier? In this post we’ll cover what useRef is, walk through five

A bug that only happens for some users, that you can never reproduce, that isn't in your code. Welcome to the React + browser-translation crash — what causes it, why it's so sneaky, and the battle-tested one-file fix.

Upgrading a core production database is usually the stuff of dev nightmares. It often involves maintenance windows, scheduled downtime, and the looming fear of a botched migration. But what if you cou

We are moving into products that adapt, predict and react with real context. Designing only interfaces is not enough anymore. We are designing experiences that understand the user. Designers and digital agencies are now challenged to move beyond trad...

Engineering at JoBins
167 posts
Welcome to Engineering at JoBins — where we share the stories, insights, and lessons from building a world-class hiring platform. From system design and scalability to developer tools and team culture, our engineers write about the real challenges we solve every day. Whether you're a curious developer or a fellow builder, we hope our experiences inspire and inform your own engineering journey.
Celery is an open-source asynchronous task queue or job queue based on distributed message passing. While it supports scheduling, it focuses on real-time operations. When used with Pipenv, Python's tool for managing dependencies and virtual environments, developers can simplify their work and ensure consistent setups. Python-dotenv enhances this by loading environment variables from a .env file, keeping configurations clean and secure. Together, these tools create a strong system for handling background tasks like email sending in Python projects.
In this blog post, we’ll show how to use Celery, Pipenv, and Python-dotenv to handle email sending tasks via SMTP in your Python projects.
Let's start by creating a new Python project with Pipenv and then add Celery to it.
Install Pipenv:
pip install pipenv
Create a new project directory and initialize Pipenv:
mkdir celery-email
cd celery-email
pipenv install
Install Celery, Redis (as a message broker), and Python-dotenv:
pipenv install celery redis python-dotenv
Create a.envfile in your project directory to store environment variables
# Celery configuration
REDIS_URL=redis://localhost:6379/0
# Email configuration
SMTP_SERVER=smtp.mailtrap.io
SMTP_PORT=2525
SMTP_USERNAME=username
SMTP_PASSWORD=password
Create a celeryconfig.py file in your project directory with the following content:
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Celery configuration
broker_url = os.getenv('REDIS_URL')
result_backend = os.getenv('REDIS_URL')
broker_connection_retry_on_startup = True # Ensure broker connection retry on startup
In this setup, we use Python-dotenv to load the Celery broker and backend URLs from the .env file, keeping sensitive information out of our source code.
Create a tasks.py file in your project directory:
from celery import Celery
from celery.utils.log import get_task_logger
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
import os
logger = get_task_logger(__name__)
# Initialize Celery app
app = Celery('tasks', broker=os.getenv('REDIS_URL'), backend=os.getenv('REDIS_URL'))
@app.task
def send_email(recipient_email):
# Email content
msg = MIMEMultipart()
msg['From'] = os.getenv('SMTP_USERNAME')
msg['Subject'] = 'Test Email from Celery'
body = 'This is a test email sent asynchronously using Celery.'
msg.attach(MIMEText(body, 'plain'))
# SMTP server configuration
smtp_server = os.getenv('SMTP_SERVER')
smtp_port = int(os.getenv('SMTP_PORT', 587)) # Convert to integer, default to 587 if not specified
smtp_username = os.getenv('SMTP_USERNAME')
smtp_password = os.getenv('SMTP_PASSWORD')
try:
# Create SMTP session
server = smtplib.SMTP(smtp_server, smtp_port)
server.starttls()
server.login(smtp_username, smtp_password)
msg['To'] = recipient_email
# Send email
server.sendmail(smtp_username, recipient_email, msg.as_string())
logger.info(f"Email sent successfully to {recipient_email}")
except Exception as e:
logger.error(f"Failed to send email to {recipient_email}: {str(e)}")
finally:
server.quit()
This task sends an email asynchronously using Celery and smtplib.
To start the Celery worker, run below command in your project directory:
pipenv run celery -A tasks worker --loglevel=info
This command starts a Celery worker that listens for tasks defined in tasks.py.
You can now use the defined task in your Python scripts or web applications. Here is an example of how to call this task:
from tasks import send_email
# List of recipients
recipient_emails = ['rajendra@example.com', 'manish@example.com']
# Triggering the Celery task asynchronously
for recipient in recipient_emails:
print(f"Email start {recipient}")
result = send_email.delay(recipient)
print(f"Email task sent to {recipient}: {result}")
Integrating Celery with Pipenv and Python-dotenv offers a robust solution for managing and optimizing Python email tasks. Besides email processing, Celery is excellent for many other asynchronous tasks. It can handle background job scheduling, periodic tasks, and real-time data processing. Celery's ability to distribute work across multiple workers can enhance the performance of data-heavy applications, web scraping, and machine learning model training.
If you have any questions or need further clarification, feel free to reach out. Happy coding! 😊👍