Merge branch 'jc/maint-test-portability' into maint
[gitweb.git] / git-send-email.perl
index 5a7c29db9324df48c9da68b08a946e5a357f0a78..94c7f76a156f1eaa4c622db267710f2982cf7826 100755 (executable)
@@ -753,16 +753,11 @@ sub file_declares_8bit_cte {
        }
 }
 
-my $prompting = 0;
 if (!defined $sender) {
        $sender = $repoauthor || $repocommitter || '';
-       $sender = ask("Who should the emails appear to be from? [$sender] ",
-                     default => $sender,
-                     valid_re => qr/\@.*\./, confirm_only => 1);
-       print "Emails will be sent from: ", $sender, "\n";
-       $prompting++;
 }
 
+my $prompting = 0;
 if (!@initial_to && !defined $to_cmd) {
        my $to = ask("Who should the emails be sent to (if any)? ",
                     default => "",
@@ -786,9 +781,11 @@ sub expand_one_alias {
 }
 
 @initial_to = expand_aliases(@initial_to);
-@initial_to = (map { sanitize_address($_) } @initial_to);
+@initial_to = validate_address_list(sanitize_address_list(@initial_to));
 @initial_cc = expand_aliases(@initial_cc);
+@initial_cc = validate_address_list(sanitize_address_list(@initial_cc));
 @bcclist = expand_aliases(@bcclist);
+@bcclist = validate_address_list(sanitize_address_list(@bcclist));
 
 if ($thread && !defined $initial_reply_to && $prompting) {
        $initial_reply_to = ask(
@@ -831,12 +828,45 @@ sub extract_valid_address {
        $address =~ s/^\s*<(.*)>\s*$/$1/;
        if ($have_email_valid) {
                return scalar Email::Valid->address($address);
-       } else {
-               # less robust/correct than the monster regexp in Email::Valid,
-               # but still does a 99% job, and one less dependency
-               $address =~ /($local_part_regexp\@$domain_regexp)/;
-               return $1;
        }
+
+       # less robust/correct than the monster regexp in Email::Valid,
+       # but still does a 99% job, and one less dependency
+       return $1 if $address =~ /($local_part_regexp\@$domain_regexp)/;
+       return undef;
+}
+
+sub extract_valid_address_or_die {
+       my $address = shift;
+       $address = extract_valid_address($address);
+       die "error: unable to extract a valid address from: $address\n"
+               if !$address;
+       return $address;
+}
+
+sub validate_address {
+       my $address = shift;
+       while (!extract_valid_address($address)) {
+               print STDERR "error: unable to extract a valid address from: $address\n";
+               $_ = ask("What to do with this address? ([q]uit|[d]rop|[e]dit): ",
+                       valid_re => qr/^(?:quit|q|drop|d|edit|e)/i,
+                       default => 'q');
+               if (/^d/i) {
+                       return undef;
+               } elsif (/^q/i) {
+                       cleanup_compose_files();
+                       exit(0);
+               }
+               $address = ask("Who should the email be sent to (if any)? ",
+                       default => "",
+                       valid_re => qr/\@.*\./, confirm_only => 1);
+       }
+       return $address;
+}
+
+sub validate_address_list {
+       return (grep { defined $_ }
+               map { validate_address($_) } @_);
 }
 
 # Usually don't need to change anything below here.
@@ -924,6 +954,10 @@ sub quote_subject {
 # use the simplest quoting being able to handle the recipient
 sub sanitize_address {
        my ($recipient) = @_;
+
+       # remove garbage after email address
+       $recipient =~ s/(.*>).*$/$1/;
+
        my ($recipient_name, $recipient_addr) = ($recipient =~ /^(.*?)\s*(<.*)/);
 
        if (not $recipient_name) {
@@ -951,6 +985,10 @@ sub sanitize_address {
 
 }
 
+sub sanitize_address_list {
+       return (map { sanitize_address($_) } @_);
+}
+
 # Returns the local Fully Qualified Domain Name (FQDN) if available.
 #
 # Tightly configured MTAa require that a caller sends a real DNS
@@ -1013,14 +1051,13 @@ sub maildomain {
 
 sub send_message {
        my @recipients = unique_email_list(@to);
-       @cc = (grep { my $cc = extract_valid_address($_);
+       @cc = (grep { my $cc = extract_valid_address_or_die($_);
                      not grep { $cc eq $_ || $_ =~ /<\Q${cc}\E>$/ } @recipients
                    }
-              map { sanitize_address($_) }
               @cc);
        my $to = join (",\n\t", @recipients);
        @recipients = unique_email_list(@recipients,@cc,@bcclist);
-       @recipients = (map { extract_valid_address($_) } @recipients);
+       @recipients = (map { extract_valid_address_or_die($_) } @recipients);
        my $date = format_2822_time($time++);
        my $gitversion = '@@GIT_VERSION@@';
        if ($gitversion =~ m/..GIT_VERSION../) {
@@ -1263,7 +1300,7 @@ sub send_message {
                                foreach my $addr (parse_address_line($1)) {
                                        printf("(mbox) Adding to: %s from line '%s'\n",
                                                $addr, $_) unless $quiet;
-                                       push @to, sanitize_address($addr);
+                                       push @to, $addr;
                                }
                        }
                        elsif (/^Cc:\s+(.*)$/) {
@@ -1372,6 +1409,9 @@ sub send_message {
                ($confirm =~ /^(?:auto|compose)$/ && $compose && $message_num == 1));
        $needs_confirm = "inform" if ($needs_confirm && $confirm_unconfigured && @cc);
 
+       @to = validate_address_list(sanitize_address_list(@to));
+       @cc = validate_address_list(sanitize_address_list(@cc));
+
        @to = (@initial_to, @to);
        @cc = (@initial_cc, @cc);
 
@@ -1427,14 +1467,10 @@ sub unique_email_list {
        my @emails;
 
        foreach my $entry (@_) {
-               if (my $clean = extract_valid_address($entry)) {
-                       $seen{$clean} ||= 0;
-                       next if $seen{$clean}++;
-                       push @emails, $entry;
-               } else {
-                       print STDERR "W: unable to extract a valid address",
-                                       " from: $entry\n";
-               }
+               my $clean = extract_valid_address_or_die($entry);
+               $seen{$clean} ||= 0;
+               next if $seen{$clean}++;
+               push @emails, $entry;
        }
        return @emails;
 }