Reminder

This is a method for keeping a list of important dates and events and sending out email reminders when they are about to occur.
reminder.zip

Overview

Email Reminder
The main part of the program is sending out an email notification when an event is scheduled to occur. This way I don't have to remember important dates myself (because I am really, really horrible at it). I don't even have to remember to put them on my calendar each year. I'll be emailed them automatically. For example:
To: tommut@csh.rit.edu
Subject:  Reminder: Wedding anniversary 
Date: Sat, 6 Aug 2005 00:01:02 -0500 (EST)

The following event occurs on 08-08-2005:
  Wedding anniversary -- Anniversary of our wedding  - 08/08/04
Event List
In order to be reminded about events, we need to keep a list of events that you wish to remember and be reminded about. This is stored in XML format:
<reminders>
 <entry>  
   <date>01-11</date>
   <name>Tom's b-day </name> 
   <info>It's my birthday, yo.  01/11/1978</info>
   <notify-days-before>0</notify-days-before>
   <occurrence>ALL</occurrence>
 </entry> 
 <entry>
   <date>02-14</date>
   <name>Valentine's Day</name>
   <info>Remember to get something special for the little lady</info>
   <notify-days-before>1</notify-days-before>
   <occurrence>ALL</occurrence>
 </entry>
 <entry>
   <date>08-08</date>
   <name>Wedding anniversary</name>
   <info>Anniversary of our wedding  - 08/08/04</info>
   <notify-days-before>2</notify-days-before>
   <occurrence>ALL</occurrence>
 </entry>
</reminders>
You see that each entry is composed of the date that the event falls on, along with the name of the event, and any additional info about the event. If the month of the date is set to a wildcard, such as "*-15", then that means that this event reoccurs on the same day of every month -- in this case Jan 15, Feb 15, etc. The notify-days-before field represents the number of days in advance of the event that a reminder will be sent. If 0 is specified, you will be notified on midnight of the date of the event. If you want to be notified a week in advance, you would put 7. The occurrence field is how many times the reminder occurs: ALL if it occurs every year, or ONCE for a one-time-only event.

Then when an event is scheduled to occur, an email notice will be sent to you. Also, on the first of each month an email reminder will be sent with a cumulative list of all events occurring that month.

Adding Events
I wanted to make an easier way of adding events rather than having to log in to the mail server machine and update the xml directly. To update events you can send an email to yourself with the keyword REMINDER in the Subject of the email.
Add: To add an event, send an email with all of the event information delimited by "::", like so:
REMINDER add::04-26::Cindy's Birthday::Cindy's Birthday - born 04/26/1968::2::ALL
This will add this entry to your list of events and you will be sent a reminder when it occurs.

Remove: To remove an event, send an email with the date and part of the name of the event that should be removed:
REMINDER remove::04-26::Cindy
This will remove the matching entry (if it exists) frome your list of events; you will no longer be sent a reminder when it occurs.

List: You can also have a list of all current events mailed to you by sending an email with the following in the header:
REMINDER list
This will send you an email with all your events, like so:
To: tommut@csh.rit.edu
Subject:  Reminder: list events
Date: Thu, 13 Jan 2005 17:05:02 -0500 (EST)

01-11 -- Tom's b-day -- Birthday, yo.  01/11/1978 -- 0 -- ALL
02-14 -- Valentine's Day -- vday -- 1 -- ALL
04-26 -- cick's b-day -- Cindy's birthday - Apr 26, 1975 -- 0 -- ALL
04-28 -- Tubb's b-day -- It's Tubb's B-day; give him food -- 0 -- ALL
07-20 -- Mom's b-day -- Nance's birthday -- 0 -- ALL
08-08 -- wedding anniversary -- anniversary of our wedding  - 08/08/04 -- 2 -- ALL

Implementation

The solution was composed of three parts:
  1. Java code that:
    a) goes through the current list of events and sends out email notification when neccessary
    b) handles updates and modifications of the list of events
  2. An entry in the crontab that kicks off the java code each day.

  3. And an entry in my .procmailrc that handles event requests.
Java code
The code consists of three classes:
Reminder - this handles checking the list of events and sending out email reminders when needed.
ReminderHandler - this handles receiving event modification requests such as Add, Delete, List, and updating the list of events accordingly.
ReminderConstants - this file contains constants that would need to be modified, such as notification email address, SMTP mail server, path to the date files, etc. This should be the only file that needs modified.

Event List Handling
In order to handle the email requests for adding, removing, and listing events, I had to add a recipe to my .procmailrc to handle this. Essentially it checks for an email with myself as a sender, which also contains the text "REMINDER" in the subject. If that is a match, then it writes the action in the subject to a file (reminderActions.txt) that will be later handled by Java code. (Note that this step is optional; you could instead just keep the reminder event xml file updated by hand).

.procmailrc:
TESTDIR=/u4/tommut/test
REMINDERDIR=/u4/tommut/src/java/Reminder/reminder
#An auxiliary regular expression to detect text,
#The brackets [] contain a space and a tab
GETTEXT="[  ]*\/[^  ].*"

# this checks incoming mail to see if it is from me and
# has REMINDER in the subject - this adds it to my reminder 
# action queue
# flags - c means to continue after running this recipe
#       - D means to make the regexp case-sensitive
:0Dc:${REMINDERDIR}/Proctest.mail.lock
* ^Subject.*REMINDER
* ^From.*tommut@csh.rit.edu*
* $ ^Subject:${GETTEXT}
| echo "${MATCH}" >> ${REMINDERDIR}/reminderActions.txt

Task Scheduling
I then needed to schedule my reminder task(s). I set up some entries in my crontab. I set up one entry to run the ReminderHandler Java code; this is what looks for any event updates in the reminderActions.txt and then modifies the list of events accordingly. I set this to run every hour.
Then the other event is set to run the Reminder Java code that looks through the events and sends out any neccessary email notifications. I scheduled this to run at midnight every night.

crontab:
# process any reminder commands (top of every hour)
0 * * * * java -cp $HOME/src/java/Reminder reminder/ReminderHandler
# send out any reminders for the day (12:01am)
1 0 * * * java -cp $HOME/src/java/Reminder reminder/Reminder