Fix copyright and version in comment and POD, too.
[mail/checkmail.git] / checkmail.pl
index c8f9e91..f4f881c 100644 (file)
@@ -1,15 +1,15 @@
-#! /usr/bin/perl -W
+#! /usr/bin/perl -w
 #
 #
-# checkmail Version 0.5 by Thomas Hochstein
+# checkmail Version 0.6.3 by Thomas Hochstein
 #
 # This script tries to verify the deliverability of (a) mail address(es).
 # 
 #
 # This script tries to verify the deliverability of (a) mail address(es).
 # 
-# Copyright (c) 2002-2010 Thomas Hochstein <thh@inter.net>
+# Copyright (c) 2002-2016 Thomas Hochstein <thh@inter.net>
 #
 # It can be redistributed and/or modified under the same terms under 
 # which Perl itself is published.
 
 #
 # It can be redistributed and/or modified under the same terms under 
 # which Perl itself is published.
 
-our $VERSION = "0.5";
+our $VERSION = "0.6.3 (unreleased)";
 
 ################################# Configuration ################################
 # Please fill in a working configuration!
 
 ################################# Configuration ################################
 # Please fill in a working configuration!
@@ -39,7 +39,7 @@ getopts('Vhqlrf:m:s:e:', \%options);
 
 # -V: display version
 if ($options{'V'}) {
 
 # -V: display version
 if ($options{'V'}) {
-  print "$myself v $VERSION\nCopyright (c) 2010 Thomas Hochstein <thh\@inter.net>\n";
+  print "$myself v $VERSION\nCopyright (c) 2010-2016 Thomas Hochstein <thh\@inter.net>\n";
   print "This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.\n";
   exit(100);
 };
   print "This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.\n";
   exit(100);
 };
@@ -67,7 +67,7 @@ if (!$options{'f'} and !$ARGV[0]) {
 };
 
 # -s / -e: override configuration
 };
 
 # -s / -e: override configuration
-$config{'from'} = $options{'s'} if $options{'s'};
+$config{'from'} = $options{'s'} if defined($options{'s'});
 $config{'helo'} = $options{'e'} if $options{'e'};
 
 # -f: open file and read addresses to @adresses
 $config{'helo'} = $options{'e'} if $options{'e'};
 
 # -f: open file and read addresses to @adresses
