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

I'm a bit stuck right now and was hoping for some divine monk intervention so I can kind of move past this current block that been eating away @ myt brain for the past 24 hours. I'm sure the answer is simple and I'm just not "seeing it" because I'm so caught up with the entire script.

I basically need to pass a hash to a subroutine and then iterate through the hash in the subroutine and email it's contents to myself. I used the Perl Cookbook's emailing recipe (18.3) because it seemed a bit easier then invoking SendMail directly (I don't know how to do that) - where I'm stuck is how to iterate through the hash and assign it to the $body variable so the hash contents can be sent via email. I know the snippet I'm including has a scoping problem.

Is there any way I could get some answers and just a short discussion of how to implement the solution properly and a way I could avoid this in the future. I'm sure it's a design problem - that's what I get for not being a programmer.

#!/usr/local/bin/perl -w use strict; use Mail::Mailer; my %hash = ( '742+evergreen+terrace' => '60516', '1094+evergreen+terrace' => '60187' ); notify(\%hash); sub notify { my $error_hash = shift; foreach my $address (keys %$error_hash) { $contents = "$address $error_hash->{$address}"; } my $from = 'system@system.com'; my $to = 'me@system.com'; my $subject = 'Warning'; my $body = $contents; my $mailer = Mail::Mailer->new("sendmail"); $mailer->open({ From => $from, To => $to, Subject => $subject, }) or die "Can't open: $!\n"; print $mailer $body; $mailer->close(); }

Replies are listed 'Best First'.
Re: Iterating Through a Hash and Emailing the Result
by Limbic~Region (Chancellor) on Mar 25, 2004 at 14:32 UTC
    bivouac,
    You were almost there. You have a couple of issues.
    • You show that you are using strictures, but you do not properly declare $contents
    • You do not append to the value of $contents, you overwrite it each iteration
    Try the following instead:
    #!/usr/bin/perl use strict; use warnings; use Mail::Mailer; my %hash = (foo => '3.14159265358', bar => '1.61803398874'); notify( \%hash ); sub notify { my $hash_ref = shift; my $mailer = Mail::Mailer->new("sendmail"); $mailer->open( { From => 'system@system.com', To => 'me@system.com', Subject => 'Warning', } ) or die "Can't open sendmail : $!"; for my $key ( keys %{ $hash_ref ) ) { print $mailer "$key : $hash_ref->{$key}\n"; } $mailer->close(); }
    Cheers - L~R
      Thanks so much. I couldn't figure out where to put that "for" block in the "mail" part. Unblocked!
Re: Iterating Through a Hash and Emailing the Result
by Abigail-II (Bishop) on Mar 25, 2004 at 14:30 UTC
    Your code doesn't even compile ($contents is undeclared). And what's the purpose of the first loop in the notify sub? It overwrites the variable in each iteration, but you aren't doing anything with the variable in the loop

    If your problem lies in how to serialize a hash, I suggest using YAML. This produces compact, human readable code, unlike the at this site popular Data::Dumper.

    Abigail

Re: Iterating Through a Hash and Emailing the Result
by b10m (Vicar) on Mar 25, 2004 at 14:30 UTC

    What about this?

    my $contents; foreach my $address (keys %$error_hash) { $contents .= "$address\t\t$error_hash->{$address}\n"; } # ... print $mailer $contents;
    --
    b10m

    All code is usually tested, but rarely trusted.
Re: Iterating Through a Hash and Emailing the Result
by matija (Priest) on Mar 25, 2004 at 14:36 UTC
    The most "I could avoid this in the future" solution I can come up with is use Data::Dumper. You can mail a Dump to yourself, and best of all, it will work for complex structures - even if the has contains arrays and other hashes.

    On the other hand, if you wish to learn about references, I suggest that you start by reading perldoc perlref.