Cron Email Campaigns — Automated Email Scheduling with Cron
In this tutorial, you will learn about Cron Email Campaigns. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn cron-based email campaign scheduling: trigger transactional emails at specific times, manage newsletter delivery queues, process bounces and complaints, and monitor email delivery health with automated Cron Jobs.
What You Learn
You will learn how to use cron for email campaigns: scheduling batch email delivery, managing email queues, processing delivery reports, handling bounces, and monitoring email infrastructure health.
Why It Matters
Sending emails at the wrong time reduces engagement and increases unsubscribes. Cron enables precise scheduling: newsletters at optimal times, reminders at specific intervals, and automated follow-ups without manual triggering.
Real-World Use
DodaTech's email cron jobs send weekly newsletters every Tuesday at 10 AM, transactional email queues process every 5 minutes, bounce reports are processed every hour, and email health metrics are collected daily at 8 AM.
Email Queue Processor
import time
import random
from datetime import datetime
class EmailQueueProcessor:
def __init__(self):
self.queue = []
self.sent = 0
self.failed = 0
def enqueue(self, to, subject, body, scheduled_time=None):
self.queue.append({
'to': to,
'subject': subject,
'body': body,
'scheduled': scheduled_time or datetime.now(),
'status': 'pending'
})
def process_batch(self, batch_size=50):
now = datetime.now()
batch = [e for e in self.queue if e['scheduled'] <= now and e['status'] == 'pending'][:batch_size]
for email in batch:
email['status'] = 'sending'
time.sleep(random.uniform(0.01, 0.05))
if random.random() > 0.05:
email['status'] = 'sent'
self.sent += 1
else:
email['status'] = 'failed'
self.failed += 1
print(f"[{now.strftime('%H:%M:%S')}] Processed {len(batch)} emails ({self.sent} sent, {self.failed} failed)")
return len(batch)
def get_queue_depth(self):
pending = sum(1 for e in self.queue if e['status'] == 'pending')
return pending
processor = EmailQueueProcessor()
for i in range(10):
processor.enqueue(f"user{i}@example.com", f"Newsletter #{i}", "Content here")
processor.process_batch(batch_size=50)
print(f"Queue depth: {processor.get_queue_depth()}")
Expected output:
[00:00:00] Processed 10 emails (10 sent, 0 failed)
Queue depth: 0
Email Delivery Monitor
import time
from datetime import datetime, timedelta
class EmailDeliveryMonitor:
def __init__(self):
self.metrics = {
'sent': 0,
'delivered': 0,
'bounced': 0,
'opened': 0,
'clicked': 0,
'complained': 0,
}
def record_delivery_event(self, event_type, count=1):
if event_type in self.metrics:
self.metrics[event_type] += count
def get_delivery_rate(self):
if self.metrics['sent'] == 0:
return 0.0
return (self.metrics['delivered'] / self.metrics['sent']) * 100
def get_bounce_rate(self):
if self.metrics['sent'] == 0:
return 0.0
return (self.metrics['bounced'] / self.metrics['sent']) * 100
def get_open_rate(self):
if self.metrics['delivered'] == 0:
return 0.0
return (self.metrics['opened'] / self.metrics['delivered']) * 100
def report(self):
print(f"Email Delivery Report ({datetime.now().strftime('%Y-%m-%d %H:%M')})")
print(f" Sent: {self.metrics['sent']}")
print(f" Delivered: {self.metrics['delivered']} ({self.get_delivery_rate():.1f}%)")
print(f" Bounced: {self.metrics['bounced']} ({self.get_bounce_rate():.1f}%)")
print(f" Opened: {self.metrics['opened']} ({self.get_open_rate():.1f}%)")
print(f" Complaints: {self.metrics['complained']}")
monitor = EmailDeliveryMonitor()
monitor.record_delivery_event('sent', 1000)
monitor.record_delivery_event('delivered', 970)
monitor.record_delivery_event('bounced', 30)
monitor.record_delivery_event('opened', 250)
monitor.report()
Expected output:
Email Delivery Report (2026-06-28 00:00)
Sent: 1000
Delivered: 970 (97.0%)
Bounced: 30 (3.0%)
Opened: 250 (25.8%)
Complaints: 0
Common Mistakes
1. Sending Emails at Wrong Times
Sending newsletters at midnight or during weekends reduces engagement. Schedule emails during optimal times: 10 AM-2 PM Tuesday-Thursday. Use cron to schedule delivery at these times. Allow users to choose their preferred timezone.
2. No Bounce Processing
Hard bounces (invalid addresses) waste delivery resources and damage sender reputation. Process bounce reports every hour via cron. Automatically suppress hard bounces. Flag soft bounces (temporary failures) for retry with backoff.
3. Email Queue Growing Unbounded
If email sending rate is lower than enqueue rate, the queue grows indefinitely. Monitor queue depth and alert if it exceeds thresholds. Implement backpressure: pause enqueueing when queue is too deep.
4. No Rate Limiting for ESP Limits
Email service providers (SendGrid, SES) have sending limits. Implement a rate limiter that respects the ESP's limits: max emails per second, per hour, per day. Cron jobs should process at a throttled rate.
5. Sending Without Engagement Monitoring
If open rates drop below 10% or complaint rates exceed 0.1%, you risk being marked as spam. Monitor engagement metrics daily via cron. Alert on negative trends. Pause campaigns if metrics exceed thresholds.
Practice Questions
1. How do you schedule a weekly newsletter with cron?
Set a cron expression: 0 10 * * 2 for Tuesday at 10 AM. The cron job queries subscribers, generates the newsletter content, and adds to the email queue. The queue processor runs every 5 minutes to send batch emails.
2. How do you handle email bounces in cron?
Schedule a bounce processing cron job every hour. The job downloads bounce reports from the ESP, classifies bounces as hard (invalid address) or soft (temporary), suppresses hard bounces, and schedules retry for soft bounces with exponential backoff.
3. How do you rate-limit email sending in a cron job?
Implement a token bucket that respects ESP limits: 10 emails/second, 5000/hour, 50000/day. The cron job processes emails at this rate. If the daily limit is reached, remaining emails stay in the queue for the next day.
4. What email metrics should cron jobs monitor?
Track: emails sent, delivered, bounced (hard/soft), opened, clicked, complained, unsubscribed. Calculate rates: delivery rate (>95%), bounce rate (<5%), open rate (>20%), complaint rate (<0.1%). Alert on threshold breaches.
Challenge
Build an email campaign cron system: (1) campaign scheduler: weekly newsletter (Tue 10 AM), daily digest (7 AM), transactional queue (every 5 min), (2) email queue with throttling: 10 emails/sec, 5000/hour, 50000/day, (3) bounce processor: hourly, classify hard/soft, suppress hard, retry soft with 24h/72h/168h backoff, (4) engagement monitor: daily report of delivery/open/click rates, (5) suppression list: maintain and check against hard bounces and complaints, (6) monitoring: queue depth, sending rate, delivery rates, bounce rates, (7) alerting: bounce rate >5%, open rate <10%, complaint rate >0.1%, queue >10000.
FAQ
Mini Project: Email Campaign Cron System
Build a cron-based email campaign system: (1) campaign scheduler: weekly newsletter (Tue 10 AM), daily digest, transactional queue (every 5 min), re-engagement (every 30 days since last email), (2) email queue with throttling: 10 emails/sec concurrency, 5000/hour limit, 50000/day limit, (3) bounce processor: hourly, hard/soft classification, suppression list, (4) engagement monitor: daily delivery/open/click rates, complaint tracking, (5) suppression management: auto-suppress hard bounces and complaints, manual review for soft bounces, (6) rate limiter: token bucket per ESP with configurable limits, (7) monitoring: queue depth, sending rate, delivery metrics, alerting on threshold breaches.
What's Next
Now that you understand email campaign scheduling with cron, explore SSL certificate renewal automation, then learn about system health check scheduling.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro