NAME    Mail::Bulkmail - Platform independent mailing list moduleAUTHOR    Jim Thomason jim3@psynet.netSYNOPSIS    open (LIST, "./list.txt") || die "Can't open list!";     $bulk = Mail::Bulkmail->new(            From    => 'jimt@playboy.com',            Subject => 'This is a test message!',            Message => "Here is the text of my message!",            'LIST'  => *LIST,     );    $bulk->bulkmail;    close LIST;    Be sure to set your default variables in the module, or set them    in each bulk mail object. Otherwise, you'll be using the    defaults. (Not that that's necessarily bad)DESCRIPTION    Mail::Bulkmail gives a fairly complete set of tools for managing    mass-mailing lists. I wrote it because our existing tools were    just too damn slow for mailing out to thousands of recipients.REQUIRES    Perl5.004, SocketOBJECT METHODS  CREATION    New Mail::Bulkmail objects are created with the new()    constructor. For a minimalist creation, do this:    $object = Mail::Bulkmail->new();    You can also initialize values at creation time, such as:     $object = Mail::Bulkmail->new(                            From    =>      'jim3@psynet.net',                            Smtp    =>      'some.smtp.com'                    );  BUILT IN ACCESSORS    Okay, here's where the fun stuff beings. Since these are    objects, the important stuff is how you access your data.    Object methods work as you probably expect.     $bulk->property      Will return the value of "property" in $bulk     $bulk->property("new value")       Will set the value of "property" in $bulk to "new value" and return "new value"       The property will not be set if $object->No_errors is 0 and the property has a       validation check on it.  See Validated Accessors, below.    All accessor methods are case sensitive. Be careful!    Here are all of the accessors that come built in to your    Mail::Bulkmail objects.    From       The e-mail address this list is coming from. This can be               either a simple e-mail address (jim3@psynet.net), or               a name + e-mail address ("Jim               Thomason"<jim3@psynet.net>). This is validated unless               you turned off validation by setting No_errors. See               above.    Subject    The subject of the e-mail message. If it's not set,               you'll use the default.    Message    This is the actual text that will appear in the message               body. You can include control fields that can be               mapped into specific values. See MAPPING, below    Map        This specifies a character map for the message text. See               MAPPING, below.    Smtp       This sets the SMTP server that you're going to connect               to. You'll probably just want to use whatever you've               set as your default SMTP server in the module. You               did set your default SMTP server when you double-               checked all the other defaults, right?    Tries      This sets the number of times that you will attempt to               connect to a server. You'll probably just want to use               the default.    Precedence This sets the precedence of the e-mail message. This is               validated unless you turn off validation by setting               No_errors.    Domain     You're going to be saying HELO to an SMTP server, you'd               be be willing to give it a domain as well. You can               explicitly set the Domain here, or choose not to. If               no Domain is set, the domain of the From e-mail               address will be used instead. It doesn't do you any               good to set Domain after you've connected to a               server.    LIST       This is a glob to a filehandle. This is your actual list               of e-mail addresses. You can either have one e-mail               address per line, or have an multiple "::" seperated               fields in addition to the e-mail address. If you               choose to use "::" fields, read the section on               MAPPING, below. This file should be openned with read               access. Required if you're going to be bulkmailing.    BAD        This is a glob to a filehandle. Bulkmail will happily               print out all failed addresses, exactly as they               appeared in LIST to this file. This file should be               openned with write or append access. Totally               optional.    GOOD       This is a glob to a filehandle. Bulkmail will happily               print out all successful addresses, exactly as they               appeared in LIST to this file. This file should be               openned with write or append access. Totally               optional. GOOD is much more useful than BAD since               GOOD is a duplicate of your original list, with all               invalid addresses weeded out.    ERROR      This is a glob to a filehandle. Any errors that occur in               Bulkmail will be printed out here. Totally optional,               but highly recommended. This file should be openned               with write or append access.    BANNED     This is a glob to a filehandle. BANNED allows you to weed               your mailing list and not mail to any e-mail               addresses that you may have in your list that you               don't want to. For example, you may not want to be               able to send any e-mail to               "president@whitehouse.gov", putting that into your               banned file will automatically skip that address               while mailing. Additionally, you can specify domains               so that no mail will go to "whitehouse.gov", for               example. A word of caution: Subdomains are banned               recursively. This means that "whitehouse.gov" will               ban "staff.whitehouse.gov" but that               "staff.whitehouse.gov" will allow e-mail to go               through to "whitehouse.gov". This file should be               openned with read access.    Tz         This allows you to set the timezone. See above. You               probably don't want to touch this.    Date       This allows you to set the date. See above. You probably               don't want to touch this.    Duplicates Duplicates is off by default. Setting Duplicates to 1               will allow people with multiple entries in your               mailing list to receive multiple copies of the               message. Otherwise, they will only receive one copy               of the message. Duplicate addresses are printed out               to ERROR, if you specified ERROR and you didn't turn               Duplicates on.    headset    headset() is actually a method that pretends to be an               accessor. See ADDTIONAL ACCESSORS, below.    No_errors  No_errors() lets you decide to turn of error checking. By               default, Mail::Bulkmail will only allow you to use               valid e-mail addresses (well, kinda see the               _valid_email function for comments), valid dates,               valid timezones, and valid precedences. No_errors is               off by default. Turn it on by setting it to some non-               zero value. This will bypass all error checking. You               should probabaly just leave it off so you can check               for valid e-mails, dates, etc. But you have the               option, at least.  ADDITIONAL ACCESSORS    You're perfectly welcome to access any additional data that    you'd like. We're gonna assume that you're accessing or setting    a header other than the standard ones that are provided. You    even get a special method to access them: headset(). Using it is    a piece of cake:    $bulk->headset('Reply-to', 'jim3@psynet.net');    Will set a "Reply-to" header to the value of "jim3@psynet.net".    Want to access it?    $bulk->headset('Reply-to');    What's that you ask? Why don't we set *all* headers this way?    Well, truth be told you can set them using headset.    $bulk->headset('From', 'jim3@psynet.net');    Is the same as:    $bulk->From('jim3@psynet.net');    Note that you can only set other _headers_ this way. The headers    that have their own methods are From, Subject, and Precedence.    Calling headset on something else, though (like "Smtp") will set    a header with that value, which is probably not what you want to    do (a "Smtp: your.server.com" header is reeeeeal useful). I'd    recommend just using the provided From, Subject, and Precedence    headers. That's what they're there for.    What's that? Why the hell can't you just say $bulk-    >my_header('some value')? It's because you may want to have a    header with a non-word character in it (like "Reply-to"), and    methods with non-word characters are a Perl no-no. So since it's    not possible for me to check every damn header to see if it has    a non-word character in it (things get stripped and messed up    and the original value is lost), you'll just have to use headset    to set or access additional headers.    OR--You can just set your headers at object construction.    Realistically, you're going to be setting all of your headers at    construction time, so this is not a problem. Just remember to    quote those things with non-word characters in them.     $bulk->Mail::Bulkmail->new(                    From            =>      'jim3@psynet.net',                    Subject         =>      'Some mass message',                    'Reply-to'      =>      'jimt@playboy.com'            );    If you don't quote headers with non-word characters, all sorts    of nasty errors may pop up. And they're tough to track down. So    don't do it. You've been warned.  VALIDATED ACCESSORS    The properties that have validation checks are "From",    "Precedence", "Date", and "Tz" to try to keep you from making    mistakes. The only one that should really ever concern you is    perhaps "From"    From       This checks the return e-mail address against RFC 822               standards. The validation routine is not perfect as               it's really really hard to be perfect, but it should               accept any valid non-group non-commented e-mail               address. There is one bug in the routine that will               allow "Jim<jim3@psynet.net" to pass as valid, but               it's a nuisance to fix so I'm not going to. :-)    Precedence We are doing bulkmail here, so the precedence should               always be "list", "bulk", or "junk" and nothing else.               We might as well be polite and not make our servers               think that we're sending out 60,000 first-class or               special-delivery messages. You probably don't want to               fiddle with this.    Date       This checks that the date set is a valid RFC 822 date.               You probably don't ever want to set the date, since               it will be automagically inserted to each e-mail               message as it is sent. Nonetheless, if you just have               to use some other random date, set it here. But               follow the spec, please.    Tz         This checks that the timezone set is a valid RFC 822 Time               zone. The only time I can think of where you'd want               to set the time zone is if your machine is off and               you want to correct it. For example, several of our               servers seem to think that they're on Pacific Time               instead of Central Time, which is annoying. Fix the               time zone here if you need to.    If you don't want to do any validation checks, then set    No_errors equal to 1 (see METHODS, below). That will bypass all    validation checks and allow you to insert "Garbonzo" as your    date if you desire. It's recommended that you leave error    checking on. It's pretty good. And you have more important    things to worry about.  Methods    There are several methods you are allowed to invoke upon your    bulkmail object.    bulkmail  This method is where the magic is. This method starts up              your mailing, sending your message to every person              specified in LIST. bulkmail returns nothing. bulkmail              merely loops through everything in your LIST file and              calls mail on each entry.    mail      Okay, maybe mail is really where the magic is. This method              sends out a message to a single address. You can use              this method if you want to send out a message to only              one person, though arguably there are better ways to              send e-mail to a single individual than using              Mail::Bulkmail. The first argument to mail is the e-              mail address of the recipient. The second argument is              an optional local map. See MAPPING below. Further              arguments are optional headers. Calling mail directly              is really only useful if you need to do preprocessing              of your list before sending your message or if your              list of addresses is stored in an array or some other              non-filehandle location.              Returns 1 on success, 0 on failure.    connect   This method connects to your SMTP server. It is called by              mail (and in turn, bulkmail). You should never need to              directly call this unless you want to merely test SMTP              connectivity.              Returns 1 on success, 0 on failure.    disconnect              This method disconnects from your SMTP server. It is              called at object destruction, or explicitly if you              wish to disconnect earlier. You should never need to              call this method. Returns nothing.    error     error is where the last error message is kept. Can be used              as follows:              $object->connect || die $object->error;              All error messages will be logged if you specifed an              ERROR file.MAPPING    Finally, the mysterious mapping section so often alluded to.    You are sending out bulk e-mail to any number of people, but    perhaps you would like to personalize the message to some    degree. That's where mapping comes in handy. You are able to    define a map to replace certain characters (control strings) in    an e-mail message with certain other characters (values).    Maps can be global so that all control strings in all messages    will be replaced with the same value or local so that control    strings are replaced with different values depending upon the    recipient.    Maps are declared at object constrution or by using the Map    accessor. Map values are either anonymous hashes or references    to hashes. For example:    At constrution:            $bulk = Mail::Bulkmail->new(                                    From    =>      jim3@psynet.net,                                    Map             => {                                                                    'DATE' => 'today',                                                                    'company' => 'Playboy Enterprises'                                                            }                            );    Or using the accessor:            $bulk->Map({'DATE'=>yesterday});                Global maps are not terribly useful beyond setting generic values, such as today's date within a message    template.  Local maps are much more helpful since they allow values to be set individually in each    message.  Local maps can be declared either in a call to the mail method or by using the BULK_FILEMAP    key.  Local maps are declared with the same keyword (Map) as global maps.    As a call to mail:            $bulk->mail(                            'jim3@psynet.net',                            Map => {                                    'ID'   => '36373',                                    'NAME' => 'Jim Thomason',                            }                    );         Using BULK_FILEMAP            $bulk->Map({'BULK_FILEMAP'=>'BULK_EMAIL::ID::NAME'});                Be careful with your control strings to make sure that you don't accidentally replace text in the message    that you didn't mean to.  Control strings are case sensitive, so that "name" in a message from the     above example would not be replaced by "Jim Thomason" but "NAME" would be.    BULK_FILEMAP will be explained more below.  BULK_FILEMAP    Earlier we learned that LIST files may be in two formats, either    a single e-mail address per line, or a "::" delimited list of    values, one of which must be an e-mail address.    "::" delimited lists _must_ be used in conjunction with a    BULK_FILEMAP parameter to Map. BULK_FILEMAP allows you to    specify that each e-mail message will have unique values    inserted for control strings without having to loop through the    address list yourself and specify a new local map for every    message. BULK_FILEMAP may only be set in a global map, its    presence is ignored in local maps.     If your list file is this:       jim3@psynet.net::36373::Jim Thomason           You can have a corresponding map as follows:     $bulk->Map({                    'BULK_FILEMAP'=>'BULK_EMAIL::ID::NAME'                    });    This BULK_FILEMAP will operate the same way that the local map    above operated. "BULK_EMAIL" is the only required item, it is    case sensitive. This is where in your :: delimited line the e-    mail address of the recipient is. "BULK_EMAIL" _is_ used as a    control string in your message. Be careful. So if you want to    include someone's e-mail address within the text of your    message, put the string "BULK_EMAIL" in your message body    wherever you'd like to insert it.    Everything else may be anything you'd like, these are the    control strings that will be substituted for the values at that    location in the line in the file. You may use global maps,    BULK_FILEMAPs and local maps simultaneously.  Map precedence    BULK_FILEMAP values will override global map values. local map    values will override anything else. Evaluation of map control    strings is     local value -> BULK_FILEMAP value -> global value    where the first value found is the one that is used.CLASS VARIABLES     $def_From              = 'Postmaster';     $def_Smtp              = 'your.smtp.com';     $def_Port              = '25';     $def_Tries             = '5';     $def_Subject           = "(no subject)";     $def_Precedence        = "list";     $def_No_errors         = 0;     $def_Duplicates        = 0;    The default values. for various items. All of which may be    overridden in individual objects.    def_From  Who will this message be from if no return address is              specified or if it's invalid?    def_Smtp  What's the default SMTP server to connect to? You really              should set this variable! If you don't, you'll have to              specify an SMTP server in every bulkmail object you              set up. "your.smtp.com" doesn't work, it's example              only.    def_Port  What port on that machine should we try to connect to?    def_Tries How many times should we try to reconnect if we fail?    def_Subject              What should the subject of the message be if we don't              have one?    def_Precedence              What should the precedence for these messages be?    def_No_errors              Should we allow error checking? if No_errors is true,              then we won't check for valid dates, time zones, email              addresses, and precedences    def_Duplicates              If someone is on a list more than once, should they              receive multiple copies of the message? =backDIAGNOSTICS              Bulkmail doesn't directly generate any errors. If              something fails, it will return 0 and set the ->error              property of the bulkmail object. If you've provided an              error log file, the error will be printed out to the              log file.              Check the return type of your functions, if it's 0,              check ->error to find out what happened.HISTORY    1.01	  Bug fixed.  _everyone_ should get this release.    1.00          08/18/99 First public release onto CPAN    0.93          08/12/99 Re-vamped the documentation substantially.    0.92          08/12/99 Started adding a zero in front of the version                  name, just like I always should have Changed                  accessing of non-standard headers so that they                  have to be accessed and retrieved via the                  "headset" method. This is because methods cannot                  have non-word characters in them. From, Subject,                  and Precedence headers may also be accessed via                  headset, if you so choose. AUTOLOAD now complains                  loudly (setting ->error and printing to STDERR) if                  it's called.    .91           08/11/99 Fixed bugs in setting values which require                  validation checks. Fixed accessing of non-standard                  headers so that the returns are identical to every                  other accesor method.    .90              08/10/99 Initial "completed" release. First release              available to general public.EXAMPLES  bulkmailing              Here's how we use Bulkmail in one of our programs:               use Mail::Bulkmail;               open (LIST,   "./list.txt")            || die "Can't open list!";               open (GOOD,   ">./good_list.txt") || die "Can't open good list!";               open (BAD,    ">./baddata.txt")        || die "Can't open bad list!";               open (ERROR,  ">./error.txt")          || die "Can't open error file!";               open (BANNED, "./banned.txt")          || die "Can't open banned list!";               $bulk = Mail::Bulkmail->new(                      From    => $from,                      Subject => $subject,                      Message => $message,                      X-Header=> "Rockin' e-mail!",                      Map             => {                                              '<DATE>'                => $today,                                              BULK_FILEMAP    =>      "email::<ID>::<NAME>::<ADDRESS>"                                              },                      'LIST'  => *LIST,                      'GOOD'  => *GOOD,                      'BAD'   => *BAD,                      'ERROR' => *ERROR,                      'BANNED'=> *BANNED,               );              That example will set up a new bulkmail object, fill              in who it's from, the subject, and the message, as              well as a "X-header" header which is set to "Rockin'              e-mail!". It will also define a map to turn "<DATE>"              control strings into the $today string, a BULK_FILEMAP              to map in the name, id number, and address of the              user. It defined the LIST as the LIST file openned              earlier, and sets up GOOD, BAD, and ERROR files for              logging. It also uses a BANNED list.              This list is then mailed to by simply calling              $bulk->bulkmail();              Easy as pie. Especially considering that when we had              to write all of this code out in our original              implementation, it took up well over 100 lines.  Single mailing               use Mail::Bulkmail;                              $bulk = Mail::Bulkmail->new(                      From    =>      $from,                      Subject =>      $Subject,                      Message =>      $message,                      X-Header=>      "Rockin' e-mail!"               );                              $bulk->mail(                              'jim3@psynet.net',                              Map             => {                                                      '<DATE>'        => $today,                                                      '<ID>'          => 36373,                                                      '<NAME>'        => 'Jim Thomason',                                                      '<ADDRESS>'     => 'Chicago, IL'                                                      }                              );              This will e-mail out a message identical to the one we              bulkmailed up above, but it'll only go to              jim3@psynet.netMISCELLANEA              Mail::Bulkmail will automatically set three headers              for you.    1             Who the message is from (From:....)    2             The subject of the message (Subject:...)    3             The precedence of the message (Precedence:...)              The defaults will be set unless you give them new              values, but regardless these headers *will* be set. No              way around it. Additional headers are set solely at              the descretion of the user.              Also, this module was originally written to make my              life easier by including in one place all the goodies              that I used constantly. That's not to say that there              aren't goodies that I haven't included that would be              beneficial to add. If there's something that you feel              would be worthwhile to include, please let me know and              I'll consider adding it.              How do you know what's a worthwhile addition?              Basically, if you need to do some sort of pre-              processing to your e-mail addresses so that you have              to use your own loop and calls to mail() instead of              using bulkmail(), and you're using said loop and              processing in several routines, it may be a useful              addition. Definitely let me know about those.              That's not to say that random suggestions wouldn't be              good, those I'll listen to as well. But something big              like that is probably a useful thing to have so I'd be              most interested in hearing about them.COPYRIGHT (again)              Copyright (c) 1999 James A Thomason III              (jim3@psynet.net). All rights reserved. This program              is free software; you can redistribute it and/or              modify it under the same terms as Perl itself.CONTACT INFO              So you don't have to scroll all the way back to the              top, I'm Jim Thomason (jim3@psynet.net) and feedback              is appreciated. Bug reports/suggestions/questions/etc.              Hell, drop me a line to let me know that you're using              the module and that it's made your life easier. :-)