#!perl.exe -w =pod TITLE : omnipage.pl AUTHOR : boo_radley (theeaterofsocks@hotmail.com) DESCRIPTION : This script is designed to take the output of one or more SQL query and processes it through a series of filters, allowing it to issue template-based e-mail based on the content of that query. This script relies on the existence of a configuration file and several different directories. These items have default values, but may be renamed in the constants section of the script. The default name for the configuration file is named 'config.txt', and the default directories are "logs", "incoming", "templates","completed" and "emailtemplates". All examples and suggestion will use these default names. Descriptions of these items follow, with notes and examples following the descriptions. The directory named 'incoming' contains the output of any SQL queries which the script should act upon. This file needs to be a delimited file with no headers. The default delimiter is a comma, but this may be changed by altering the value of IncomingDivider in the constants section. The 'templates' directory contains the template files that the script uses to create e-mail messages. These template files are plain text files that make use of special tags to indicate field positions. These tags look like "[% field.0 %]", and correspond to fields within the SQL report. The 'emailtemplates' directory contains templates for creating e-mail addresses for the recipients of the script's output. In most cases, the e-mail address should The "completed' directory contains SQL reports which have been processed successfully. "config.txt" is a simple text file that lists groupings of associated files -- the contents of this file should correlate to the names of the of the SQL report files. Finally, the "logs" directory contains a logfile for each group listed in config.txt. Each time the script is run, the log file will either be created or appended to. EXAMPLE : A config.txt which contains one line, "example" indicates that there will be a file called "example" in each of the sub- directories : /templates/example /incoming/example /logs/example /completed/example /emailtemplates/example The incoming file might look like this : user@company.com,Joe,user, 2,1,TELECOM,123456,"Customer has problem with phone line" Since the recipient's e-mail address is in the SQL report, the email template is very simple : [% fields.0 %] The corresponding template file might look like the following. Notice that even though the email address has been added as one of the headers in the message due to requirements in SMTP's requirements. Any number of arbitrary headers may be added in this fashion. To: [% fields.0 %] From: MailAgent@helpdesk.com Subject: Your [% fields.5 %] ticket Dear [% fields.1 %] [% fields.2 %], Your [% fields.5 %] ticket number [% fields.6 %] regarding [% fields.7 %] has been closed. If you'd like to reopen it, call the helpdesk at 555-1212. Once finished processing, the result would an email that looks like : To: user@company.com From: MailAgent@helpdesk.com Subject: Your Telecom ticket Dear Joe User, Your TELECOM ticket number 123456 regarding "Customer has problem with phone line" has been closed. If you'd like to reopen it, call the helpdesk at 555-1212. =cut ############################################################################## # modules # use strict; use Template; use Net::SMTP; use File::Copy; use Date::Manip; ############################################################################## # constant delcarations # use constant LogPath => "logs/"; use constant IncomingPath => "incoming/"; use constant EmailMsgTemplatePath => "templates/"; use constant CompletedPath => "completed/"; use constant EmailAddressTemplatePath => "emailtemplates/"; use constant ConfigFile => "config.txt"; use constant IncomingDivider => ','; use constant SMTPServer => "your server here"; ############################################################################## # main # &Date_Init("TZ=MDT"); my $template = Template->new() or die ("Can't create template : $!"); my $paginggroups = load_paging_groups(ConfigFile); foreach my $thisgroup (@$paginggroups) { my $errorout = 0; print_log ($thisgroup, "checking $thisgroup\n for data"); my $incoming = get_incoming ($thisgroup); my $completed = CompletedPath . $thisgroup; my $emailmsgtemplate = EmailMsgTemplatePath . $thisgroup; my $emailaddresstemplate = EmailAddressTemplatePath . $thisgroup; foreach my $thisline(@$incoming) { # set up the vars for the templates. my $vars = {fields=>$thisline}; # complete email address my $emailaddress; unless ($template->process ($emailaddresstemplate,$vars,\$emailaddress)) { $errorout .="bad email address template |"; print_log ($thisgroup, "Unable to create email address from template. Template reports $!. Skipping entry\n"); #die "no process! $!"; }; # complete email message my $emailmessage; unless ($template->process ($emailmsgtemplate,$vars,\$emailmessage)) { $errorout .="bad email message template |"; print_log ($thisgroup, "Unable to create email message from template. Template reports $!. Skipping entry\n"); #die "no process! $!"; }; #debug email address $emailaddress = "debug@domain.com"; # issue email unless the address or message creation failed. unless ($errorout){ print_log ($thisgroup, "issuing mail for ", join (",",@$thisline),"\n"); my $smtp= Net::SMTP->new(SMTPServer ) or die ("Can't create smtp object - $!"); $smtp->mail($ENV{USER}); $smtp->recipient ($emailaddress); $smtp->data(); $smtp->datasend($emailmessage); $smtp->dataend(); $smtp->quit; # log. } } if ($errorout) { print_log ($thisgroup, "Unable to complete $thisgroup\n"); }else{ archive_incoming ($thisgroup); } $errorout || print_log ($thisgroup, "finished with $thisgroup\n"); } ############################################################################## # support routines # ############################################################################## sub load_paging_groups { print "here is $_[0]\n"; open FH, $_[0] or die "can't open groups : $!"; my @lines = ; chomp $_ foreach @lines; close FH; print "in load paging @lines\n"; return \@lines; } ############################################################################## sub get_incoming { die "nothing to get_incoming" unless @_; my @lines; open INCOMING, IncomingPath . $_[0] or die "can't open incoming file $_[0]!"; # # read past 2 lines for sql report headers. # ; ; while () { # all the extra syntax in the regex enables the use of a constant # $string =~ m /@{[ CONST ]}/; my @line = split /@{[IncomingDivider]}/, $_; push @lines, \@line; foreach (@line) {s/^\s+//; s/\s+$//}; # trim leading and trailing whitespace } close INCOMING; return \@lines; } ############################################################################## sub archive_incoming { my $filename = shift or die "no file name passed to archive_incoming!"; my $ts = UnixDate("now","%q"); # %q format : %Y%m%d%H%M%S : 19961025174058 my $backup = CompletedPath.$ts.$filename; print "\n--$backup--\n"; copy (IncomingPath.$filename, $backup) or die "can't copy! $!"; } ############################################################################## sub print_log { my $thisgroup = shift or die "no group name to print_log!"; open LOGFILE, ">>",LogPath . $thisgroup; print LOGFILE UnixDate("now","%q"),"\t@_"; close LOGFILE; }