File Coverage

blib/lib/Email/Valid.pm
Criterion Covered Total %
statement 138 201 68.6
branch 62 140 44.2
condition 28 58 48.2
subroutine 22 26 84.6
pod 6 6 100.0
total 256 431 59.4


line stmt bran cond sub pod time code
1             require 5.006;
2 3     3   895333 use strict;
  3         7  
  3         133  
3 3     3   25 use warnings;
  3         7  
  3         396  
4             package Email::Valid 1.204;
5              
6             # ABSTRACT: Check validity of Internet email addresses
7             our (
8             $RFC822PAT,
9             $Details, $Resolver, $Nslookup_Path,
10             $Debug,
11             );
12              
13 3     3   23 use Carp;
  3         7  
  3         265  
14 3     3   1219 use IO::File;
  3         24110  
  3         553  
15 3     3   1937 use Mail::Address;
  3         12471  
  3         138  
16 3     3   41 use File::Spec;
  3         6  
  3         117  
17 3     3   18 use Scalar::Util 'blessed';
  3         6  
  3         12570  
18              
19             our %AUTOLOAD = (
20             allow_ip => 1,
21             fqdn => 1,
22             fudge => 1,
23             mxcheck => 1,
24             tldcheck => 1,
25             local_rules => 1,
26             localpart => 1,
27             );
28              
29             our $NSLOOKUP_PAT = 'preference|serial|expire|mail\s+exchanger';
30             our @NSLOOKUP_PATHS = File::Spec->path();
31              
32             # initialize if already loaded, better in prefork mod_perl environment
33             our $DNS_Method = defined $Net::DNS::VERSION ? 'Net::DNS' : '';
34             unless ($DNS_Method) {
35             __PACKAGE__->_select_dns_method;
36             }
37              
38             # initialize $Resolver if necessary
39             if ($DNS_Method eq 'Net::DNS') {
40             unless (defined $Resolver) {
41             $Resolver = Net::DNS::Resolver->new;
42             }
43             }
44              
45             sub new {
46 1     1 1 334289 my $class = shift;
47              
48 1   33     7 $class = ref $class || $class;
49 1         4 bless my $self = {}, $class;
50 1         7 $self->_initialize;
51 1         11 %$self = $self->_rearrange([ keys %AUTOLOAD ], \@_);
52 1         7 return $self;
53             }
54              
55             sub _initialize {
56 5     5   22 my $self = shift;
57              
58 5         27 $self->{mxcheck} = 0;
59 5         11 $self->{tldcheck} = 0;
60 5         11 $self->{fudge} = 0;
61 5         10 $self->{fqdn} = 1;
62 5         12 $self->{allow_ip} = 1;
63 5         20 $self->{local_rules} = 0;
64 5         11 $self->{localpart} = 1;
65 5         15 $self->{details} = $Details = undef;
66             }
67              
68             # Pupose: handles named parameter calling style
69             sub _rearrange {
70 59     59   101 my $self = shift;
71 59         98 my(@names) = @{ shift() };
  59         193  
72 59         121 my(@params) = @{ shift() };
  59         131  
73 59         89 my(%args);
74              
75 59 100       379 ref $self ? %args = %$self : _initialize( \%args );
76 59 100       182 return %args unless @params;
77              
78 58 100 66     332 unless (@params > 1 and $params[0] =~ /^-/) {
79 12         29 while(@params) {
80 12 50       33 croak 'unexpected number of parameters' unless @names;
81 12         50 $args{ lc shift @names } = shift @params;
82             }
83 12         103 return %args;
84             }
85              
86 46         118 while(@params) {
87 61         160 my $param = lc substr(shift @params, 1);
88 61         241 $args{ $param } = shift @params;
89             }
90              
91 46         333 %args;
92             }
93              
94             # Purpose: determine why an address failed a check
95             sub details {
96 13     13 1 27 my $self = shift;
97              
98 13 50       52 return (ref $self ? $self->{details} : $Details) unless @_;
    100          
99 10         21 $Details = shift;
100 10 100       32 $self->{details} = $Details if ref $self;
101 10         123 return undef;
102             }
103              
104             # Purpose: Check whether address conforms to RFC 822 syntax.
105             sub rfc822 {
106 28     28 1 44 my $self = shift;
107 28         87 my %args = $self->_rearrange([qw( address )], \@_);
108              
109 28 50       129 my $addr = $args{address} or return $self->details('rfc822');
110 28 50 33     79 $addr = $addr->address if (blessed($addr) && $addr->isa('Mail::Address'));
111              
112 28 100 100     4754 return $self->details('rfc822')
113             if $addr =~ /\P{ASCII}/ or $addr !~ m/^$RFC822PAT$/o;
114              
115 25         156 return 1;
116             }
117              
118             # Purpose: attempt to locate the nslookup utility
119             sub _find_nslookup {
120 0     0   0 my $self = shift;
121              
122 0         0 my $ns = 'nslookup';
123 0         0 foreach my $path (@NSLOOKUP_PATHS) {
124 0         0 my $file = File::Spec->catfile($path, $ns);
125 0 0 0     0 return "$file.exe" if ($^O eq 'MSWin32') and -x "$file.exe" and !-d _;
      0        
126 0 0 0     0 return $file if -x $file and !-d _;
127             }
128 0         0 return undef;
129             }
130              
131             sub _select_dns_method {
132             # Configure a global resolver object for DNS queries
133             # if Net::DNS is available
134 2     2   5 eval { require Net::DNS };
  2         1163  
135 2 50       291434 return $DNS_Method = 'Net::DNS' unless $@;
136              
137 0         0 $DNS_Method = 'nslookup';
138             }
139              
140             # Purpose: perform DNS query using the Net::DNS module
141             sub _net_dns_query {
142 2     2   5 my $self = shift;
143 2         3 my $host = shift;
144              
145 2 50       5 $Resolver = Net::DNS::Resolver->new unless defined $Resolver;
146              
147 2         10 my @mx_entries = Net::DNS::mx($Resolver, $host);
148              
149             # Check for valid MX records for $host
150 2 50       200507 if (@mx_entries) {
151             # Check for RFC-7505 Null MX
152 2         6 my $nmx = scalar @mx_entries;
153 2 50 33     10 if ($nmx == 1 && $mx_entries[0]->exchange eq '.') {
154 0         0 return $self->details('mx');
155             }
156 2         6 foreach my $mx (@mx_entries) {
157 2         8 my $mxhost = $mx->exchange;
158 2         204 my $query = $Resolver->search($mxhost);
159 2 50       96621 next unless ($query);
160 2         10 foreach my $a_rr ($query->answer) {
161 2 50       31 return 1 unless $a_rr->type ne 'A';
162             }
163             }
164             }
165              
166             # Check for A record for $host
167 0         0 my $ans = $Resolver->query($host, 'A');
168 0 0       0 my @a_rrs = $ans ? $ans->answer : ();
169              
170 0 0       0 if (@a_rrs) {
171 0         0 foreach my $a_rr (@a_rrs) {
172 0 0       0 return 1 unless $a_rr->type ne 'A';
173             }
174             }
175              
176             # MX Check failed
177 0         0 return $self->details('mx');
178             }
179              
180             # Purpose: perform DNS query using the nslookup utility
181             sub _nslookup_query {
182 0     0   0 my $self = shift;
183 0         0 my $host = shift;
184 0         0 local($/, *OLDERR);
185              
186 0 0       0 unless ($Nslookup_Path) {
187 0 0       0 $Nslookup_Path = $self->_find_nslookup
188             or croak 'unable to locate nslookup';
189             }
190              
191             # Check for an A record
192 0 0       0 return 1 if gethostbyname $host;
193              
194             # Check for an MX record
195 0 0 0     0 if ($^O eq 'MSWin32' or $^O eq 'Cygwin') {
196             # Oh no, we're on Windows!
197 0         0 require Capture::Tiny;
198 0         0 my $response = Capture::Tiny::capture_stdout {
199 0         0 $Nslookup_Path, '-query=mx', $host
200             };
201 0 0       0 croak "unable to execute nslookup '$Nslookup_Path': exit $?" if $?;
202 0 0       0 print STDERR $response if $Debug;
203 0 0       0 $response =~ /$NSLOOKUP_PAT/io or return $self->details('mx');
204 0         0 return 1;
205             } else {
206             # phew, we're not on Windows!
207 0 0       0 if (my $fh = IO::File->new('-|')) {
208 0         0 my $response = <$fh>;
209 0 0       0 print STDERR $response if $Debug;
210 0         0 close $fh;
211 0 0       0 $response =~ /$NSLOOKUP_PAT/io or return $self->details('mx');
212 0         0 return 1;
213             } else {
214 0 0       0 open OLDERR, '>&STDERR' or croak "cannot dup stderr: $!";
215 0 0       0 open STDERR, '>&STDOUT' or croak "cannot redirect stderr to stdout: $!";
216             {
217 0         0 exec $Nslookup_Path, '-query=mx', $host;
  0         0  
218             }
219 0         0 open STDERR, ">&OLDERR";
220 0         0 croak "unable to execute nslookup '$Nslookup_Path': $!";
221             }
222             }
223             }
224              
225             # Purpose: Check whether a top level domain is valid for a domain.
226             sub tld {
227 0     0 1 0 my $self = shift;
228 0         0 my %args = $self->_rearrange([qw( address )], \@_);
229              
230 0 0       0 unless (eval {require Net::Domain::TLD; Net::Domain::TLD->VERSION(1.65); 1}) {
  0         0  
  0         0  
  0         0  
231 0         0 die "Net::Domain::TLD not available";
232             }
233              
234 0   0     0 my $host = $self->_host( $args{address} or return $self->details('tld') );
235 0         0 my ($tld) = $host =~ m#\.(\w+)$#;
236              
237 0         0 my %invalid_tlds = map { $_ => 1 } qw(invalid test example localhost);
  0         0  
238              
239 0 0       0 return defined $invalid_tlds{$tld} ? 0 : Net::Domain::TLD::tld_exists($tld);
240             }
241              
242             # Purpose: Check whether a DNS record (A or MX) exists for a domain.
243             sub mx {
244 2     2 1 27 my $self = shift;
245 2         28 my %args = $self->_rearrange([qw( address )], \@_);
246              
247 2 50       11 my $host = $self->_host($args{address}) or return $self->details('mx');
248              
249 2 50       7 $self->_select_dns_method unless $DNS_Method;
250              
251 2 50       6 if ($DNS_Method eq 'Net::DNS') {
    0          
252 2 50       7 print STDERR "using Net::DNS for dns query\n" if $Debug;
253 2         9 return $self->_net_dns_query( $host );
254             } elsif ($DNS_Method eq 'nslookup') {
255 0 0       0 print STDERR "using nslookup for dns query\n" if $Debug;
256 0         0 return $self->_nslookup_query( $host );
257             } else {
258 0         0 croak "unknown DNS method '$DNS_Method'";
259             }
260             }
261              
262             # Purpose: convert address to host
263             # Returns: host
264              
265             sub _host {
266 2     2   4 my $self = shift;
267 2         4 my $addr = shift;
268              
269 2 50 33     9 $addr = $addr->address if (blessed($addr) && $addr->isa('Mail::Address'));
270              
271 2 50       9 my $host = ($addr =~ /^.*@(.*)$/ ? $1 : $addr);
272 2         7 $host =~ s/\s+//g;
273              
274             # REMOVE BRACKETS IF IT'S A DOMAIN-LITERAL
275             # RFC822 3.4.6
276             # Square brackets ("[" and "]") are used to indicate the
277             # presence of a domain-literal, which the appropriate
278             # name-domain is to use directly, bypassing normal
279             # name-resolution mechanisms.
280 2         13 $host =~ s/(^\[)|(\]$)//g;
281 2         10 $host;
282             }
283              
284             # Purpose: Fix common addressing errors
285             # Returns: Possibly modified address
286             sub _fudge {
287 1     1   2 my $self = shift;
288 1         3 my $addr = shift;
289              
290 1 50       14 $addr =~ s/\s+//g if $addr =~ /aol\.com$/i;
291 1 50       5 $addr =~ s/,/./g if $addr =~ /compuserve\.com$/i;
292 1         4 $addr;
293             }
294              
295             # Purpose: Special address restrictions on a per-domain basis.
296             # Caveats: These organizations may change their rules at any time.
297             sub _local_rules {
298 0     0   0 my $self = shift;
299 0         0 my($user, $host) = @_;
300              
301 0         0 1;
302             }
303              
304             sub _valid_local_part {
305 24     24   355 my ($self, $localpart) = @_;
306              
307 24 100 66     113 return 0 unless defined $localpart and length $localpart <= 64;
308              
309 23         72 return 1;
310             }
311              
312             sub _valid_domain_parts {
313 21     21   292 my ($self, $string) = @_;
314              
315 21 50 33     92 return unless $string and length $string <= 255;
316 21 50       78 return if $string =~ /\.\./;
317 21         92 my @labels = split /\./, $string;
318              
319 21         74 for my $label (@labels) {
320 43 100       90 return 0 unless $self->_is_domain_label($label);
321             }
322 18         44 return scalar @labels;
323             }
324              
325             sub _is_domain_label {
326 43     43   81 my ($self, $string) = @_;
327 43 100       196 return unless $string =~ /\A
328             [A-Z0-9] # must start with an alnum
329             (?:
330             [-A-Z0-9]* # then maybe a dash or alnum
331             [A-Z0-9] # finally ending with an alnum
332             )? # lather, rinse, repeat
333             \z/ix;
334 40         108 return 1;
335             }
336              
337             # Purpose: Put an address through a series of checks to determine
338             # whether it should be considered valid.
339             sub address {
340 28     28 1 461701 my $self = shift;
341 28         152 my %args = $self->_rearrange([qw( address fudge mxcheck tldcheck fqdn
342             local_rules )], \@_);
343              
344 28 50       136 my $addr = $args{address} or return $self->details('rfc822');
345 28 100 66     98 $addr = $addr->address if (blessed($addr) && $addr->isa('Mail::Address'));
346              
347 28 100       95 $addr = $self->_fudge( $addr ) if $args{fudge};
348 28 100       88 $self->rfc822( -address => $addr ) or return undef;
349              
350 25         138 ($addr) = Mail::Address->parse( $addr );
351              
352 25 50       5541 $addr or return $self->details('rfc822'); # This should never happen
353              
354 25 100       82 if (length($addr->address) > 254) {
355 1         13 return $self->details('address_too_long');
356             }
357              
358 24 50       292 if ($args{local_rules}) {
359 0 0       0 $self->_local_rules( $addr->user, $addr->host )
360             or return $self->details('local_rules');
361             }
362              
363 24 50       71 if ($args{localpart}) {
364 24 100       79 $self->_valid_local_part($addr->user) > 0
365             or return $self->details('localpart');
366             }
367              
368 23   100     107 my $ip_ok = $args{allow_ip} && $addr->host =~ /\A\[
369             (?:[0-9]{1,3}\.){3}[0-9]{1,3}
370             /x;
371              
372 23 100 100     414 if (! $ip_ok && $args{fqdn}) {
373 21         51 my $domain_parts = $self->_valid_domain_parts($addr->host);
374              
375 21 100 100     128 return $self->details('fqdn')
      66        
376             unless $ip_ok || ($domain_parts && $domain_parts > 1);
377             }
378              
379 18 50 66     96 if (! $ip_ok && $args{tldcheck}) {
380 0 0       0 $self->tld( $addr->host ) or return $self->details('tldcheck');
381             }
382              
383 18 100       54 if ($args{mxcheck}) {
384             # I'm not sure this ->details call is needed, but I'll test for it later.
385             # The whole ->details thing is... weird. -- rjbs, 2006-06-08
386 2 50       8 $self->mx( $addr->host ) or return $self->details('mxcheck');
387             }
388              
389 18 50       213 return (wantarray ? ($addr->address, $addr) : $addr->address);
390             }
391              
392             sub AUTOLOAD {
393 1     1   5672 my $self = shift;
394 1   50     5 my $type = ref($self) || die "$self is not an object";
395 1         4 my $name = our $AUTOLOAD;
396              
397 1         7 $name =~ s/.*://;
398 1 50       144 return if $name eq 'DESTROY';
399 0 0         die "unknown autoload name '$name'" unless $AUTOLOAD{$name};
400              
401 0 0         return (@_ ? $self->{$name} = shift : $self->{$name});
402             }
403              
404             # Regular expression built using Jeffrey Friedl's example in
405             # _Mastering Regular Expressions_ (http://www.ora.com/catalog/regexp/).
406              
407             $RFC822PAT = <<'EOF';
408             [\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\
409             xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xf
410             f\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\x
411             ff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015
412             "]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\
413             xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80
414             -\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*
415             )*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\
416             \\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\
417             x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x8
418             0-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n
419             \015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x
420             80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
421             \x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
422             \t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([
423             ^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\
424             \\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\
425             x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-
426             \xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()
427             ]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\
428             x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\04
429             0\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\
430             n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\
431             015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?!
432             [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\
433             ]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\
434             x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\01
435             5()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*|(?:[^(\040)<>@,;:".
436             \\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]
437             )|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^
438             ()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*(?:(?:\([^\\\x80-\xff\n\0
439             15()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][
440             ^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)|"[^\\\x80-\xff\
441             n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\
442             x80-\xff\000-\010\012-\037]*)*<[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?
443             :(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-
444             \xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:@[\040\t]*
445             (?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015
446             ()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()
447             ]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\0
448             40)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\
449             [^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\
450             xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*
451             )*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80
452             -\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x
453             80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t
454             ]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\
455             \[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])
456             *\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x
457             80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80
458             -\xff\n\015()]*)*\)[\040\t]*)*)*(?:,[\040\t]*(?:\([^\\\x80-\xff\n\015(
459             )]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\
460             \x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*@[\040\t
461             ]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\0
462             15()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015
463             ()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(
464             \040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|
465             \\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80
466             -\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()
467             ]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x
468             80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
469             \x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
470             \t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".
471             \\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff
472             ])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\
473             \x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x
474             80-\xff\n\015()]*)*\)[\040\t]*)*)*)*:[\040\t]*(?:\([^\\\x80-\xff\n\015
475             ()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\
476             \\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)?(?:[^
477             (\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-
478             \037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\
479             n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|
480             \([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))
481             [^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff
482             \n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\x
483             ff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(
484             ?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\
485             000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\
486             xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\x
487             ff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)
488             *\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\x
489             ff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-
490             \xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)
491             *(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\
492             ]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]
493             )[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-
494             \xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\x
495             ff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(
496             ?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80
497             -\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<
498             >@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x8
499             0-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:
500             \([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]
501             *(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)
502             *\)[\040\t]*)*)*>)
503             EOF
504              
505             $RFC822PAT =~ s/\n//g;
506              
507             1;
508              
509              
510             #pod =head1 SYNOPSIS
511             #pod
512             #pod use Email::Valid;
513             #pod my $address = Email::Valid->address('maurice@hevanet.com');
514             #pod print ($address ? 'yes' : 'no');
515             #pod
516             #pod =head1 DESCRIPTION
517             #pod
518             #pod This module determines whether an email address is well-formed, and
519             #pod optionally, whether a mail host exists for the domain.
520             #pod
521             #pod Please note that there is no way to determine whether an
522             #pod address is deliverable without attempting delivery
523             #pod (for details, see L<perlfaq 9|http://perldoc.perl.org/perlfaq9.html#How-do-I-check-a-valid-mail-address>).
524             #pod
525             #pod =head1 PREREQUISITES
526             #pod
527             #pod This module requires perl 5.004 or later and the L<Mail::Address> module.
528             #pod Either the L<Net::DNS> module or the nslookup utility is required
529             #pod for DNS checks. The L<Net::Domain::TLD> module is required to check the
530             #pod validity of top level domains.
531             #pod
532             #pod =head1 METHODS
533             #pod
534             #pod Every method which accepts an C<< <ADDRESS> >> parameter may
535             #pod be passed either a string or an instance of the Mail::Address
536             #pod class. All errors raise an exception.
537             #pod
538             #pod =over 4
539             #pod
540             #pod =item new ( [PARAMS] )
541             #pod
542             #pod This method is used to construct an Email::Valid object.
543             #pod It accepts an optional list of named parameters to
544             #pod control the behavior of the object at instantiation.
545             #pod
546             #pod The following named parameters are allowed. See the
547             #pod individual methods below for details.
548             #pod
549             #pod -mxcheck
550             #pod -tldcheck
551             #pod -fudge
552             #pod -fqdn
553             #pod -allow_ip
554             #pod -local_rules
555             #pod
556             #pod =item mx ( <ADDRESS>|<DOMAIN> )
557             #pod
558             #pod This method accepts an email address or domain name and determines
559             #pod whether a DNS record (A or MX) exists for it.
560             #pod
561             #pod The method returns true if a record is found and undef if not.
562             #pod
563             #pod Either the Net::DNS module or the nslookup utility is required for
564             #pod DNS checks. Using Net::DNS is the preferred method since error
565             #pod handling is improved. If Net::DNS is available, you can modify
566             #pod the behavior of the resolver (e.g. change the default tcp_timeout
567             #pod value) by manipulating the global L<Net::DNS::Resolver> instance stored in
568             #pod C<$Email::Valid::Resolver>.
569             #pod
570             #pod =item rfc822 ( <ADDRESS> )
571             #pod
572             #pod This method determines whether an address conforms to the RFC822
573             #pod specification (except for nested comments). It returns true if it
574             #pod conforms and undef if not.
575             #pod
576             #pod =item fudge ( <TRUE>|<FALSE> )
577             #pod
578             #pod Specifies whether calls to address() should attempt to correct
579             #pod common addressing errors. Currently, this results in the removal of
580             #pod spaces in AOL addresses, and the conversion of commas to periods in
581             #pod Compuserve addresses. The default is false.
582             #pod
583             #pod =item allow_ip ( <TRUE>|<FALSE> )
584             #pod
585             #pod Specifies whether a "domain literal" is acceptable as the domain part. That
586             #pod means addresses like: C<rjbs@[1.2.3.4]>
587             #pod
588             #pod The checking for the domain literal is stricter than the RFC and looser than
589             #pod checking for a valid IP address, I<but this is subject to change>.
590             #pod
591             #pod The default is true.
592             #pod
593             #pod =item fqdn ( <TRUE>|<FALSE> )
594             #pod
595             #pod Specifies whether addresses passed to address() must contain a fully
596             #pod qualified domain name (FQDN). The default is true.
597             #pod
598             #pod B<Please note!> FQDN checks only occur for non-domain-literals. In other
599             #pod words, if you have set C<allow_ip> and the address ends in a bracketed IP
600             #pod address, the FQDN check will not occur.
601             #pod
602             #pod =item tld ( <ADDRESS> )
603             #pod
604             #pod This method determines whether the domain part of an address is in a
605             #pod recognized top-level domain.
606             #pod
607             #pod B<Please note!> TLD checks only occur for non-domain-literals. In other
608             #pod words, if you have set C<allow_ip> and the address ends in a bracketed IP
609             #pod address, the TLD check will not occur.
610             #pod
611             #pod =item local_rules ( <TRUE>|<FALSE> )
612             #pod
613             #pod Specifies whether addresses passed to address() should be tested
614             #pod for domain specific restrictions. Currently, this is limited to
615             #pod certain AOL restrictions that I'm aware of. The default is false.
616             #pod
617             #pod =item mxcheck ( <TRUE>|<FALSE> )
618             #pod
619             #pod Specifies whether addresses passed to address() should be checked
620             #pod for a valid DNS entry. The default is false.
621             #pod
622             #pod =item tldcheck ( <TRUE>|<FALSE> )
623             #pod
624             #pod Specifies whether addresses passed to address() should be checked
625             #pod for a valid top level domains. The default is false.
626             #pod
627             #pod =item address ( <ADDRESS> )
628             #pod
629             #pod This is the primary method which determines whether an email
630             #pod address is valid. Its behavior is modified by the values of
631             #pod mxcheck(), tldcheck(), local_rules(), fqdn(), and fudge(). If the address
632             #pod passes all checks, the (possibly modified) address is returned as
633             #pod a string. Otherwise, undef is returned.
634             #pod In a list context, the method also returns an instance of the
635             #pod Mail::Address class representing the email address.
636             #pod
637             #pod =item details ()
638             #pod
639             #pod If the last call to address() returned undef, you can call this
640             #pod method to determine why it failed. Possible values are:
641             #pod
642             #pod rfc822
643             #pod localpart
644             #pod local_rules
645             #pod fqdn
646             #pod mxcheck
647             #pod tldcheck
648             #pod
649             #pod If the class is not instantiated, you can get the same information
650             #pod from the global C<$Email::Valid::Details>.
651             #pod
652             #pod =back
653             #pod
654             #pod =head1 EXAMPLES
655             #pod
656             #pod Let's see if the address 'maurice@hevanet.com' conforms to the
657             #pod RFC822 specification:
658             #pod
659             #pod print (Email::Valid->address('maurice@hevanet.com') ? 'yes' : 'no');
660             #pod
661             #pod Additionally, let's make sure there's a mail host for it:
662             #pod
663             #pod print (Email::Valid->address( -address => 'maurice@hevanet.com',
664             #pod -mxcheck => 1 ) ? 'yes' : 'no');
665             #pod
666             #pod Let's see an example of how the address may be modified:
667             #pod
668             #pod $addr = Email::Valid->address('Alfred Neuman <Neuman @ foo.bar>');
669             #pod print "$addr\n"; # prints Neuman@foo.bar
670             #pod
671             #pod Now let's add the check for top level domains:
672             #pod
673             #pod $addr = Email::Valid->address( -address => 'Neuman@foo.bar',
674             #pod -tldcheck => 1 );
675             #pod print "$addr\n"; # doesn't print anything
676             #pod
677             #pod Need to determine why an address failed?
678             #pod
679             #pod unless(Email::Valid->address('maurice@hevanet')) {
680             #pod print "address failed $Email::Valid::Details check.\n";
681             #pod }
682             #pod
683             #pod If an error is encountered, an exception is raised. This is really
684             #pod only possible when performing DNS queries. Trap any exceptions by
685             #pod wrapping the call in an eval block:
686             #pod
687             #pod eval {
688             #pod $addr = Email::Valid->address( -address => 'maurice@hevanet.com',
689             #pod -mxcheck => 1 );
690             #pod };
691             #pod warn "an error was encountered: $@" if $@;
692             #pod
693             #pod =head1 CREDITS
694             #pod
695             #pod Significant portions of this module are based on the ckaddr program
696             #pod written by Tom Christiansen and the RFC822 address pattern developed
697             #pod by Jeffrey Friedl. Neither were involved in the construction of this
698             #pod module; all errors are mine.
699             #pod
700             #pod Thanks very much to the following people for their suggestions and
701             #pod bug fixes:
702             #pod
703             #pod Otis Gospodnetic <otis@DOMINIS.com>
704             #pod Kim Ryan <kimaryan@ozemail.com.au>
705             #pod Pete Ehlke <pde@listserv.music.sony.com>
706             #pod Lupe Christoph
707             #pod David Birnbaum
708             #pod Achim
709             #pod Elizabeth Mattijsen (liz@dijkmat.nl)
710             #pod
711             #pod =head1 SEE ALSO
712             #pod
713             #pod L<Mail::Address>, L<Net::DNS>, L<Net::Domain::TLD>, L<perlfaq9|https://metacpan.org/pod/distribution/perlfaq/lib/perlfaq9.pod>
714             #pod
715             #pod L<RFC822|https://www.ietf.org/rfc/rfc0822.txt> -
716             #pod standard for the format of ARPA internet text messages.
717             #pod Superseded by L<RFC2822|https://www.ietf.org/rfc/rfc2822.txt>.
718             #pod
719             #pod =cut
720              
721             __END__
722              
723             =pod
724              
725             =encoding UTF-8
726              
727             =head1 NAME
728              
729             Email::Valid - Check validity of Internet email addresses
730              
731             =head1 VERSION
732              
733             version 1.204
734              
735             =head1 SYNOPSIS
736              
737             use Email::Valid;
738             my $address = Email::Valid->address('maurice@hevanet.com');
739             print ($address ? 'yes' : 'no');
740              
741             =head1 DESCRIPTION
742              
743             This module determines whether an email address is well-formed, and
744             optionally, whether a mail host exists for the domain.
745              
746             Please note that there is no way to determine whether an
747             address is deliverable without attempting delivery
748             (for details, see L<perlfaq 9|http://perldoc.perl.org/perlfaq9.html#How-do-I-check-a-valid-mail-address>).
749              
750             =head1 PERL VERSION
751              
752             This library should run on perls released even a long time ago. It should
753             work on any version of perl released in the last five years.
754              
755             Although it may work on older versions of perl, no guarantee is made that the
756             minimum required version will not be increased. The version may be increased
757             for any reason, and there is no promise that patches will be accepted to
758             lower the minimum required perl.
759              
760             =head1 PREREQUISITES
761              
762             This module requires perl 5.004 or later and the L<Mail::Address> module.
763             Either the L<Net::DNS> module or the nslookup utility is required
764             for DNS checks. The L<Net::Domain::TLD> module is required to check the
765             validity of top level domains.
766              
767             =head1 METHODS
768              
769             Every method which accepts an C<< <ADDRESS> >> parameter may
770             be passed either a string or an instance of the Mail::Address
771             class. All errors raise an exception.
772              
773             =over 4
774              
775             =item new ( [PARAMS] )
776              
777             This method is used to construct an Email::Valid object.
778             It accepts an optional list of named parameters to
779             control the behavior of the object at instantiation.
780              
781             The following named parameters are allowed. See the
782             individual methods below for details.
783              
784             -mxcheck
785             -tldcheck
786             -fudge
787             -fqdn
788             -allow_ip
789             -local_rules
790              
791             =item mx ( <ADDRESS>|<DOMAIN> )
792              
793             This method accepts an email address or domain name and determines
794             whether a DNS record (A or MX) exists for it.
795              
796             The method returns true if a record is found and undef if not.
797              
798             Either the Net::DNS module or the nslookup utility is required for
799             DNS checks. Using Net::DNS is the preferred method since error
800             handling is improved. If Net::DNS is available, you can modify
801             the behavior of the resolver (e.g. change the default tcp_timeout
802             value) by manipulating the global L<Net::DNS::Resolver> instance stored in
803             C<$Email::Valid::Resolver>.
804              
805             =item rfc822 ( <ADDRESS> )
806              
807             This method determines whether an address conforms to the RFC822
808             specification (except for nested comments). It returns true if it
809             conforms and undef if not.
810              
811             =item fudge ( <TRUE>|<FALSE> )
812              
813             Specifies whether calls to address() should attempt to correct
814             common addressing errors. Currently, this results in the removal of
815             spaces in AOL addresses, and the conversion of commas to periods in
816             Compuserve addresses. The default is false.
817              
818             =item allow_ip ( <TRUE>|<FALSE> )
819              
820             Specifies whether a "domain literal" is acceptable as the domain part. That
821             means addresses like: C<rjbs@[1.2.3.4]>
822              
823             The checking for the domain literal is stricter than the RFC and looser than
824             checking for a valid IP address, I<but this is subject to change>.
825              
826             The default is true.
827              
828             =item fqdn ( <TRUE>|<FALSE> )
829              
830             Specifies whether addresses passed to address() must contain a fully
831             qualified domain name (FQDN). The default is true.
832              
833             B<Please note!> FQDN checks only occur for non-domain-literals. In other
834             words, if you have set C<allow_ip> and the address ends in a bracketed IP
835             address, the FQDN check will not occur.
836              
837             =item tld ( <ADDRESS> )
838              
839             This method determines whether the domain part of an address is in a
840             recognized top-level domain.
841              
842             B<Please note!> TLD checks only occur for non-domain-literals. In other
843             words, if you have set C<allow_ip> and the address ends in a bracketed IP
844             address, the TLD check will not occur.
845              
846             =item local_rules ( <TRUE>|<FALSE> )
847              
848             Specifies whether addresses passed to address() should be tested
849             for domain specific restrictions. Currently, this is limited to
850             certain AOL restrictions that I'm aware of. The default is false.
851              
852             =item mxcheck ( <TRUE>|<FALSE> )
853              
854             Specifies whether addresses passed to address() should be checked
855             for a valid DNS entry. The default is false.
856              
857             =item tldcheck ( <TRUE>|<FALSE> )
858              
859             Specifies whether addresses passed to address() should be checked
860             for a valid top level domains. The default is false.
861              
862             =item address ( <ADDRESS> )
863              
864             This is the primary method which determines whether an email
865             address is valid. Its behavior is modified by the values of
866             mxcheck(), tldcheck(), local_rules(), fqdn(), and fudge(). If the address
867             passes all checks, the (possibly modified) address is returned as
868             a string. Otherwise, undef is returned.
869             In a list context, the method also returns an instance of the
870             Mail::Address class representing the email address.
871              
872             =item details ()
873              
874             If the last call to address() returned undef, you can call this
875             method to determine why it failed. Possible values are:
876              
877             rfc822
878             localpart
879             local_rules
880             fqdn
881             mxcheck
882             tldcheck
883              
884             If the class is not instantiated, you can get the same information
885             from the global C<$Email::Valid::Details>.
886              
887             =back
888              
889             =head1 EXAMPLES
890              
891             Let's see if the address 'maurice@hevanet.com' conforms to the
892             RFC822 specification:
893              
894             print (Email::Valid->address('maurice@hevanet.com') ? 'yes' : 'no');
895              
896             Additionally, let's make sure there's a mail host for it:
897              
898             print (Email::Valid->address( -address => 'maurice@hevanet.com',
899             -mxcheck => 1 ) ? 'yes' : 'no');
900              
901             Let's see an example of how the address may be modified:
902              
903             $addr = Email::Valid->address('Alfred Neuman <Neuman @ foo.bar>');
904             print "$addr\n"; # prints Neuman@foo.bar
905              
906             Now let's add the check for top level domains:
907              
908             $addr = Email::Valid->address( -address => 'Neuman@foo.bar',
909             -tldcheck => 1 );
910             print "$addr\n"; # doesn't print anything
911              
912             Need to determine why an address failed?
913              
914             unless(Email::Valid->address('maurice@hevanet')) {
915             print "address failed $Email::Valid::Details check.\n";
916             }
917              
918             If an error is encountered, an exception is raised. This is really
919             only possible when performing DNS queries. Trap any exceptions by
920             wrapping the call in an eval block:
921              
922             eval {
923             $addr = Email::Valid->address( -address => 'maurice@hevanet.com',
924             -mxcheck => 1 );
925             };
926             warn "an error was encountered: $@" if $@;
927              
928             =head1 CREDITS
929              
930             Significant portions of this module are based on the ckaddr program
931             written by Tom Christiansen and the RFC822 address pattern developed
932             by Jeffrey Friedl. Neither were involved in the construction of this
933             module; all errors are mine.
934              
935             Thanks very much to the following people for their suggestions and
936             bug fixes:
937              
938             Otis Gospodnetic <otis@DOMINIS.com>
939             Kim Ryan <kimaryan@ozemail.com.au>
940             Pete Ehlke <pde@listserv.music.sony.com>
941             Lupe Christoph
942             David Birnbaum
943             Achim
944             Elizabeth Mattijsen (liz@dijkmat.nl)
945              
946             =head1 SEE ALSO
947              
948             L<Mail::Address>, L<Net::DNS>, L<Net::Domain::TLD>, L<perlfaq9|https://metacpan.org/pod/distribution/perlfaq/lib/perlfaq9.pod>
949              
950             L<RFC822|https://www.ietf.org/rfc/rfc0822.txt> -
951             standard for the format of ARPA internet text messages.
952             Superseded by L<RFC2822|https://www.ietf.org/rfc/rfc2822.txt>.
953              
954             =head1 AUTHOR
955              
956             Maurice Aubrey <maurice@hevanet.com>
957              
958             =head1 CONTRIBUTORS
959              
960             =for stopwords Alexandr Ciornii Arne Johannessen Dan Book Gene Hightower James E Keenan Karel Miko McA Michael Schout Mohammad S Anwar Neil Bowers Ricardo Signes Steve Bertrand Svetlana Troy Morehouse Yanick Champoux
961              
962             =over 4
963              
964             =item *
965              
966             Alexandr Ciornii <alexchorny@gmail.com>
967              
968             =item *
969              
970             Arne Johannessen <ajnn@cpan.org>
971              
972             =item *
973              
974             Dan Book <grinnz@gmail.com>
975              
976             =item *
977              
978             Gene Hightower <gene@digilicious.com>
979              
980             =item *
981              
982             James E Keenan <jkeenan@cpan.org>
983              
984             =item *
985              
986             Karel Miko <karel.miko@gmail.com>
987              
988             =item *
989              
990             McA <McA@github.com>
991              
992             =item *
993              
994             Michael Schout <mschout@gkg.net>
995              
996             =item *
997              
998             Mohammad S Anwar <mohammad.anwar@yahoo.com>
999              
1000             =item *
1001              
1002             Neil Bowers <neil@bowers.com>
1003              
1004             =item *
1005              
1006             Ricardo Signes <rjbs@semiotic.systems>
1007              
1008             =item *
1009              
1010             Steve Bertrand <steveb@cpan.org>
1011              
1012             =item *
1013              
1014             Svetlana <svetlana.wiczer@gmail.com>
1015              
1016             =item *
1017              
1018             Troy Morehouse <troymore@nbnet.nb.ca>
1019              
1020             =item *
1021              
1022             Yanick Champoux <yanick@babyl.dyndns.org>
1023              
1024             =back
1025              
1026             =head1 COPYRIGHT AND LICENSE
1027              
1028             This software is copyright (c) 1998 by Maurice Aubrey.
1029              
1030             This is free software; you can redistribute it and/or modify it under
1031             the same terms as the Perl 5 programming language system itself.
1032              
1033             =cut