diff -r -u Email-Valid-0.13/Valid.pm Email-Valid-mxchecklocal/Valid.pm
--- Email-Valid-0.13/Valid.pm	Tue Jan 16 13:26:41 2001
+++ Email-Valid-mxchecklocal/Valid.pm	Tue Mar 26 20:01:46 2002
@@ -11,7 +11,7 @@
 
 $VERSION = '0.13';
 
-%AUTOLOAD = ( mxcheck => 1, fudge => 1, fqdn => 1, local_rules => 1 );
+%AUTOLOAD = ( mxcheck => 1, mxlocalcheck => 1, fudge => 1, fqdn => 1, local_rules => 1 );
 $NSLOOKUP_PAT = 'preference|serial|expire|mail\s+exchanger';
 @NSLOOKUP_PATHS = qw( /usr/bin /usr/sbin /bin );
 $DNS_Method = '';
@@ -22,7 +22,7 @@
   $class = ref $class || $class;
   bless my $self = {}, $class;
   $self->_initialize;
-  %$self = $self->_rearrange([qw( mxcheck fudge fqdn local_rules )], \@_);
+  %$self = $self->_rearrange([qw( mxcheck fudge fqdn local_rules mxlocalcheck )], \@_);
   return $self;
 }
 
@@ -32,6 +32,7 @@
   my $self = shift;
 
   $self->{mxcheck}     = 0;
+  $self->{mxclocalcheck} = 0;
   $self->{fudge}       = 0;
   $self->{fqdn}        = 1;
   $self->{local_rules} = 0;
@@ -110,24 +111,53 @@
 sub _net_dns_query {
   my $self = shift;
   my $host = shift;
+  my $checkname = shift;
 
   $Resolver = Net::DNS::Resolver->new unless defined $Resolver; 
 
-  my $packet = $Resolver->send($host, 'A')
+  # Do the MX check before the A check since it's first priority.
+  my $packet = $Resolver->send($host, 'MX')
     or croak $Resolver->errorstring;
-  return 1 if $packet->header->ancount;
- 
-  $packet = $Resolver->send($host, 'MX')
+  if ( $packet->header->ancount ) {
+    return 1 if $checkname eq 'mx';
+    my %exchange = ();
+    foreach my $rr ( $packet->answer ) {
+      if ($rr->type eq 'MX') {
+        $exchange{$rr->exchange} = 1;
+      }
+    }
+    # Check the IP addresses of the mail exchange hosts.
+    foreach my $rr ( $packet->additional ) {
+      return $self->details($checkname)
+        if $rr->type eq 'A' and
+           $exchange{$rr->name} and
+           $rr->address eq '127.0.0.1';
+    }
+    # If there were mail exchange hosts and none were local, then it's good.
+    return 1 if scalar keys %exchange;
+  }
+
+  # Check A records for direct IP resolution of host.
+  $packet = $Resolver->send($host, 'A')
     or croak $Resolver->errorstring;
-  return 1 if $packet->header->ancount;
- 
-  return $self->details('mx');               
+  if ( $packet->header->ancount ) {
+    return 1 if $checkname eq 'mx';
+    foreach my $rr ( $packet->answer ) {
+      return $self->details($checkname)
+        if $rr->type eq 'A' and
+           $rr->address eq '127.0.0.1';
+    }
+    return 1;
+  }
+
+  return $self->details($checkname);
 }
 
 # Purpose: perform DNS query using the nslookup utility
 sub _nslookup_query {
   my $self = shift;
   my $host = shift;
+  my $checkname = shift;
   local($/, *OLDERR);
 
   unless ($Nslookup_Path) {
@@ -143,7 +173,7 @@
     my $response = <$fh>;
     print STDERR $response if $Debug;
     close $fh;
-    $response =~ /$NSLOOKUP_PAT/io or return $self->details('mx');
+    $response =~ /$NSLOOKUP_PAT/io or return $self->details($checkname);
     return 1;
   } else {
     open OLDERR, '>&STDERR' or croak "cannot dup stderr: $!";
@@ -159,9 +189,10 @@
 # Purpose: Check whether a DNS record (A or MX) exists for a domain.
 sub mx {
   my $self = shift;
-  my %args = $self->_rearrange([qw( address )], \@_);
+  my %args = $self->_rearrange([qw( address checkname )], \@_);
 
-  my $addr = $args{address} or return $self->details('mx');
+  my $checkname = $args{checkname};
+  my $addr = $args{address} or return $self->details($checkname);
   $addr = $addr->address if UNIVERSAL::isa($addr, 'Mail::Address');
 
   my $host = ($addr =~ /^.*@(.*)$/ ? $1 : $addr);
@@ -179,10 +210,10 @@
 
   if ($DNS_Method eq 'Net::DNS') {
     print STDERR "using Net::DNS for dns query\n" if $Debug;
-    return $self->_net_dns_query( $host );
+    return $self->_net_dns_query( $host, $checkname );
   } elsif ($DNS_Method eq 'nslookup') {
     print STDERR "using nslookup for dns query\n" if $Debug;
-    return $self->_nslookup_query( $host );
+    return $self->_nslookup_query( $host, $checkname );
   } else {
     croak "unknown DNS method '$DNS_Method'";
   }
@@ -222,7 +253,7 @@
 sub address {
   my $self = shift;
   my %args = $self->_rearrange([qw( address fudge mxcheck fqdn  
-                                    local_rules )], \@_);
+                                    local_rules mxlocalcheck )], \@_);
 
   my $addr = $args{address} or return $self->details('rfc822');
   $addr = $addr->address if UNIVERSAL::isa($addr, 'Mail::Address');
@@ -242,8 +273,12 @@
     $addr->host =~ /^.+\..+$/ or return $self->details('fqdn');
   }
 
