File Coverage

blib/lib/Email/Verify/SMTP.pm
Criterion Covered Total %
statement 18 68 26.4
branch 0 32 0.0
condition 0 9 0.0
subroutine 6 9 66.6
pod 1 1 100.0
total 25 119 21.0


line stmt bran cond sub pod time code
1              
2             package Email::Verify::SMTP;
3              
4 1     1   753 use strict;
  1         2  
  1         42  
5 1     1   7 use warnings 'all';
  1         2  
  1         40  
6 1     1   13 use base 'Exporter';
  1         1  
  1         78  
7 1     1   910 use Net::Nslookup;
  1         952  
  1         53  
8 1     1   878 use IO::Socket::Telnet;
  1         187088  
  1         22  
9 1     1   1646 use Carp 'confess';
  1         3  
  1         1539  
10              
11             our @EXPORT = ('verify_email');
12             our $VERSION = '0.003';
13             our $FROM = 'root@localhost';
14             our $DEBUG = 0;
15              
16             sub verify_email
17             {
18 0 0   0 1   my $email = shift or return;
19 0           $email = lc($email);
20              
21 0           my $error;
22              
23 0           my (undef, $domain) = split /@/, $email;
24 0 0         unless( $domain )
25             {
26 0           return _result(
27             undef, "Invalid email address"
28             );
29             }# end unless()
30              
31              
32 0           my $err = undef;
33 0           my $host = $domain;
34             local $SIG{ALRM} = sub {
35 0     0     $err = "Timeout on host '$host'";
36 0           die "Timeout on host '$host'";
37 0           };
38              
39 0           alarm(4);
40 0 0         my ($mx) = eval {
41             my ($mx) = nslookup(domain => $domain, type => "MX")
42 0 0         or do { $err = "No mx records found for '$domain'"; die };
  0            
  0            
43 0           $mx;
44             } or return _result(undef, "No mx records found for '$domain'");
45 0           $host = $mx;
46 0           alarm(0);
47 0 0 0       return _result( undef, $err || $@ ) if $err || $@;
      0        
48              
49 0 0         my $t = IO::Socket::Telnet->new(
50             PeerAddr => $mx,
51             PeerPort => 25,
52             ) or return _result(undef, "Cannot open socket to '$mx'");
53              
54 0           alarm(8);
55 0           my $res = eval {
56 0           $t->send("helo $domain\n");
57 0 0         $t->recv(my $res, 4096) or do{ $err = "Socket error on HELO"; die };
  0            
  0            
58 0 0         warn $res if $DEBUG;
59              
60 0           $t->send(qq(mail from: <$FROM>\n));
61 0 0         $t->recv($res, 4096) or do{ $err = "Socket error on MAIL FROM"; die };
  0            
  0            
62 0 0         warn $res if $DEBUG;
63              
64 0           $t->send(qq(rcpt to: <$email>\n));
65 0 0         $t->recv($res, 4096) or do{ $err = "Socket error on RCPT TO"; die };
  0            
  0            
66 0 0         warn $res if $DEBUG;
67              
68 0           $res;
69             };
70 0           alarm(0);
71            
72 0           $t->close;
73 0 0 0       return _result( undef, $err || $@ ) if $@;
74            
75 0           my $is_valid = $res =~ m/^250\b/;
76 0 0         return _result( $is_valid, $is_valid ? "" : $res );
77             }# end verify()
78              
79              
80             sub _result
81             {
82 0     0     my ($valid, $msg) = @_;
83            
84 0 0         if( wantarray )
85             {
86 0           chomp($msg);
87             return (
88 0           $valid, $msg
89             );
90             }
91             else
92             {
93 0 0         return unless defined $valid;
94 0           return $valid;
95             }# end if()
96             }# end _result()
97              
98             1;# return true:
99              
100             =pod
101              
102             =head1 NAME
103              
104             Email::Verify::SMTP - Verify an email address by using SMTP.
105              
106             =head1 SYNOPSIS
107              
108             use Email::Verify::SMTP;
109            
110             # This is important:
111             $Email::Verify::SMTP::FROM = 'verifier@my-server.com';
112            
113             # Just a true/false:
114             if( verify_email('foo@example.com') ) {
115             # Email is valid
116             }
117            
118             # Find out if, and why not (if not):
119             my ($is_valid, $msg) = verify_email('foo@example.com');
120             if( $is_valid ) {
121             # Email is valid:
122             }
123             else {
124             # Email is *not* valid:
125             warn "Email is bad: $msg";
126             }
127              
128             =head1 DESCRIPTION
129              
130             C is what I came with when I needed to verify several email
131             addresses without actually sending them email.
132              
133             To put that another way:
134              
135             =over 4
136              
137             B
138              
139             =back
140              
141             =head1 EXPORTED FUNCTIONS
142              
143             =head2 verify_email( $email )
144              
145             Verifies the supplied email address.
146              
147             If called in scalar context, eg:
148              
149             my $is_valid = verify_email( $email )
150              
151             then you get a true or false value.
152              
153             If called in list context, eg:
154              
155             my ($is_valid, $why_not) = verify_email( $email )
156              
157             then you get both a true/false value and any error message that came up.
158              
159             =head1 PUBLIC STATIC VARIABLES
160              
161             =head2 $Email::Verify::SMTP::FROM
162              
163             Default value:
164              
165             This is used as the "from" field on the email that is not actually sent. It
166             should be a valid email address on a real domain - just like if you were sending
167             a normal email.
168              
169             =head2 $Email::Verify::SMTP::DEBUG
170              
171             Default value: C<0>
172              
173             If set to a true value, extra diagnostics will be output to STDERR via C.
174              
175             =head1 DEPENDENCIES
176              
177             This module depends on the following:
178              
179             =over 4
180              
181             =item L
182              
183             To discover the mail exchange servers for the email address provided.
184              
185             =item L
186              
187             A nice socket interface to use, even if you're not using Telnet.
188              
189             =back
190              
191             =head1 AUTHOR
192              
193             John Drago
194              
195             =head1 LICENSE
196              
197             This software is B software and may be used, copied and redistributed under
198             the same terms as perl itself.
199              
200             =cut
201