An e-mail reminder Python script
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)