-  if ($args{mxcheck}) {
-    $self->mx( $addr->host ) or return undef; 
+  # mxlocalcheck includes mxcheck
+  if ($args{mxlocalcheck}) {
+    $self->mx( $addr->host, 'mxlocal' ) or return undef;
+
+  } elsif ($args{mxcheck}) {
+    $self->mx( $addr->host, 'mx' ) or return undef; 
   }
 
   return (wantarray ? ($addr->address, $addr) : $addr->address);  
@@ -410,6 +445,7 @@
 individual methods below of details.
 
  -mxcheck
+ -mxlocalcheck
  -fudge
  -fqdn
  -local_rules
@@ -457,15 +493,27 @@
 Specifies whether addresses passed to address() should be checked
 for a valid DNS entry.  The default is false.
 
+=item mxlocalcheck ( <TRUE>|<FALSE> )
+
+Specifies whether addresses passed to address() should be checked for
+a valid DNS entry (just like mxcheck).  In addition, this checks to
+make sure that the DNS entry is not 127.0.0.1 (localhost). Many
+domains set their MX host to resolve to 127.0.0.1 to indicate that
+they do not support email. The default is false.
+
+CAVEAT: mxlocalcheck only performs the additional localhost check when
+Net::DNS is available for DNS lookups.  Otherwise it behaves pretty
+much like mxcheck.
+
 =item address ( <ADDRESS> )
 
-This is the primary method which determines whether an email 
-address is valid.  It's behavior is modified by the values of
-mxcheck(), local_rules(), fqdn(), and fudge().  If the address
-passes all checks, the (possibly modified) address is returned as
-a string.  Otherwise, the undefined value is returned.
-In a list context, the method also returns an instance of the
-Mail::Address class representing the email address.
+This is the primary method which determines whether an email address
+is valid.  It's behavior is modified by the values of mxcheck(),
+mxlocalcheck(), local_rules(), fqdn(), and fudge().  If the address
+passes all checks, the (possibly modified) address is returned as a
+string.  Otherwise, the undefined value is returned.  In a list
+context, the method also returns an instance of the Mail::Address
+class representing the email address.
 
 =item details ()
 
@@ -475,7 +523,8 @@
  rfc822
  local_rules
  fqdn
- mxcheck  
+ mx
+ mxlocal
 
 If the class is not instantiated, you can get the same information
 from the global $Email::Valid::Details.  
Only in Email-Valid-mxchecklocal: Valid.pm~
diff -r -u Email-Valid-0.13/blib/lib/Email/Valid.pm Email-Valid-mxchecklocal/blib/lib/Email/Valid.pm
--- Email-Valid-0.13/blib/lib/Email/Valid.pm	Tue Jan 16 13:26:41 2001
+++ Email-Valid-mxchecklocal/blib/lib/Email/Valid.pm	Tue Mar 26 19:56:58 2002
@@ -11,7 +11,7 @@
 
 $VERSION = '0.13';
 
-%AUTOLOAD = ( mxcheck => 1, fudge => 1, fqdn => 1, local_rules => 1 );
+%AUTOLOAD = ( mxcheck => 1, mxlocalcheck => 1, fudge => 1, fqdn => 1, local_rules => 1 );
 $NSLOOKUP_PAT = 'preference|serial|expire|mail\s+exchanger';
 @NSLOOKUP_PATHS = qw( /usr/bin /usr/sbin /bin );
 $DNS_Method = '';
@@ -22,7 +22,7 @@
   $class = ref $class || $class;
   bless my $self = {}, $class;
   $self->_initialize;
-  %$self = $self->_rearrange([qw( mxcheck fudge fqdn local_rules )], \@_);
+  %$self = $self->_rearrange([qw( mxcheck fudge fqdn local_rules mxlocalcheck )], \@_);
   return $self;
 }
 
