ww has asked for the wisdom of the Perl Monks concerning the following question:

Warning and apology: This is a hideously long post, but at the wrong end of nearly 72 hours without sleep, I no longer have any idea how to isolate the problem. Please forgive me.

I have over-reached and this is now overdue despite kind help overnite (20-21 Jun US EDT) from kyle, zaxo and GrandFather.

system info: developing on w2k, perl 5.8.x for use on linux/apache to which I have shell (SSH) access.

Lest this be read as an attempt to spam, the recipients are all folks (reporters and editors) who, as I did in a former life, have mixed attitudes about news releases: we get too many, but hate to NOT get one that has real interest. The "client" who helped me con myself into trying to write this is a non-profit with what it and I regard as a chance to get good publicity while providing valuable information to the public. Finally, by way of background, my fee for making this work, this morning, US EDT (Aargh!) is $0.00.

However, despite hours with the Llama, the Alpaca, the Camel and the Cookbook, I am again/still failing to reference and/or dereference the hash across the call to the sendmail sub. The output of the code between the first two lines of "=" signs tells me $VAR14 = '%HoA{0}';; the print Dumper (@{ $HoA{$j} }); spits out the 5 emails I would expect as does $msg->print_header(\*STDOUT);; but $msg->send () or die... insists "no data in this part at mailerww2.pl line</c>. Thus, at this point, I dare not test it on the server, lest (unknown but BAD) consequences arise.

So my questions -- the first of which I would have expected to find in the POD for Mime::Lite but did not, perhaps for lack of understanding -- are threefold.

  1. Will Mime::Lite or sendmail correctly unfold the hash of email addresses or, if not, what is it that I need to do to make the addresses accessible to them?
  2. What is the cure for the "no data" error at $msg->send () or die...?
  3. On the dev box, this hangs after the first set of output and the (expected) message that the script can't find SendMail on this machine, but I have not figured out how to specify its location on the server: should it be something like send('smtp', 'smtp.client.com', Timeout=>90); or send('/usr/sbin/sendmail',...) or ?
. Trying to get to the heart of things....
#!/usr/bin/perl -w use strict; use vars qw ($line $list $flag); $flag = 0; # modules # use diagnostics; # debug use Data::Dumper; # debug use MIME::Lite; # open address file, read in address file, convert to useful form for +email: open FIN,"<fakes.txt" or die ( "Can't open testlist.txt: $!") ; while ( defined ( $line = <FIN> ) ) { chomp $line; if ($flag == 0) { $list = $line; $flag = 1; } else { $list .= ",$line"; } } close (FIN); # now we have all the names, comma-separated, in $list # group into sets of five my $i=0; # counter my $j=0; # key for %HoA my @wholelist; my $individual; my @fives; my $fives; my %HoA; my $HoA; @wholelist = split/,/,$list; shuffle(\@wholelist); # sub to randomize before grouping for $individual(@wholelist) { push @fives, $individual; if (defined ($fives[4]) ) { push(@{$HoA{$j}}, @fives); undef(@fives); $i = 0; $j++; # reset $i; ++ j to have next @fives go +into a new key } else { $i++; } } print "\n\nDumping \%HoA:\n"; # debug print Dumper(%HoA); # debug $j=0; #reusing key for ($j=0; $j<4; $j++) { #20 emails in wholelist, so +0..3 keys in %HoA
I think the trouble starts here:
use vars qw ( %params ); %params = ( "To" => "ww\@disadvantage.org", "Bcc" => "%HoA{$j}", "Subject" => "A test from ww", "Reply-To" => "ww\@disadvantage.org", "body" => "This is just some simple test text from ww. When you rec +eive it please simply 'FORWARD' it (do NOT 'REPLY') to me at \n\n'whe +elerw\@disadvantage.org' \n\nso I can confirm that my test ran proper +ly.\n\nThanks, in advance, for your help!\n", ); print "\n\n +++++++++++\n\nDumping \%params next:\n\n"; # debug print Dumper (%params); # debug print "\n Done dumping \%params\n\n +++++++++++\n\n"; # debug print "\n\n \$HoA{$j}' is: @{ $HoA{$j} }\n\n"; # debug exit; # debug =head sendmail ( ${ %params } ); =cut sleep (2); #120 in production } #### SUBS ##### # suffle array (Fisher-Yates) to minimize having any domain get all of + a single batch. sub shuffle { my $individual = shift; my $i; for ($i = @$individual; --$i; ) { my $j = int rand ($i+1); next if $i == $j; @$individual[$i,$j] = @$individual[$j,$i]; } } sub sendmail { $params{Type} = 'text/plain' if ! exists $params{Type}; $params{From} = 'Postmaster@createyouradvantage.com' if ! exi +sts $params{From}; print "\n\n======================================\n\n"; print Dumper (%params); print "\n======================================\n\n"; print Dumper (@{ $HoA{$j} }); print "\n======================================\n\n"; # my $msg = MIME::Lite->new (%params{$j}); print "\n\n -------------------------------\n"; my $msg->print_header(\*STDOUT); print "\n\n -------------------------------\n"; # $msg->send ('smtp', "fake.disadvantage.org", Timeout=>90) o +r die "Message send failed: $!"; # error ^: "no data in this part" return; }

