2023-02-10
Since I cannot keep everything I have to remember in my head, I need a reminder system. While I would prefer an analog system (ideally one that integrates with my system for keeping track of tasks), I have not found a satisfying analog solution so far.
I am not looking for a full-fledged calendar system. If I were, I would be using
Remind or calendar.1 But
they offer way more features than I need.
I basically have two requirements for my reminder system:
The solution I have come up with is almost too trivial to share: It employs
cron and at to schedule reminders, which are sent as e-mails via a remote
SMTP server when they are due.
The system depends on the following ingredients:
smtpd – for relaying e-mails to a remote SMTP server.cron – for scheduling recurring reminders (like birthdays).at – for scheduling nonrecurring reminders (like one-time events, or events
which recur in irregular intervals).mail – for sending e-mails non-interactively.On OpenBSD, all the required software is part of the base system; see smtpd(8), cron(8), at(1), mail(1).
Both cron and at basically take two kinds of data as input: A timestamp
which specifies when something is to be done, and an action which specifies
what is to be done at the specified time.
Regardless of whether a reminder is recurring or nonrecurring, I want an e-mail
to be sent to me at the specified time. Therefore, the action in both cases is
sending an e-mail to me reminding me of the given event. Since the e-mail needs
to be sent non-interactively when the given time is reached, the mail utility
is invoked, and the reminder text is passed to it as the mail subject (since
they are usually short, I only specify a subject and leave the body empty; then
I don’t even have to open the e-mail).
In order not to have to specify the non-changing details (like the e-mail
address) for sending the mail each time, I employ a small script called
mailrem which is basically a wrapper around mail which takes the reminder
text as its argument:
#!/bin/sh
from="John Doe <john.doe@email.com>"
subject="$1"
echo | mail -r "$from" -s "$subject" "$from"
Finally, in order for mail to be able to send mails to a remote SMTP server,
smtpd needs to be xref:smtpd-relay[configured such that it relays outgoing
mail to a remote server].
E-mail reminders are sent by calling mailrem with the specific reminder text
as its argument, e.g.
$ mailrem "Prepare tax statement"
In order to schedule reminders for a specific time, mailrem is not invoked
directly as above, but either by cron or by at, depending on whether the
reminder is to be sent on a regular basis or just once.
Recurring reminders are scheduled by cron via corresponding crontab entries.
Start editing the crontab file:
$ crontab -e
Then add an entry for each recurring reminder like this:
0 0 3 18 * $HOME/bin/mailrem "[Reminder] Paul's $(( $(/bin/date +\%Y) - 1976 )). birthday (1976)"
This entry would send an e-mail each year at midnight on March 18 with subject
“[Reminder] Paul’s n. birthday (1976)”, where n is calculated each time
the cron entry is triggered by subtracting Paul’s year of birth, 1976, from the
current year obtained by the date utility.3
Nonrecurring reminders are scheduled by at via corresponding atjobs. For
instance, to schedule an atjob for midnight in three days:
$ at midnight + 3 days
When prompted, enter the action to be executed at the specified time like this:
> mailrem "[Reminder] Doctor's appointment at 9 am"
Then, press <Ctrl> + D to queue the atjob.
That’s it. A very simple system which does its job and is easy to setup and maintain.
crontab -l could be used.
Similarly, atq displays the queue of atjobs. However, the output of atq is
pretty much unparseable (at least in the version which ships with OpenBSD). So
one would have to manually extract the job ID from the output of atq and
then do $ at -c <id> in order to see the content of the job.cron daemon is not running at the
time a reminder is due, it will not be sent and will subsequently be lost
forever.Man page of the OpenBSD version: calendar(1) ↩
In principle, of course, it is also possible to run the system on a laptop. The severe drawback would be that reminders were lost if the laptop were not running at the scheduled time of a reminder. One could use tools like anacron instead of cron. This would mitigate the risk of losing reminders, but the time they are sent would then depend on when the laptop is running (which may differ greatly from the intended time of sending). ↩