@@ -32,6 +32,7 @@
   my $self = shift;
 
   $self->{mxcheck}     = 0;
+  $self->{mxclocalcheck} = 0;
   $self->{fudge}       = 0;
   $self->{fqdn}        = 1;
   $self->{local_rules} = 0;
@@ -110,24 +111,49 @@
 sub _net_dns_query {
   my $self = shift;
   my $host = shift;
+  my $checkname = shift;
 
   $Resolver = Net::DNS::Resolver->new unless defined $Resolver; 
 
-  my $packet = $Resolver->send($host, 'A')
+  my $packet = $Resolver->send($host, 'MX')
     or croak $Resolver->errorstring;
-  return 1 if $packet->header->ancount;
- 
-  $packet = $Resolver->send($host, 'MX')
+  if ( $packet->header->ancount ) {
+    return 1 if $checkname eq 'mx';
+    my %exchange = ();
+    foreach my $rr ( $packet->answer ) {
+      if ($rr->type eq 'MX') {
+        $exchange{$rr->exchange} = 1;
+      }
+    }
+    foreach my $rr ( $packet->additional ) {
+      return $self->details($checkname)
+        if $rr->type eq 'A' and
+           $exchange{$rr->name} and
+           $rr->address eq '127.0.0.1';
+    }
+    return 1 if scalar keys %exchange;
+  }
+
+  $packet = $Resolver->send($host, 'A')
     or croak $Resolver->errorstring;
-  return 1 if $packet->header->ancount;
- 
-  return $self->details('mx');               
+  if ( $packet->header->ancount ) {
+    return 1 if $checkname eq 'mx';
+    foreach my $rr ( $packet->answer ) {
+      return $self->details($checkname)
+        if $rr->type eq 'A' and
+           $rr->address eq '127.0.0.1';
+    }
+    return 1;
+  }
+
+  return $self->details($checkname);
 }
 
 # Purpose: perform DNS query using the nslookup utility
 sub _nslookup_query {
   my $self = shift;
   my $host = shift;
+  my $checkname = shift;
   local($/, *OLDERR);
 
   unless ($Nslookup_Path) {
@@ -143,7 +169,7 @@
     my $response = <$fh>;
     print STDERR $response if $Debug;
     close $fh;
-    $response =~ /$NSLOOKUP_PAT/io or return $self->details('mx');
+    $response =~ /$NSLOOKUP_PAT/io or return $self->details($checkname);
     return 1;
   } else {
     open OLDERR, '>&STDERR' or croak "cannot dup stderr: $!";
@@ -159,9 +185,10 @@
 # Purpose: Check whether a DNS record (A or MX) exists for a domain.
 sub mx {
   my $self = shift;
-  my %args = $self->_rearrange([qw( address )], \@_);
+  my %args = $self->_rearrange([qw( address checkname )], \@_);
 
-  my $addr = $args{address} or return $self->details('mx');
+  my $checkname = $args{checkname};
+  my $addr = $args{address} or return $self->details($checkname);
   $addr = $addr->address if UNIVERSAL::isa($addr, 'Mail::Address');
 
   my $host = ($addr =~ /^.*@(.*)$/ ? $1 : $addr);
@@ -179,10 +206,10 @@
 
   if ($DNS_Method eq 'Net::DNS') {
     print STDERR "using Net::DNS for dns query\n" if $Debug;
-    return $self->_net_dns_query( $host );
+    return $self->_net_dns_query( $host, $checkname );
   } elsif ($DNS_Method eq 'nslookup') {
     print STDERR "using nslookup for dns query\n" if $Debug;
-    return $self->_nslookup_query( $host );
+    return $self->_nslookup_query( $host, $checkname );
   } else {
     croak "unknown DNS method '$DNS_Method'";
   }
@@ -222,7 +249,7 @@
 sub address {
   my $self = shift;
   my %args = $self->_rearrange([qw( address fudge mxcheck fqdn  
-                                    local_rules )], \@_);
+                                    local_rules mxlocalcheck )], \@_);
 
   my $addr = $args{address} or return $self->details('rfc822');
   $addr = $addr->address if UNIVERSAL::isa($addr, 'Mail::Address');
@@ -242,8 +269,12 @@
     $addr->host =~ /^.+\..+$/ or return $self->details('fqdn');
   }
 
