Newer
Older
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
sub clean_file_emails {
my (@file_emails) = @_;
my @fmt_emails = ();
foreach my $email (@file_emails) {
$email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
my ($name, $address) = parse_email($email);
if ($name eq '"[,\.]"') {
$name = "";
}
my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
if (@nw > 2) {
my $first = $nw[@nw - 3];
my $middle = $nw[@nw - 2];
my $last = $nw[@nw - 1];
if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
(length($first) == 2 && substr($first, -1) eq ".")) ||
(length($middle) == 1 ||
(length($middle) == 2 && substr($middle, -1) eq "."))) {
$name = "$first $middle $last";
} else {
$name = "$middle $last";
}
}
if (substr($name, -1) =~ /[,\.]/) {
$name = substr($name, 0, length($name) - 1);
} elsif (substr($name, -2) =~ /[,\.]"/) {
$name = substr($name, 0, length($name) - 2) . '"';
}
if (substr($name, 0, 1) =~ /[,\.]/) {
$name = substr($name, 1, length($name) - 1);
} elsif (substr($name, 0, 2) =~ /"[,\.]/) {
$name = '"' . substr($name, 2, length($name) - 2);
}
my $fmt_email = format_email($name, $address, $email_usename);
push(@fmt_emails, $fmt_email);
}
return @fmt_emails;
}
sub merge_email {
my @lines;
my %saw;
for (@_) {
my ($address, $role) = @$_;
if (!$saw{$address}) {
if ($output_roles) {
push(@lines, "$address ($role)");
push(@lines, $address);
}
$saw{$address} = 1;
}
}
return @lines;
}
my (@parms) = @_;
if ($output_multiline) {
foreach my $line (@parms) {
print("${line}\n");
}
} else {
print(join($output_separator, @parms));
print("\n");
}
}

Joe Perches
committed
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
my $rfc822re;
sub make_rfc822re {
# Basic lexical tokens are specials, domain_literal, quoted_string, atom, and
# comment. We must allow for rfc822_lwsp (or comments) after each of these.
# This regexp will only work on addresses which have had comments stripped
# and replaced with rfc822_lwsp.
my $specials = '()<>@,;:\\\\".\\[\\]';
my $controls = '\\000-\\037\\177';
my $dtext = "[^\\[\\]\\r\\\\]";
my $domain_literal = "\\[(?:$dtext|\\\\.)*\\]$rfc822_lwsp*";
my $quoted_string = "\"(?:[^\\\"\\r\\\\]|\\\\.|$rfc822_lwsp)*\"$rfc822_lwsp*";
# Use zero-width assertion to spot the limit of an atom. A simple
# $rfc822_lwsp* causes the regexp engine to hang occasionally.
my $atom = "[^$specials $controls]+(?:$rfc822_lwsp+|\\Z|(?=[\\[\"$specials]))";
my $word = "(?:$atom|$quoted_string)";
my $localpart = "$word(?:\\.$rfc822_lwsp*$word)*";
my $sub_domain = "(?:$atom|$domain_literal)";
my $domain = "$sub_domain(?:\\.$rfc822_lwsp*$sub_domain)*";
my $addr_spec = "$localpart\@$rfc822_lwsp*$domain";
my $phrase = "$word*";
my $route = "(?:\@$domain(?:,\@$rfc822_lwsp*$domain)*:$rfc822_lwsp*)";
my $route_addr = "\\<$rfc822_lwsp*$route?$addr_spec\\>$rfc822_lwsp*";
my $mailbox = "(?:$addr_spec|$phrase$route_addr)";
my $group = "$phrase:$rfc822_lwsp*(?:$mailbox(?:,\\s*$mailbox)*)?;\\s*";
my $address = "(?:$mailbox|$group)";
return "$rfc822_lwsp*$address";
}
sub rfc822_strip_comments {
my $s = shift;
# Recursively remove comments, and replace with a single space. The simpler
# regexps in the Email Addressing FAQ are imperfect - they will miss escaped
# chars in atoms, for example.
while ($s =~ s/^((?:[^"\\]|\\.)*
(?:"(?:[^"\\]|\\.)*"(?:[^"\\]|\\.)*)*)
\((?:[^()\\]|\\.)*\)/$1 /osx) {}
return $s;
}
# valid: returns true if the parameter is an RFC822 valid address
#

Joe Perches
committed
my $s = rfc822_strip_comments(shift);
if (!$rfc822re) {
$rfc822re = make_rfc822re();
}
return $s =~ m/^$rfc822re$/so && $s =~ m/^$rfc822_char*$/;
}
# validlist: In scalar context, returns true if the parameter is an RFC822
# valid list of addresses.
#
# In list context, returns an empty list on failure (an invalid
# address was found); otherwise a list whose first element is the
# number of addresses found and whose remaining elements are the
# addresses. This is needed to disambiguate failure (invalid)
# from success with no addresses found, because an empty string is
# a valid list.

Joe Perches
committed
my $s = rfc822_strip_comments(shift);
if (!$rfc822re) {
$rfc822re = make_rfc822re();
}
# * null list items are valid according to the RFC
# * the '1' business is to aid in distinguishing failure from no results
my @r;
if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so &&
$s =~ m/^$rfc822_char*$/) {
while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) {
push(@r, $1);

Joe Perches
committed
}
return wantarray ? (scalar(@r), @r) : 1;
}
return wantarray ? () : 0;