Article 2119 of alt.sources: Xref: feenix.metronet.com alt.sources:2119 Newsgroups: alt.sources Path: feenix.metronet.com!news.utdallas.edu!hermes.chpc.utexas.edu!cs.utexas.edu!uunet!spool.mu.edu!agate!headwall.Stanford.EDU!unixhub!jupiter.SLAC.Stanford.EDU!jfm From: jfm@jupiter.SLAC.Stanford.EDU (John F. McGowan) Subject: junkmail - a Perl script for customized mass e-mailing Message-ID: Keywords: Perl e-mail custom mailer Sender: news@unixhub.SLAC.Stanford.EDU Organization: Stanford Linear Accelerator Center Date: Fri, 22 Oct 1993 05:04:00 GMT Lines: 1637 Below is a shell archive generated using shar containing junkmail, a Perl script for generating custom mailings, some example files, some documentation on the program, and a README file. junkmail contains an embedded manpage following the convention in Programming Perl by Larry Wall and Randal L. Schwartz. Despite the title, the Internet does frown on unsolicited mass mailings particularly for commercial purposes. Please exercise caution in using junkmail. Please send comments, bug reports and so forth to jfm@jupiter.slac.stanford.edu. - John McGowan ------------------------------->CUT HERE<------------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'README' <<'END_OF_FILE' X junkmail: An Automatic E-Mail Message Generator X by John F. McGowan (jfm@jupiter.slac.stanford.edu) X X This README note is copyright (C) 1993 by John F. McGowan X XIntroduction: X X Junkmail is a Perl script to automate sending customized letters Xto multiple e-mail addresses, referred to as targets. The custom Xinformation for each target such as name, e-mail address, and so forth Xis represented as a record in a database. Each database record consists of Xnamed database fields. Key fields (used to uniquely identify the record) are Xtagged by a traling asterisk. The fields are ASCII strings. Database records Xare entered using a data entry form. X X Junkmail works from a template file that contains special instructions Xthat junkmail replaces with dates, the values of database fields, and Xso forth. X X Junkmail can be used to send customized cover letters and resumes Xto companies that have posted job listings in Internet jobs groups such as Xmisc.jobs.offered, to send customized mailings to a group of friends or Xassociates, to send customized mailings to co-workers, to send customized Xmailings to a group of customers, and so forth. X XData Entry Form: X X A junkmail data entry form consists of a text file. Each line of Xthe file is used for entering one database field. The form consists of Xthe database field name (with trailing asterisk for key fields), a colon, Xat least one space, followed by the value entered by the user. An editor Xsuch as vi or emacs is used to edit the form. Junkmail uses the environment Xvariable EDITOR to set the editor used to edit the form. The form is Xspecified with the -f flag. X X There are other ways to enter data such as the -t text Xdatabase entry method. However, the data entry form is the easiest. X XJunkmail Template File: X X A template is a template for a mailing, such as a cover letter Xand resume. The template tells junkmail how to generate a custom Xmailing for each target basd on the contents of the database. XJunkmail interprets certain text strings specially however and Xsubstitutes appropriate values in there place. $database-field-name Xis replaced by the value of the database field for that record. X#macro# indicates a built-in macro or command, such as #date# which is Xreplaced by today's date. #particle# is replaced by a or an depending Xon the next word's first letter (consonant or vowel). X X#if $field eq /something/ XHello there. X#endif X Xis used to include the body (Hello there.) if the field matches something. X X#include "my.propaganda" X Xincludes another file in the mailing. X XDocumentation: X X This README file. X X junkmail -h outputs a short help listing the junkmail flags. X X junkmail contains documentation in the form of Perl comments and Xan embedded manpage following the convention in Programming Perl by Larry XWall and Randall Schwarz. To install the manual page, X X cp junkmail junkmail.1 X mv junkmail /your/man/man1 (and) X setenv MANPATH MANPATH:/your/man (C shell). X X junkmail contains embedded nroff commands that cause the Perl Xcode to be ignored by man. X XArchive Contents: X X README (this file) X junkmail - the Perl script itself X entry - a sample data entry form X template - a sample template file X sample.resume - a sample include file used by template X sample.text - a sample ASCII text database X manual - Programmer's Manual and Reference X XWarning Note: X XThe Internet community frowns on mass mailing campaigns. I developed Xjunkmail to reply to postings in the Usenet jobs newsgroups. These Xpostings SOLICIT a reply. In general, it is good etiquette to use Xjunkmail to send letters to people who have solicited a message, to Xfriends, to coworkers at your organization, and others who will not be Xoffended by receiving a mailing. X XCopyright: X Xjunkmail is copyright (C) by John F. McGowan. This software may be Xmodified and distributed but the copyright notice and the disclaimer Xmust be retained. X XDisclaimer: X XThis software is distributed as is. There is no warranty, either Xexpress or implied, that it will work correctly or as desired. In other Xwords, use at your own risk. X X X X X X END_OF_FILE if test 4139 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'junkmail' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'junkmail'\" else echo shar: Extracting \"'junkmail'\" \(24949 characters\) sed "s/^X//" >'junkmail' <<'END_OF_FILE' X#!/usr/local/bin/perl X'di'; X'ig00'; X# X# Name: junkmail X# Date: $Date: 1993/10/22 04:53:40 $ X# Version: $Revision: 1.20 $ X# Author: John F. McGowan ($Author: jfm $) X# X# Description: junkmail automates sending custom mailings to X# multiple e-mail addresses (referred to as targets). The mailings X# are customized using a database record for each target. The user X# can specify database fields for information such as the target X# name, organization, favorite color, political orientation, etc. X# junkmail expects a database field named 'e-mail' to exist which X# is the e-mail address of the target. X# X# junkmail supports database record entry using a simple user-defined X# Data Entry Form. It also supports data entry from a text database X# file using the ASCII quoted field format used by common word X# processors such as Microsoft Word. junkmail expects key field X# names to be terminated with an asterisk. The trailing asterisk X# is treated specially by junkmail. X# X# junkmail can save the database entries in the ASCII text file format X# if desired. X# X# junkmail can also save the database in a DBM format file. X# X# junkmail is written in Perl (Practical Extraction and Report X# Language). Perl was written by Larry Wall. Good sources of X# information on Perl are "Programming Perl" by Larry Wall and X# Randal L. Schwartz and the comp.lang.perl newsgroup. X# X# junkmail comes in a shell archive (junkmail.shar) containing the junkmail X# source code, a README file of information on junkmail, a sample X# template file, a sample include file used with the sample X# template, a sample data entry form, a short Programmer's Manual X# and reference to assist customizing/upgrading junkmail for your X# needs, and a sample ASCII text database file. junkmail contains X# an embedded manpage following the convention in Programming Perl X# by Larry Wall and Randal L. Schwartz. X# X# Revision Record: X# X# $Log: junkmail,v $ X# Revision 1.20 1993/10/22 04:53:40 jfm X# 1. Improve -h help message. X# X# Revision 1.19 1993/10/22 04:37:38 jfm X# 1. Junkmail now prompts for a data entry method is one was not X# specified with the command line arguments. X# X# Revision 1.18 1993/10/22 03:45:25 jfm X# 1. Remove the -r flag. This is obsolete. X# X# Revision 1.17 1993/10/22 03:32:03 jfm X# *** empty log message *** X# X# Revision 1.16 1993/10/20 05:28:12 jfm X# 1. cleaned up a bit, removed send_letter subroutine X# X# Revision 1.15 1993/09/21 19:30:28 jfm X# #if now should handle key fields (trailing asterisk) correctly X# X# Revision 1.14 1993/09/21 18:51:24 jfm X# 1. Added documentation on template file to manpage X# 2. Added some protection against using binary file where text file X# is expected. X# 3. couple minor changes X# X# Revision 1.13 1993/09/16 23:44:54 jfm X# 1. Add code to check that form file is a text file X# X# Revision 1.12 1993/09/16 23:36:31 jfm X# 1. Added code to check if template file is a text file. Aborts if the X# template file is binary. X# X# Revision 1.11 1993/07/23 20:53:28 jfm X# 1. Added support for storing records in a DBM database file. Kind of X# kludgy -- hope to improve. X# X# Revision 1.10 1993/06/10 02:28:14 jfm X# 1. Added code to prompt for name of text database save file if not specified on command line. X# X# Revision 1.9 1993/06/03 22:02:25 jfm X# 1. Added copyright notice to manpage X# X# Revision 1.8 1993/05/23 18:23:28 jfm X# Slight improvement to the manpage at end of script. X# Note that manpage is accessed by creating a link junkmail.1 in manpages X# directory to the actual junkmail script file. X# X# Revision 1.7 1993/05/23 18:18:36 jfm X# Added embedded manpage at end of script X# X# Revision 1.6 1993/05/22 21:35:24 jfm X# Try to add a revision record using the $Log: junkmail,v $ X# Revision 1.20 1993/10/22 04:53:40 jfm X# 1. Improve -h help message. X# X# Revision 1.19 1993/10/22 04:37:38 jfm X# 1. Junkmail now prompts for a data entry method is one was not X# specified with the command line arguments. X# X# Revision 1.18 1993/10/22 03:45:25 jfm X# 1. Remove the -r flag. This is obsolete. X# X# Revision 1.17 1993/10/22 03:32:03 jfm X# *** empty log message *** X# X# Revision 1.16 1993/10/20 05:28:12 jfm X# 1. cleaned up a bit, removed send_letter subroutine X# X# Revision 1.15 1993/09/21 19:30:28 jfm X# #if now should handle key fields (trailing asterisk) correctly X# X# Revision 1.14 1993/09/21 18:51:24 jfm X# 1. Added documentation on template file to manpage X# 2. Added some protection against using binary file where text file X# is expected. X# 3. couple minor changes X# X# Revision 1.13 1993/09/16 23:44:54 jfm X# 1. Add code to check that form file is a text file X# X# Revision 1.12 1993/09/16 23:36:31 jfm X# 1. Added code to check if template file is a text file. Aborts if the X# template file is binary. X# X# Revision 1.11 1993/07/23 20:53:28 jfm X# 1. Added support for storing records in a DBM database file. Kind of X# kludgy -- hope to improve. X# X# Revision 1.10 1993/06/10 02:28:14 jfm X# 1. Added code to prompt for name of text database save file if not specified on command line. X# X# Revision 1.9 1993/06/03 22:02:25 jfm X# 1. Added copyright notice to manpage X# X# Revision 1.8 1993/05/23 18:23:28 jfm X# Slight improvement to the manpage at end of script. X# Note that manpage is accessed by creating a link junkmail.1 in manpages X# directory to the actual junkmail script file. X# X# Revision 1.7 1993/05/23 18:18:36 jfm X# Added embedded manpage at end of script X# keyword X# X# Xrequire "getopts.pl"; X X$| = 1; X X&Getopts('f:s:d:b:t:c:mhc'); # -f -s -d -b -c take argument X X# set umask for process so only user can access files created Xumask 077; X X# associative array of built in macros X# key is macro name; value is perl subroutine to call X%builtin = ( X 'date', 'GetDate', X 'particle', 'Particle', X '$1' , 'Evaluated Wrong', # test entry X); X# list of reserved words used by template facility X%reserved = X( X 'include', 'INCLUDE', X 'if' , 'IF', X 'endif', 'ENDIF', X); X Xif($ENV{'EDITOR'}) X{ X $myeditor = $ENV{'EDITOR'}; X} Xelse X{ X $myeditor = 'emacs'; X} X X# handle processing command line arguments below Xif($opt_h) X{ Xprint <<'EOF'; X junkmail X X Automatically generates a custom mailing and mails this Xto a list of e-mail addresses, known as targets. Each target is Xrepresented as a record in a user-defined database which can include Xvarious information specific to the target. X X Command Line Flags: X X -h Help (this message) X -m Automatically mail to targets that X have a field 'e-mail' in record. X -d Filename Read text database of addresses from X Filename. X -b Use DBM file with database of mailing X targets. X -t Filename Generate mailing from template X contained in Filename. X -f Filename Use form in Filename to enter data. X -s Filename Save the database of targets to a File X Filename in Text Database Format. X -c User Send copy of each mailing to User. X XEOF Xexit; X} # end of processing help -h flag X Xif(!($opt_f || $opt_d)) X{ X print "You have not specified a data entry method!\nOptions are Data Entry Form data entry (-f flag) (or)\nText Database File Entry (-d flag)\n"; X do { print "Enter Form Entry, Text Database File Entry, or Quit (f/t/q): "; $c = <>; chop $c; } until $c =~ /[FfTtQq]/; X X if($c =~ /[Ff]/) # Data Entry Form data entry X { X print "Please enter Data Entry Form file specification: "; X $opt_f = <>; X chop $opt_f; X while(!-e $opt_f) X { X print "File $opt_f does not exist!\nPlease enter another Data Entry Form file specification: "; X $opt_f = <>; X chop $opt_f; X } X } X elsif($c =~ /[Tt]/) # Text Database File data entry X { X print "Please enter Text Database file specification: "; X $opt_d = <>; X chop $opt_d; X while(!-e $opt_d) X { X print "File $opt_d does not exist!\nPlease enter another Data Entry Form file specification: "; X $opt_d = <>; X chop $opt_d; X } X } X else X { X warn "Quitting junkmail! Bye!\n"; X exit; X } X} X Xif($opt_c) X{ X $user = $opt_c; X} Xelse # do not want to send a copy to someone X{ X $user = ''; # null string X} X Xif($opt_t) X{ X $tfile = $opt_t; # X} # end processing template flag -t Xelse # X{ X print "You did not specify a template file!\nPlease enter file specification of your junkmail template file: "; X $tfile = <>; X chop $tfile; X} X Xwhile(! -e $tfile) X{ X print "Template file $tfile does not exist!\nDo you wish to enter another template file specification (y/n): "; X $answer = <>; X chop $answer; X if($answer =~ /[Yy]/) X { X print "Enter new template file specification: "; X $tfile = <>; X chop $tfile; X } X else X { X exit; X } X} X X Xif (-T $tfile) # template file should be text X{ X open(TEMPLATE,"$tfile"); # open template file X @template =