-  if ($args{mxcheck}) {
-    $self->mx( $addr->host ) or return undef; 
+  # mxlocalcheck includes mxcheck
+  if ($args{mxlocalcheck}) {
+    $self->mx( $addr->host, 'mxlocal' ) or return undef;
+
+  } elsif ($args{mxcheck}) {
+    $self->mx( $addr->host, 'mx' ) or return undef; 
   }
 
   return (wantarray ? ($addr->address, $addr) : $addr->address);  
@@ -410,6 +441,7 @@
 individual methods below of details.
 
  -mxcheck
+ -mxlocalcheck
  -fudge
  -fqdn
  -local_rules
@@ -457,15 +489,27 @@
 Specifies whether addresses passed to address() should be checked
 for a valid DNS entry.  The default is false.
 
+=item mxlocalcheck ( <TRUE>|<FALSE> )
+
+Specifies whether addresses passed to address() should be checked for
+a valid DNS entry (just like mxcheck).  In addition, this checks to
+make sure that the DNS entry is not 127.0.0.1 (localhost). Many
+domains set their MX host to resolve to 127.0.0.1 to indicate that
+they do not support email. The default is false.
+
+CAVEAT: mxlocalcheck only performs the additional localhost check when
+Net::DNS is available for DNS lookups.  Otherwise it behaves pretty
+much like mxcheck.
+
 =item address ( <ADDRESS> )
 
-This is the primary method which determines whether an email 
-address is valid.  It's behavior is modified by the values of
-mxcheck(), local_rules(), fqdn(), and fudge().  If the address
-passes all checks, the (possibly modified) address is returned as
-a string.  Otherwise, the undefined value is returned.
-In a list context, the method also returns an instance of the
-Mail::Address class representing the email address.
+This is the primary method which determines whether an email address
+is valid.  It's behavior is modified by the values of mxcheck(),
+mxlocalcheck(), local_rules(), fqdn(), and fudge().  If the address
+passes all checks, the (possibly modified) address is returned as a
+string.  Otherwise, the undefined value is returned.  In a list
+context, the method also returns an instance of the Mail::Address
+class representing the email address.
 
 =item details ()
 
@@ -475,7 +519,8 @@
  rfc822
  local_rules
  fqdn
- mxcheck  
+ mx
+ mxlocal
 
 If the class is not instantiated, you can get the same information
 from the global $Email::Valid::Details.  
diff -r -u Email-Valid-0.13/t/valid.t Email-Valid-mxchecklocal/t/valid.t
--- Email-Valid-0.13/t/valid.t	Thu Jul  8 19:50:12 1999
+++ Email-Valid-mxchecklocal/t/valid.t	Tue Mar 26 19:39:05 2002
@@ -6,7 +6,7 @@
 # Change 1..1 below to 1..last_test_to_print .
 # (It may become useful if the test is moved to ./t subdirectory.)
 
-BEGIN { $| = 1; print "1..10\n"; }
+BEGIN { $| = 1; print "1..13\n"; }
 END {print "not ok 1\n" unless $loaded;}
 use Email::Valid;
 $loaded = 1;
@@ -47,3 +47,10 @@
              -mxcheck => 1) ? ok : not_ok;
 $v->address( -address => 'blort@notarealdomainfoo.com',
              -mxcheck => 1) ? not_ok : ok;   
+
+$v->address( -address => 'user@domain.com',
+                               ) ? ok : not_ok;   
+$v->address( -address => 'user@domain.com',
+             -mxcheck => 1     ) ? ok : not_ok;   
+$v->address( -address => 'user@domain.com',
+             -mxlocalcheck => 1) ? not_ok : ok;
