I feel the need to ponder the elegant simplicity of Net::SMTP, having written some nice support code using this module for testing routines against anti-spam servers at work.

Sadly, the systems I wrote my code for do not provide support for DSN's as an extension within initial conversation, so using
$smtp->recipients(@addresses, { Notify => ['SUCCESS','FAILURE','DELAY' +] });
or similar was not an option, which is a pity. Regardless, on with the pondering.

#!/usr/bin/perl # Use strictures use strict; use warnings; # Additional modules use Socket; use Net::DNS; use Net::SMTP; # At launch, ask for an email address print "Please enter an email address: "; my $address = <STDIN>; # Break apart the address and do MX lookup against the # domain our ($userpart, $domainpart) = split /@/, $address; our $res = Net::DNS::Resolver->new(); our @mx = mx($res, $domainpart) or die "Cannot resolve $domainpart: $!\n";
Within a few short lines of code, you already have something useful. You could at this point, for example, chuck in some code to simply print out the MX records that Net::DNS found, like:
for my $rr (@mx) { print $rr->preference, " ", $rr->exchange,"\n"; }
But this is not about resolving MX records. This is about talking to SMTP hosts!

What we want to do, is ask a server if it would accept mail from our address. It's not perfect, some hosts answer ambiguously with a 2.5.2 or 2.5.0 and bounce out of conversation, but many systems will reply correctly, with 250 or 550. In event of the latter, we wouldn't bother to offload email to a failure response, and would simply elect to bounce mail. See end notes for comments on sender verification through SMTP conversation ;)

So,in the beautiful prose of Perl, we would say:
# We assume that @mx contains something, since the die() # during MX resolution would have killed us by now for (@mx) { # It *would* be more elegant to test the primary server # in the event of round-robin MX or pick one in the # event of load-balanced MX, but I want to test for # any disparities in replies. my @mailservers = $rr->exchange; for my $mailserver (@mailservers) { # Connection plus EHLO my $smtp = Net::SMTP->new( Host => $mailserver, Hello => some.server.tld, Timeout => 30, Debug => 0 ) or die "Cannot connect to $mailserver!\n"; # MAIL FROM: $smtp->mail('me@somewhere.com'); # RCPT TO: my $response = $smtp->recipient($address); # Now go looking for response codes. On my system, # 1 = user valid, 0 = user invalid if ($response == 1) { # Do something, or return() something } else { # Do something, or return() something } # Be polite, RSET and QUIT properly $smtp->reset(); $smtp->quit(); # Slow down the rate between probes sleep(2); } }
This piece of code can work like an SMTP ping, where you could check to see if a host is up, or do as I have and use it for primitive sender verification, or to test the existence of mailboxes at a destination host. Or whatever. You know? ;-)

This meditation was never about using code for a specific purpose. This code was about worship, basking in the elegent simplicity of Perl and CPAN. It also inadvertently propagated some *bad* ideas in spam management...

The End Note:
I'm ambivalent about the practice of people trying to verify senders against my mail systems. On one hand, I think that a probe to test an address for sender authenticity is better than simply offloading an entire mail and having to bounce it later, or generate a DSN in response to a bad address. I just prefer it when people RSET and QUIT instead of leaving sessions open, which I consider a DoS attack, and blacklist accordingly. The practice breaks in a lot of scenarios though, such as outbound gateways that aren't linked, via static list or LDAP or inbound RCPT TO probes to valid address sources that inbound gateways have access to. Mostly, I use this kind of probe in tightly controlled scenarios, and am willing to tolerate it as incoming so long as my RSET/QUIT common courtesy request is met, and the person conducting the probe doesn't mind my ambiguous 2.7.1 response if they track back to the sending IP instead of connecting against the inbound gateways specified by MX.

In reply to Pondering the elegant simplicity of Net::SMTP by NoSignal

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.