2026-07-15

How do I schedule an email to send at a certain time using cron and smtp, in python?

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

How do I schedule an email to send at a certain time using cron and smtp, in python?

How to Schedule Emails Using Cron, SMTP, and Python: A Developer's Guide

Sending emails automatically at specific times is a common requirement for many applications—think daily reports, weekly digests, or automated notifications. While Python is an excellent choice for scripting this task due to its simplicity and rich library ecosystem (like smtplib), scheduling the execution requires leveraging the operating system's built-in tools, primarily cron.

This guide will walk you through setting up a robust system where a Python script handles the email delivery and the cron daemon ensures it runs exactly when you need it to.

Understanding the Architecture: Python Meets Cron

The key concept here is separating the task (sending the email) from the scheduler (when the task runs). Your Python script will be the worker, and cron will be the clock.

Step 1: Refine the Python Email Script

Before scheduling, we need a reliable script that can handle all necessary operations, including attachments. We will use the built-in smtplib for sending and the email package to construct MIME messages, which is essential for handling attachments correctly.

Here is an improved example demonstrating how to attach a file:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os

def send_scheduled_email(recipient, subject, body, attachment_path):
    """Sends an email with an attachment."""
    try:
        # --- Configuration ---
        smtp_server = 'smtp.gmail.com'
        smtp_port = 587
        sender_email = 'your_email@gmail.com'
        password = 'your_app_password' # Use environment variables in production!

        # 1. Setup the message container
        msg = MIMEMultipart()
        msg['From'] = sender_email
        msg['To'] = recipient
        msg['Subject'] = subject

        # 2. Attach the body text
        text = f"Here is your scheduled report.\n\n{body}"
        msg.attach(MIMEText(text, 'plain'))

        # 3. Handle Attachment (if file exists)
        if attachment_path and os.path.exists(attachment_path):
            with open(attachment_path, "rb") as file:
                part = MIMEBase('application', 'octet-stream')
                part.set_payload(file.read())
                encoders.encode_base64(part)
                filename = os.path.basename(attachment_path)
                part.add_header('Content-Disposition', f"attachment; filename={filename}")
                msg.attach(part)

        # 4. Connect and Send
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.starttls()
        server.login(sender_email, password)
        text = msg.as_string()
        server.sendmail(sender_email, recipient, text)
        server.quit()

        print(f"Successfully sent email to {recipient}")

    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    # Define the task parameters for this run
    recipient_email = 'target@example.com'
    email_subject = 'Automated Report'
    email_body = 'This email was sent successfully via cron job.'
    attachment = '/path/to/your/report.pdf' # Make sure this path is correct

    send_scheduled_email(recipient_email, email_subject, email_body, attachment)

Step 2: Scheduling with Cron

Once you have a working Python script (let's assume you save it as send_email.py), you use cron to tell the operating system when to execute it.

  1. Find the Python Executable Path: Determine the exact path to your Python interpreter (e.g., /usr/bin/python3).
  2. Edit Crontab: Open your crontab file for editing by running crontab -e.
  3. Add the Schedule: Add a line defining the schedule and the command. The format is: Minute Hour DayOfMonth Month DayOfWeek Command.

If you want to run the script every day at 9:00 AM, you would add this line:

# m h dom mon dow command
0 9 * * * /usr/bin/python3 /path/to/your/send_email.py >> /var/log/email_schedule.log 2>&1

Explanation of the Cron Entry:

  • 0 9 * * *: This means "at minute 0, hour 9, every day of the month, every month, every day of the week." (i.e., 9:00 AM daily).
  • /usr/bin/python3 /path/to/your/send_email.py: This is the exact command to execute—calling the Python interpreter followed by your script.
  • >> /var/log/email_schedule.log 2>&1: This redirects all output (both standard output and errors) into a log file, which is crucial for debugging scheduled jobs.

Best Practices and Advanced Considerations

When dealing with scheduled tasks in production environments, several best practices must be followed:

  1. Security Over Credentials: Never hardcode email passwords directly into scripts. Use environment variables or secure secret management services to store sensitive data (like the SMTP password). This aligns with modern security principles seen in frameworks like those championed by Laravel where configuration is managed securely.
  2. Error Logging: As demonstrated above, always redirect output and errors to a log file. If the cron job fails, you need a record of why it failed.
  3. Handling Long-Running Tasks (Asynchronous Jobs): For more complex, long-running, or high-volume scheduled tasks, relying solely on simple system cron jobs can be fragile. A more robust approach is to use dedicated task queues (like Redis or RabbitMQ) combined with a dedicated worker process. This pattern ensures that if the script fails mid-execution, the job can be retried reliably without relying solely on the operating system's scheduler for complex state management.

By combining Python’s powerful scripting capabilities with the reliability of cron scheduling, you can create an efficient and automated email delivery system.

Tags:

Enhance your marketing setup with your own email marketing platform.

Join the growing number of SaaS platforms using Laravel Mail to offer email marketing solutions to their customers.