With the existing exclusions (by way of # and =head ... =cut) this produces this output:

Dumping %HoA: $VAR1 = '1'; $VAR2 = [ 'guer@yapot.com', 'cd@cdef.com', 'jrn@foo.com', 'greg@confcall.net', 'gecko@yapoo.com' ]; $VAR3 = '3'; $VAR4 = [ 'donm@foo.com', 'Dolly@yankeeone.org', 'Postmaster@foo.com', 'Fred.Walters@nevasink.org', 'delbert.cubby@cmail.com' ]; $VAR5 = '0'; $VAR6 = [ 'jrn@aql.com', 'ksmith@foo.com', 'bdm@prover.net', 'Donl@aql.com', 'mrod@beachball.com' ]; $VAR7 = '2'; $VAR8 = [ 'KAM@charles.net', 'de2@ulmail.ljw.edu', 'ab@abc.net', 'de1@cdef.net', 'bill@fghresearch.com' ]; +++++++++++ Dumping %params next: $VAR1 = 'body'; $VAR2 = 'This is just some simple test text from ww. When you receive +it please simply \'FORWARD\' it (do NOT \'REPLY\') to me at \'wheelerw@disadvantage.org\' so I can confirm that my test ran properly. Thanks, in advance, for your help! '; $VAR3 = 'Subject'; $VAR4 = 'A test from ww'; $VAR5 = 'Reply-To'; $VAR6 = 'ww@disadvantage.org'; $VAR7 = 'To'; $VAR8 = 'ww@disadvantage.org'; $VAR9 = 'Bcc'; $VAR10 = '%HoA{0}'; Done dumping %params +++++++++++ $HoA{0}' is: jrn@aql.com ksmith@foo.com bdm@prover.net Donl@aql.com +mrod@beachball.com

which, in brief, tells us that the initial processing is doing what's expected, and stashing it in %HoA

However, when I uncomment the call to the sendmail sub, life becomes less good:
F:\_wo_cya>perl ugly.pl >ugly_out2.txt syntax error at ugly.pl line 115, near "%params{" Execution of ugly.pl aborted due to compilation errors.

Clearly, I am missing something. And when, in line with the overnight attempts to educate me, I use:

use vars qw (%params); %params = ( "cc:" => "%HoA{$j}", "Subject" => "A test from ww", "body" => "This is just some simple test text from ww. When you +receive it please simply 'FORWARD' it (do NOT 'REPLY') to me at \n\n' +ww\@ldisadvantage.org' \n\nso I can confirm that my test ran properly +.\n\nThanks, in advance, for your help!\n" ); ( ...debugs removed) sendmail (%params); sleep (120); } (...sub shuffle removed for brevity) sub sendmail { # local %params = @_; $params{Type} = 'text/plain' if ! exists $params{Type}; $params{From} = 'Postmaster@disadvantage.com' if ! exists $pa +rams{From}; my $msg = MIME::Lite->new (%params); ### Format as a string: my $str = $msg->as_string; ## error ^ : "no data in this part at mailerww1.pl line 19 +9" print "\n\n\$str is:\n $str \n"; print "\n\n\$str is:\n $$msg \n"; # $msg->send () or die "Message send failed"; return; }

The output becomes even less clear (to me):

Reference found where even-sized list expected at mailerww.pl line 165 +. $msg is: MIME::Lite=HASH(0x1c0162c) F:\_wo_cya>perl mailerww1.pl $HoA{0}' is: (...the expected 5 email addresses) no data in this part at mailerww1.pl line 207

...which is seen here as line 12 of the last segment of code.

Again, I regret being so longwinded, but will greatly appreciate edification on the substance of my errors. (I know I have much to learn, by way of better approaches, but at this moment, I need to make good on my ill-considered -- commitment to a task and timeline which is beyond my skills.

Replies are listed 'Best First'.
Re: passing a hash to Mime::Lite and thence to SendMail
by samtregar (Abbot) on Jun 21, 2007 at 17:58 UTC
    First: get some sleep! Second: learn how to reference Perl data structures. Maybe that sounds harsh, but you've got some very basic syntax problems which you need to resolve before you can write a script that does anything useful. For example:

       sendmail ( ${ %params } );

    That simply makes no sense at all. It's trying to treat a hash as a scalar-ref! There's just no way that can work - until that's obvious to you there's really not a lot we can do for you aside from rewriting your entire program.

    If your books aren't making sense, perhaps take a read through perldata, perlref and perldsc.

    -sam

Re: passing a hash to Mime::Lite and thence to SendMail
by GrandFather (Saint) on Jun 21, 2007 at 19:11 UTC

    Following up slightly on samtregar's post: in the "I think the trouble starts here:" section not only is the syntax complete bollix, but you're not using the parameter that is passed in any case, you are using a global variable!

    In the "with the overnight attempts to educate me" section you get a little closer (probably by copying sample code from my scratch pad), but have mutilated the code so that you are still using a global. You should almost never need to use local, it doesn't do what you think! Use my for declaring variables. Do not use use vars qw (...);, it doesn't do what you think!

    Your main problem is that "Data" is where your email message text goes - the thing that the error message claims is missing. Search the MIME::Lite documentation, you will not find a single place where body is used to set the message data.


    DWIM is Perl's answer to Gödel