James
James

Reputation: 1232

Weirdness in Perl Net::SMTP

I'm having some trouble with Net::SMTP when used in a for loop. The first iteration works, but on the second iteration the script dies with Can't call method "mail" on an undefined value at..., the line referred to being

$smtp->mail('[email protected]'); #from.

Any ideas?! Thanks for your time!

use strict;
use warnings;

use Net::SMTP;

my $smtp;

#@data is defined and populated somewhere

foreach my $line (@data) {

  my @linearray = split /,/, $line;
  my $host = $linearray[2];

  $host =~ s/\r|\n//g;

  next unless ($host =~  m/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3}).([0-9]{1,3})/); # skip if it's not an IP (i.e. it's the header row)
  print "Connecting to $host...";

  # create object
  $smtp = Net::SMTP->new(
    Hello => 'hacker.net',
    Timeout => 3,
    Host => $host,
    Debug => 1,
  );
  $smtp->mail('[email protected]'); #from
  my $tocheck = $smtp->recipient('[email protected]'); #to
  if ($tocheck == 0) {
    print "$host is NOT an open relay\n";
    #$smtp->quit;
    next;
  }

  $smtp->data();
  $smtp->datasend("Test\n");
  $smtp->datasend("\n");
  $smtp->datasend("A simple test message\n");
  $smtp->dataend();
  $smtp->quit;
}

Upvotes: 0

Views: 496

Answers (2)

James
James

Reputation: 1232

Resolved. Tail slightly between the legs on this one. It turns out that the list of IPs given to me had already been contacted about the issue and therefore some has started putting measures in place to fix the problem. One such measure was blocking TCP port 25 with a source IP different to a trusted relay (not my IP just to clarify). Therefore creation of the Net::SMTP was simply failing. So reintroduction of the block suggested by Borodin (which I'd removed while trying to debug this issue) fixed it all up. Thanks for your help guys - much appreciated.

Upvotes: 0

Borodin
Borodin

Reputation: 126742

I would guess that your $host doesn't hold a valid SMTP server address. The regex checks only whether it contains something that may be a valid IP address somewhere. 999.999.999.999 isn't valid, for instance. Also whitespace will probably break things, so ' 127.0.0.1 ' won't work either. Finally there may be no working SMTP server at that address, even if it is a legal IP address so your contructor may fail anyway.

This alternative regex checks that the entire string matches a valid IP address with only 0..255 values in each field.

/\A(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\z/

You should check the return value of the constructor and warn if it has failed:

$smtp = Net::SMTP->new(
  Hello => 'hacker.net',
  Timeout => 3,
  Host => $host,
  Debug => 1,
);
unless ($smtp) {
  warn "Unable to connect to to SMTP server '$host'";
  next;
}

Upvotes: 1

Related Questions