X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=git-send-email.perl;h=d8c4b1f8923ca019e9aab9a1c538cb96d7960ca0;hb=49e3343c9fe0e134e0a8c1ec0ddeb64ae18ee9fd;hp=d2af98ac0c9645494ef484ee91cb853840cb630f;hpb=a5370b16c34993c1d0f65171d5704244901e005b;p=git.git diff --git a/git-send-email.perl b/git-send-email.perl index d2af98ac..d8c4b1f8 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -22,12 +22,12 @@ use Term::ReadLine; use Getopt::Long; use Data::Dumper; use Net::SMTP; -use Email::Valid; # most mail servers generate the Date: header, but not all... $ENV{LC_ALL} = 'C'; use POSIX qw/strftime/; +my $have_email_valid = eval { require Email::Valid; 1 }; my $smtp; sub unique_email_list(@); @@ -89,6 +89,41 @@ sub gitvar_ident { my ($author) = gitvar_ident('GIT_AUTHOR_IDENT'); my ($committer) = gitvar_ident('GIT_COMMITTER_IDENT'); +my %aliases; +chomp(my @alias_files = `git-repo-config --get-all sendemail.aliasesfile`); +chomp(my $aliasfiletype = `git-repo-config sendemail.aliasfiletype`); +my %parse_alias = ( + # multiline formats can be supported in the future + mutt => sub { my $fh = shift; while (<$fh>) { + if (/^alias\s+(\S+)\s+(.*)$/) { + my ($alias, $addr) = ($1, $2); + $addr =~ s/#.*$//; # mutt allows # comments + # commas delimit multiple addresses + $aliases{$alias} = [ split(/\s*,\s*/, $addr) ]; + }}}, + mailrc => sub { my $fh = shift; while (<$fh>) { + if (/^alias\s+(\S+)\s+(.*)$/) { + # spaces delimit multiple addresses + $aliases{$1} = [ split(/\s+/, $2) ]; + }}}, + pine => sub { my $fh = shift; while (<$fh>) { + if (/^(\S+)\s+(.*)$/) { + $aliases{$1} = [ split(/\s*,\s*/, $2) ]; + }}}, + gnus => sub { my $fh = shift; while (<$fh>) { + if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) { + $aliases{$1} = [ $2 ]; + }}} +); + +if (@alias_files && defined $parse_alias{$aliasfiletype}) { + foreach my $file (@alias_files) { + open my $fh, '<', $file or die "opening $file: $!\n"; + $parse_alias{$aliasfiletype}->($fh); + close $fh; + } +} + my $prompting = 0; if (!defined $from) { $from = $author || $committer; @@ -112,6 +147,19 @@ if (!@to) { $prompting++; } +sub expand_aliases { + my @cur = @_; + my @last; + do { + @last = @cur; + @cur = map { $aliases{$_} ? @{$aliases{$_}} : $_ } @last; + } while (join(',',@cur) ne join(',',@last)); + return @cur; +} + +@to = expand_aliases(@to); +@initial_cc = expand_aliases(@initial_cc); + if (!defined $initial_subject && $compose) { do { $_ = $term->readline("What subject should the emails start with? ", @@ -250,6 +298,16 @@ EOT # Variables we set as part of the loop over files our ($message_id, $cc, %mail, $subject, $reply_to, $message); +sub extract_valid_address { + my $address = shift; + if ($have_email_valid) { + return 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 + return ($address =~ /([^\"<>\s]+@[^<>\s]+)/); + } +} # Usually don't need to change anything below here. @@ -259,7 +317,7 @@ our ($message_id, $cc, %mail, $subject, $reply_to, $message); # 1 second since the last time we were called. # We'll setup a template for the message id, using the "from" address: -my $message_id_from = Email::Valid->address($from); +my $message_id_from = extract_valid_address($from); my $message_id_template = "<%s-git-send-email-$message_id_from>"; sub make_message_id @@ -281,6 +339,13 @@ sub send_message my $to = join (",\n\t", @recipients); @recipients = unique_email_list(@recipients,@cc); my $date = strftime('%a, %d %b %Y %H:%M:%S %z', localtime($time++)); + my $gitversion = '@@GIT_VERSION@@'; + if ($gitversion =~ m/..GIT_VERSION../) { + $gitversion = `git --version`; + chomp $gitversion; + # keep only what's after the last space + $gitversion =~ s/^.* //; + } my $header = "From: $from To: $to @@ -289,7 +354,7 @@ Subject: $subject Reply-To: $from Date: $date Message-Id: $message_id -X-Mailer: git-send-email @@GIT_VERSION@@ +X-Mailer: git-send-email $gitversion "; $header .= "In-Reply-To: $reply_to\n" if $reply_to; @@ -413,7 +478,7 @@ sub unique_email_list(@) { my @emails; foreach my $entry (@_) { - my $clean = Email::Valid->address($entry); + my $clean = extract_valid_address($entry); next if $seen{$clean}++; push @emails, $entry; }