Running a small business means drowning in repetitive emails. Here's how I automated mine with Python in one afternoon.
The Problem
Every week I was spending 3-4 hours:
- Sending follow-up emails to clients who hadn't paid
- Sending weekly status reports to 10+ clients
- Replying to the same 5 "how do I do X?" questions
- Manually forwarding supplier invoices to accounting
The Solution: A Python Email Bot
Setup
import smtplib
import imaplib
import email
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime, timedelta
import schedule
import time
1. Automated Payment Follow-Up Emails
import sqlite3
from datetime import date, timedelta
def check_overdue_invoices():
conn = sqlite3.connect('invoices.db')
cursor = conn.cursor()
# Find invoices overdue by 7+ days
overdue_date = date.today() - timedelta(days=7)
cursor.execute('''
SELECT client_email, client_name, invoice_id, amount, due_date
FROM invoices
WHERE status = 'unpaid' AND due_date <= ?
''', (overdue_date.isoformat(),))
overdue = cursor.fetchall()
for email_addr, name, inv_id, amount, due_date in overdue:
send_follow_up(email_addr, name, inv_id, amount, due_date)
conn.close()
def send_follow_up(to_email, name, invoice_id, amount, due_date):
subject = f"Payment Reminder: Invoice #{invoice_id}"
body = f"""
Hi {name},
I hope you're doing well. I wanted to follow up on Invoice #{invoice_id}
for ${amount:.2f}, which was due on {due_date}.
Could you let me know the status? If you've already sent payment,
please disregard this message.
Best regards,
Your Business Name
"""
send_email(to_email, subject, body)
# Schedule to run every Monday at 9 AM
schedule.every().monday.at("09:00").do(check_overdue_invoices)
2. Auto-Reply to Common Questions
import re
FAQS = {
"refund": "Our refund policy is 30 days. To request a refund, reply to this email with your order number.",
"pricing": "Our pricing starts at $X/month. Check our full pricing at: https://yoursite.com/pricing",
"delivery": "Standard delivery is 5-7 business days. Express shipping takes 2-3 days.",
"password": "To reset your password, visit https://yoursite.com/reset-password",
"invoice": "Invoices are sent within 24 hours of purchase. Check your spam folder first!",
}
def handle_incoming_email(email_content, sender, subject):
email_lower = email_content.lower() + " " + subject.lower()
for keyword, response in FAQS.items():
if keyword in email_lower:
send_email(
sender,
f"Re: {subject}",
f"Thanks for reaching out! {response}\n\n---\nThis is an automated reply."
)
return True # Handled
return False # Needs human attention
def check_inbox():
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('your@gmail.com', 'app_password')
mail.select('INBOX')
_, search_data = mail.search(None, 'UNSEEN')
for num in search_data[0].split():
_, data = mail.fetch(num, '(RFC822)')
email_message = email.message_from_bytes(data[0][1])
sender = email_message['From']
subject = email_message['Subject']
body = get_email_body(email_message)
handled = handle_incoming_email(body, sender, subject)
if handled:
# Mark as read
mail.store(num, '+FLAGS', '\\Seen')
3. Weekly Client Status Reports
def generate_weekly_report(client_id):
# Pull from your project tracking system
stats = {
"tasks_completed": get_completed_tasks(client_id),
"hours_logged": get_hours(client_id),
"upcoming_milestones": get_milestones(client_id),
"blockers": get_blockers(client_id)
}
report = f"""
📊 Weekly Status Report — Week of {datetime.now().strftime('%B %d, %Y')}
✅ Completed This Week:
{chr(10).join(f' • {task}' for task in stats['tasks_completed'])}
⏱️ Hours Logged: {stats['hours_logged']:.1f}h
🎯 Upcoming Milestones:
{chr(10).join(f' • {m}' for m in stats['upcoming_milestones'])}
🚧 Current Blockers: {stats['blockers'] or 'None'}
"""
return report
def send_all_reports():
clients = get_active_clients()
for client in clients:
report = generate_weekly_report(client['id'])
send_email(client['email'], "Weekly Status Report", report)
print(f"Sent report to {client['name']}")
# Run every Friday at 4 PM
schedule.every().friday.at("16:00").do(send_all_reports)
4. The Main Loop
def send_email(to_addr, subject, body):
msg = MIMEMultipart()
msg['From'] = 'your@gmail.com'
msg['To'] = to_addr
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
server.login('your@gmail.com', 'your_app_password')
server.send_message(msg)
# Main runner
print("Email automation bot started...")
while True:
schedule.run_pending()
time.sleep(60)
Results After 30 Days
- 3.5 hours/week saved on email
- Payment collection improved 40% — follow-ups actually happen on time
- Zero FAQ emails read by human — all handled automatically
- 12 clients receiving automated weekly reports
The Broader Toolkit
This email automation is one of the 5 scripts in my Python Business Automation Toolkit. The full toolkit includes:
- Invoice & Payment Tracker — SQLite database, PDF generation, automated reminders
- Expense Categorizer — reads bank CSV exports, sorts expenses automatically
- Inventory Monitor — tracks stock levels, emails alerts when low
- Client Report Generator — weekly automated status reports
- Email Automation Bot — the script from this article, fully packaged
All scripts are production-ready with error handling, logging, and documentation. Get the full toolkit for $29.
What's Next?
If this was helpful, follow me for more Python automation scripts. Next week I'll cover automating your entire bookkeeping with Python + pandas.
Have a specific business task you want to automate? Leave a comment below.
🔧 **Found this useful?* I build custom HN lead reports (20–50 companies with verified emails, tech stacks, 24h delivery) → Order done-for-you lead report — $75 | Got a workflow to automate? → 1-Hour Python Automation Audit — $39*
Top comments (0)