Monday, June 18, 2012

Shell script to send birthday reminder e-mails



   In a professional work place, it is pretty common to celebrate the birthdays of your colleagues. Somebody in the team will have the birthdays maintained in a file and they will let the team know when the day arrives. The issue here is it is quite possible to miss out if one forgets to check the birthday file. How nice it will be if you can get an e-mail reminder of the person celebrating their birthday? Let us see in this article how to create a shell script which will send us an e-mail stating the names of the people celebrating their birthdays. Also, the same script with little modifications can be used to set reminder for any other purpose.

  This article discusses about 3 scripts:
  • Shell Script to get reminder on the list of users having their birthday today.
  • Shell  Script to get reminder on the list of users having their birthday the next day or some other day.
  • Shell  Script to get reminder on the list of all users having their birthday over the next n days.
1. Shell Script to send e-mail reminder about the persons celebrating their birthday today:

 a. A csv data file should be created manually by the user with the birthday details in the following format:
     Ex: <user name>,<birth-date in DD-MON[-YYYY]>

    A sample birthdays date file will be like this:
$ cat bday.csv
User1,16-jun-1990
User2,07-Jul-1989
User3,15-Jun-1995
User4,15-Jun
     2 things to be noted:

  • Month is not case sensitive
  • the year is optional.

b. Bash Shell Script to send the reminder mail.
$ cat bday.sh
#!/bin/bash

#Setting the initial variables

IFILE="$HOME/bday.csv"
OFILE="bday_out"$$
MAILID="guru@xyz.com"

# Retrieving today's date and month

DAT=`date '+%d %b'`
DAY=${DAT:0:2}
MON=`echo ${DAT:3:3} | awk '{print toupper($0);}'`

# Reading the bday.csv file and finding the users whose 
# date matches with today and writing to OFILE

while IFS=",-" read name day month year
do
        day=`printf "%02d\n" $day`
        month=`echo $month |  awk '{print toupper($0);}'`
        if [ $day -eq $DAY -a $month = $MON ]
        then
             echo $name
        fi
done < $IFILE > $OFILE

#If OFILE has some data, header is added and the file
#is mailed to the respective users in MAILID.

if [ -f $OFILE -a -s $OFILE ]
then
   sed -i '1i The following users celebrate their birthday:\n' $OFILE
   mailx -s "Birthday on: $DAT" $MAILID  < $OFILE
   \rm $OFILE
   echo "Birthday mail sent"
else
   echo "No birthdays today"
fi
Note: In the IFILE variable, give the full path of the input file.

c. Give execute permission to this script:
$ chmod 755 bday.sh
d. Include this script as part of your profile file. By including this in profile file, the moment you log-in to your user account, this script gets executed and the e-mail will be sent. Check here to know the appropriate profile file for your shell:
  In my case, the profile file :  $HOME/.bash_profile since my default shell is bash. Adding the below line at the end of the .bash_profile:
$HOME/bday.sh
e. The e-mail sent to the user will be in the following format:
Subject: Birthday on: 16 Jun
Content:
    The following users celebrate their birthday :
     User1
f. The following are the customizations which you need to make in the script:
  • Assign your input file against the variable IFILE.
  • Assign your e-mail id against the variable MAILID. If you want this mail to be sent to multiple-mail id's, you can assign multiple mail id's to the MAILID variable separated by space.

2. Shell script to send an e-mail reminder of those having birthday the next day, i.e tomorrow

    The earlier script will only take into account of those having their birthdays the same day. To get the list of users celebrating their birthday tomorrow, only one change is to be made to the earlier script:
In place of the line:
DAT=`date '+%d %b'`
Replace with:
DAT=`date '+%d %b' -d "1 day"`
    This above command will give the date of the next day. The rest of the script will remain exactly the same. Similarly, to get the list of users whose birthday is after 2 days, in place of "1 day", simply put "2 days". Refer here to know more about the date GNU functions.

3. Shell script to get the list of all users celebrating their birthdays in the next 5 days:
    Follow the remaining steps as in example 1 with only the script from below:
#!/bin/bash

LIMIT=5
IFILE="$HOME/bday.csv"
OFILE="bday_out"$$
MAILID="guru@xyz.com"

for((i=1 ; i<=$LIMIT; i++))
do
    arr[$i]=`date '+%d-%b' -d "$i days"`
done

while IFS=",-" read name day month year
do
    for DAT in ${arr[@]}
    do
       DAY=${DAT:0:2}
       MON=`echo ${DAT:3:3} | awk '{print toupper($0);}'`
       day=`printf "%02d\n" $day`
       month=`echo $month |  awk '{print toupper($0);}'`
       if [ $day -eq $DAY -a $month = $MON ]
       then
         echo $name : $DAT
         break;
       fi
    done
done < $IFILE > $OFILE

if [ -f $OFILE -a -s $OFILE ]
then
   sed -i '1i The users celebrating their birthday are:\n' $OFILE
   mailx -s "Birthday List: " $MAILID  < $OFILE
   \rm $OFILE
   echo "Birthday mail sent"
else
   echo "No birthdays."
fi
Note: The LIMIT variable contains the value of n. If n is 5, the script will retrieve the birthdays of all users falling in the next 5 days excluding today.
Related Posts Plugin for WordPress, Blogger...

2 comments:

  1. How DO I have to change this

    [ $day -eq $DAY -a $month = $MON ]

    to also recognize the year? Even if it wouldn´t make sense with birthdays?

    ReplyDelete
    Replies
    1. Something like this:
      [ $day -eq $DAY -a $month = $MON -a $year = $YEAR ]

      Delete