Sunday, 31 August 2014

Generate mail in bulk using Windows' cmd tool

With all the fancy software out there, it is often easy to overlook simple tools that work just as well. In this article we explore the use of cmd shell scripting to generate mail for a list of recipients.

You are the boss of a small company. You just received the year's sales figures, and you realize 50 of your employees have no been meeting targets. Enraged, you decide to deduct their salary. Formality dictates that you must write letters to them. You start out with a template:

Dear [Employee Name] (ID: [Employee ID]),
  This is to inform you that your salary
  has been permanently deducted. If you
  are not happy, by all means, resign.
Boss

And start to fill out the names one by one, referring to a special list you have been keeping (Employee name, employee ID, % of sales target achieved):

John 10010 40%
Jane 10011 78%
James 10012 90%
Jack 10013 10%
Jill 10014 0%
...

For brevity only the first five names are shown. After an hour, finally you managed to fill out all the letters, and print them out. One hour! You missed a meeting with an important client!

Is there a better way? The answer is a resounding yes.

All Boss needs is a batch file:

makemail.bat

@echo off
for /f "tokens=1,2" %%a in ('more') do (
        echo Dear %%a ^(ID: %%b^), >> %%a.txt
        echo   This is to inform you that your salary >> %%a.txt
        echo   has been permanently deducted. If you >> %%a.txt
        echo   are not happy, by all means, resign. >> %%a.txt
        echo Boss >> %%a.txt
        )


and the employee list above:

employees.txt

John 10010 40%
Jane 10011 78%
James 10012 90%
Jack 10013 10%
Jill 10014 0%
...


keeping them in the same folder.

Then, from the Explorer window of the folder, go to File > Open command Prompt. Alternatively, launch cmd: Start > Run > cmd > OK and navigate to the folder using cd foldername.

Use the following command:

type employees.txt | makemail.bat

and that's it! Some 50 files are immediately generated, ready for printing!

Let's explore what each step does.

The batch file containes a for loop:

@echo off
for /f "tokens=1,2" %%a in ('more') do (
        echo Dear %%a ^(ID: %%b^), > %%a.txt
        echo   This is to inform you that your salary >> %%a.txt
        echo   has been permanently deducted. If you >> %%a.txt
        echo   are not happy, by all means, resign. >> %%a.txt
        echo Boss >> %%a.txt
        )


The first line, @echo off, turns off command echoing in the command prompt. The easiest way to find out why is to try leaving out that line. The output won't be pretty :)

Next comes the for loop. The /f switch tells cmd to match against files (don't worry about it), and the "tokens=1,2" option string tells cmd to take only the first and second tokens of the employees.txt file (that would be the employee name and id, but not the sales target).

%%a is simply a parameter, which will be replaced by cmd as it iterates through the loop. ('more') tells the script to retrieve more input from the standard input (more on this below). The do (...) clause contains the actions that should be executed for each iteration of the loop.

echo simply outputs the contents to the standard output, and >> appends the output to a file. Note that in the first line, > is used instead, which means replace all contents in the file. This would ensure that, if the script were to be executed a second time, the mail will be rewritten instead of being appended to the end of the existing mail.

%%a and %%b are special variables that are replaced by the for loop every iteration. Suppose the option string had been "tokens=1,2,3", %%c would contain the sales target for each employee. Similarly, if we used "tokens=1" then %%a will contain the employee name and the other registers (%%b through %%z) would be empty.

With that in mind, let's move on to the command:

type employee.txt | makemail.bat

The type command is used to send the contents of a file to the standard output. The | pipe is used to redirect the standard output of the previous command to the standard input of the next command. Thus, each line of the employee.txt is sent to makemail.bat, which retrieves it via the 'more' command. Notice that the more is surrounded with '', which executes the command and substitutes the result in place.

What will Boss find after he executes the script? 50 files, ready for printing, each named suitably by name:

John.txt
Jane.txt
James.txt
Jack.txt
Jill.txt
...


Now he can even modify each letter to add a personal insult for particularly disagreeable employees. "Hey, that was easy! Now I can fire more employees at will!" exclaims Boss.

No comments:

Post a Comment