cybrkyd

An e-mail reminder Python script

 Fri, 16 Feb 2024 11:37 UTC
An e-mail reminder Python script
Python logo: python.org | This image: CC BY 4.0 by cybrkyd

I miss receiving the e-mail notifications for recurring events from my days of using the Hotmail and Gmail calendars. As most days are spent buried in e-mails, my inbox is everything: my to-do list, my schedule and of course, my e-mails.

From a privacy stance, I also have concerns about having my life’s events and important dates in the cloud, sitting on someone’s server.

In an effort to self-host everything, my solution proved to be relatively simple in the end: do it yourself in Python.

I was initially on a shared-hosting platform with Roundcube, so the option to send an e-mail for up-coming calendar events was non-existent. There is an option for a “message” to be sent for the Birthday Calendar only but I have no interest in being reminded only about birthdays…what about other events? I believe that some add-on exists somewhere but that was useless to me. Being on shared hosting, I had no way of tinkering with add-ons.

My Requirements

My solution does not forward-read my calendar. Rather, this is a static reminder solution for dates which are important — birthdays, anniversaries and things I need to do on certain dates.

My reminders are stored in a tab-delimited csv file:

Subject Occurrence
REMINDER: Check tyres   02 of every month
REMINDER: Check tyres   16 of every month
REMINDER: Car MOT due 25 September 2024 15 Jul, 15 Aug
REMINDER: Book Car Service  01 Oct, 01 Nov
REMINDER: Someone's Birthday    01 Jan
REMINDER: Someone's Anniversary 02 Jan
REMINDER: Pay that bill Last day of every month

Note the “plain English” usage in some of the lines for the Occurrence column:

Last day of every month
    and
02 of every month

That is very nice shorthand, instead of having 02 Jan, 02 Feb, 02 Mar, … etc.

The cron job

This is run once a day at 7am my time.

0 7 * * * /var/www/html/example.com/cgi-bin/rem.py >/dev/null 2>&1

E-mail Reminders with Python

The script uses smtplib for the e-mail and uses the csv module to read events from the csv file. The if / elif statements each contain the instruction to e-mail — this is on purpose to avoid the situation I ran into where only one e-mail was sent if there happened to be more than one reminder on any given date.

#!/usr/bin/env python3

import csv
import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import email.utils
import calendar

def send_email(subject, body, to_email):
    me = "bot@example.com"
    msg = MIMEMultipart('alternative')
    msg['From'] = me
    msg['To'] = to_email
    msg['Subject'] = subject
    msg['Date'] = email.utils.formatdate(localtime=True)
    part1 = MIMEText(body, 'plain', 'utf-8')
    msg.attach(part1)
    s = smtplib.SMTP('localhost')
    s.sendmail(me, to_email, msg.as_string())
    s.quit()

# Read the CSV file
file_path = '/var/www/html/example.com/cgi-bin/list.csv'
current_day = datetime.datetime.now().day
current_month = datetime.datetime.now().month
current_date = datetime.datetime.now().strftime('%d %b')
current_weekday = datetime.datetime.now().strftime('%A')

to_email = 'mail@example.com'

with open(file_path, 'r') as csvfile:
    reader = csv.DictReader(csvfile, delimiter='\t')

    for row in reader:
        subject = row['Subject']
        occurrence = row['Occurrence']

        if 'Last day of every month' in occurrence:
            last_day_of_month = calendar.monthrange(datetime.datetime.now().year, current_month)[1]
            if current_day == last_day_of_month:
                email_subject = subject
                email_body = subject
                send_email(email_subject, email_body, to_email)

        elif 'of every month' in occurrence:
            day_of_month = int(occurrence.split(' ')[0])
            if current_day == day_of_month:
                email_subject = subject
                email_body = subject
                send_email(email_subject, email_body, to_email)

        elif current_date in occurrence:
            email_subject = subject
            email_body = subject
            send_email(email_subject, email_body, to_email)

        elif current_weekday.lower() in occurrence.lower():
            email_subject = subject
            email_body = subject
            send_email(email_subject, email_body, to_email)

»

Visitors: Loading...