@@ -93,8 +93,9 @@ my (%targets,$curstat,$status,$log,$message);
 foreach (@addresses) {
   my $address = $_;
   # regexp taken from http://www.regular-expressions.info/email.html
 foreach (@addresses) {
   my $address = $_;
   # regexp taken from http://www.regular-expressions.info/email.html
-  # and escaping of "/" added two times
-  if ($address !~ /^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i) {
+  # with escaping of "/" added two times and "*" changed to "+"
+  # in localpart, second alternative
+  if ($address !~ /^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f]+)")@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i) {
     printf("  > Address <%s> is syntactically INVALID.\n",$address) if !($options{'q'});
     $curstat = 2;
   } else {
     printf("  > Address <%s> is syntactically INVALID.\n",$address) if !($options{'q'});
     $curstat = 2;
   } else {
@@ -153,11 +154,20 @@ sub gettargets {
   # no MX record found; log and try A record(s)
   } else {
     print_dns_result($domain,'MX',undef,$resolver->errorstring,$logr);
   # no MX record found; log and try A record(s)
   } else {
     print_dns_result($domain,'MX',undef,$resolver->errorstring,$logr);
-    print("    Falling back to A record ...\n") if !($options{'q'});
-       # get A record(s)
+    print("    Falling back to A record(s) ...\n") if !($options{'q'});
+    # get A record(s)
+    # may get CNAMEs instead ...
     if (my $query = $resolver->query($domain,'A','IN')) {
     if (my $query = $resolver->query($domain,'A','IN')) {
-      print_dns_result($domain,'A',$query->header->ancount,undef,$logr);
+      print_dns_result($domain,'A/CNAME',$query->header->ancount,undef,$logr);
       foreach my $rr ($query->answer) {
       foreach my $rr ($query->answer) {
+        if ($rr->type ne 'A') {
+          # report CNAMEs and don't add them to target list
+          if ($rr->type eq 'CNAME') {
+            printf ("  ~ '%s' is a CNAME for '%s' and will be resolved accordingly. \n",$rr->name,$rr->cname) if !($options{'q'});
+            $$logr .= sprintf("- CNAME resolved: %s -> %s\n",$rr->name,$rr->cname);
+          }
+          next;
+        }
         $targets{$rr->address} = 0;
         $$logr .= sprintf("- %s\n",$rr->address);
       };
         $targets{$rr->address} = 0;
         $$logr .= sprintf("- %s\n",$rr->address);
       };
@@ -223,10 +233,13 @@ sub checksmtp {
         # connection failure?
         if ($success < 0) {
           $status = connection_failed(@message);
         # connection failure?
         if ($success < 0) {
           $status = connection_failed(@message);
+          # reset status - the address has been checked and _is_ valid!
+          $status = 3;
+          print "  > Address verification currently impossible. You'll have to try again or send a test mail ...\n" if !($options{'q'});
         # verification impossible?
         } elsif ($success) {
           $status = 3;
         # verification impossible?
         } elsif ($success) {
           $status = 3;
-          print "  > Address verificaton impossible. You'll have to send a test mail ...\n" if !($options{'q'});
+          print "  > Address verification impossible. You'll have to send a test mail ...\n" if !($options{'q'});
         }
       }
       # if -r is not set or status was not set to 3: valid address
         }
       }
       # if -r is not set or status was not set to 3: valid address
@@ -436,6 +449,7 @@ The hostname to be used for I<HELO> or I<EHLO> in the SMTP dialog.
 =item B<$config{'from'}>
 
 The sender address to be used for I<MAIL FROM> while testing.
 =item B<$config{'from'}>
 
 The sender address to be used for I<MAIL FROM> while testing.
+May be empty ('') to set '<>' as MAIL FROM.
 
 =back
 
 
 =back
 
@@ -456,11 +470,12 @@ them in order of precedence (if necessary). It will run through the
 SMTP dialog until just before the I<DATA> stage, i.e. doing I<EHLO>,
 I<MAIL FROM> and I<RCPT TO>. If no MX is defined, B<checkmail> will
 fall back to the I<example.org> host itself, provided there is at
 SMTP dialog until just before the I<DATA> stage, i.e. doing I<EHLO>,
 I<MAIL FROM> and I<RCPT TO>. If no MX is defined, B<checkmail> will
 fall back to the I<example.org> host itself, provided there is at
-least one A record defined in the DNS. If there are neither MX nor A
-records for I<example.org>, mail is not deliverable and B<checkmail>
-will fail accordingly. If no host can be reached, B<checkmail> will
-fail, too. Finally B<checkmail> will fail if mail to the given
-recipient is not accepted by the respective host.
+least one A record defined in the DNS. CNAMEs will be accepted and
+resolved here. If there are neither MX nor A records for
+I<example.org>, mail is not deliverable and B<checkmail> will fail
+accordingly. If no host can be reached, B<checkmail> will fail,
+too. Finally B<checkmail> will fail if mail to the given recipient
+is not accepted by the respective host.
 
 If B<checkmail> fails, you'll not be able to deliver mail to that
 address - at least not using the configured sender address and from
 
 If B<checkmail> fails, you'll not be able to deliver mail to that
 address - at least not using the configured sender address and from
@@ -614,7 +629,7 @@ Thomas Hochstein <thh@inter.net>
 
 =head1 COPYRIGHT AND LICENSE
 
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright (c) 2002-2010 Thomas Hochstein <thh@inter.net>
+Copyright (c) 2002-2016 Thomas Hochstein <thh@inter.net>
 
 This program is free software; you may redistribute it and/or modify it
 under the same terms as Perl itself.
 
 This program is free software; you may redistribute it and/or modify it
 under the same terms as Perl itself.
This page took 0.012809 seconds and 4 git commands to generate.