From: Junio C Hamano Date: Sun, 27 Jun 2010 19:07:45 +0000 (-0700) Subject: Merge branch 'tr/send-email-8bit' X-Git-Tag: v1.7.2-rc0~3 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/a278aa61a474eced7b676f3378dcd0f4ec5db4fc?hp=-c Merge branch 'tr/send-email-8bit' * tr/send-email-8bit: send-email: ask about and declare 8bit mails --- a278aa61a474eced7b676f3378dcd0f4ec5db4fc diff --combined Documentation/git-send-email.txt index 12622fc49a,e70d9bfcdb..c283084272 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@@ -101,6 -101,15 +101,15 @@@ See the CONFIGURATION section for 'send + The --to option must be repeated for each user you want on the to list. + --8bit-encoding=:: + When encountering a non-ASCII message or subject that does not + declare its encoding, add headers/quoting to indicate it is + encoded in . Default is the value of the + 'sendemail.assume8bitEncoding'; if that is unspecified, this + will be prompted for if any non-ASCII files are encountered. + + + Note that no attempts whatsoever are made to validate the encoding. + Sending ~~~~~~~ @@@ -119,13 -128,6 +128,13 @@@ value reverts to plain SMTP. Default is the value of 'sendemail.smtpencryption'. +--smtp-domain=:: + Specifies the Fully Qualified Domain Name (FQDN) used in the + HELO/EHLO command to the SMTP server. Some servers require the + FQDN to match your IP address. If not set, git send-email attempts + to determine your FQDN automatically. Default is the value of + 'sendemail.smtpdomain'. + --smtp-pass[=]:: Password for SMTP-AUTH. The argument is optional: If no argument is specified, then the empty string is used as diff --combined git-send-email.perl index 111c981229,0db39b0de4..6dab3bf6a7 --- a/git-send-email.perl +++ b/git-send-email.perl @@@ -54,6 -54,7 +54,7 @@@ git send-email [options] * Email "In-Reply-To:" --annotate * Review each patch that will be sent in an editor. --compose * Open an editor for introduction. + --8bit-encoding * Encoding to assume 8bit mails if undeclared Sending: --envelope-sender * Email envelope sender. @@@ -132,6 -133,8 +133,6 @@@ my $have_email_valid = eval { require E my $have_mail_address = eval { require Mail::Address; 1 }; my $smtp; my $auth; -my $mail_domain_default = "localhost.localdomain"; -my $mail_domain; sub unique_email_list(@); sub cleanup_compose_files(); @@@ -188,9 -191,10 +189,10 @@@ sub do_edit # Variables with corresponding config settings my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd); my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption); -my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts); +my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts, $smtp_domain); my ($validate, $confirm); my (@suppress_cc); + my ($auto_8bit_encoding); my ($debug_net_smtp) = 0; # Net::SMTP, see send_message() @@@ -210,7 -214,6 +212,7 @@@ my %config_settings = "smtpserverport" => \$smtp_server_port, "smtpuser" => \$smtp_authuser, "smtppass" => \$smtp_authpass, + "smtpdomain" => \$smtp_domain, "to" => \@to, "cc" => \@initial_cc, "cccmd" => \$cc_cmd, @@@ -222,6 -225,7 +224,7 @@@ "multiedit" => \$multiedit, "confirm" => \$confirm, "from" => \$sender, + "assume8bitencoding" => \$auto_8bit_encoding, ); # Help users prepare for 1.7.0 @@@ -282,7 -286,7 +285,7 @@@ my $rc = GetOptions("sender|from=s" => "smtp-ssl" => sub { $smtp_encryption = 'ssl' }, "smtp-encryption=s" => \$smtp_encryption, "smtp-debug:i" => \$debug_net_smtp, - "smtp-domain:s" => \$mail_domain, + "smtp-domain:s" => \$smtp_domain, "identity=s" => \$identity, "annotate" => \$annotate, "compose" => \$compose, @@@ -297,6 -301,7 +300,7 @@@ "thread!" => \$thread, "validate!" => \$validate, "format-patch!" => \$format_patch, + "8bit-encoding=s" => \$auto_8bit_encoding, ); unless ($rc) { @@@ -669,6 -674,35 +673,35 @@@ sub ask return undef; } + my %broken_encoding; + + sub file_declares_8bit_cte($) { + my $fn = shift; + open (my $fh, '<', $fn); + while (my $line = <$fh>) { + last if ($line =~ /^$/); + return 1 if ($line =~ /^Content-Transfer-Encoding: .*8bit.*$/); + } + close $fh; + return 0; + } + + foreach my $f (@files) { + next unless (body_or_subject_has_nonascii($f) + && !file_declares_8bit_cte($f)); + $broken_encoding{$f} = 1; + } + + if (!defined $auto_8bit_encoding && scalar %broken_encoding) { + print "The following files are 8bit, but do not declare " . + "a Content-Transfer-Encoding.\n"; + foreach my $f (sort keys %broken_encoding) { + print " $f\n"; + } + $auto_8bit_encoding = ask("Which 8bit encoding should I declare [UTF-8]? ", + default => "UTF-8"); + } + my $prompting = 0; if (!defined $sender) { $sender = $repoauthor || $repocommitter || ''; @@@ -760,7 -794,8 +793,7 @@@ sub extract_valid_address # We'll setup a template for the message id, using the "from" address: my ($message_id_stamp, $message_id_serial); -sub make_message_id -{ +sub make_message_id { my $uniq; if (!defined $message_id_stamp) { $message_id_stamp = sprintf("%s-%s", time, $$); @@@ -815,7 -850,8 +848,7 @@@ sub is_rfc2047_quoted } # use the simplest quoting being able to handle the recipient -sub sanitize_address -{ +sub sanitize_address { my ($recipient) = @_; my ($recipient_name, $recipient_addr) = ($recipient =~ /^(.*?)\s*(<.*)/); @@@ -860,23 -896,21 +893,23 @@@ # This maildomain*() code is based on ideas in Perl library Test::Reporter # /usr/share/perl5/Test/Reporter/Mail/Util.pm ==> sub _maildomain () -sub maildomain_net -{ +sub valid_fqdn { + my $domain = shift; + return !($^O eq 'darwin' && $domain =~ /\.local$/) && $domain =~ /\./; +} + +sub maildomain_net { my $maildomain; if (eval { require Net::Domain; 1 }) { my $domain = Net::Domain::domainname(); - $maildomain = $domain - unless $^O eq 'darwin' && $domain =~ /\.local$/; + $maildomain = $domain if valid_fqdn($domain); } return $maildomain; } -sub maildomain_mta -{ +sub maildomain_mta { my $maildomain; if (eval { require Net::SMTP; 1 }) { @@@ -886,7 -920,8 +919,7 @@@ my $domain = $smtp->domain; $smtp->quit; - $maildomain = $domain - unless $^O eq 'darwin' && $domain =~ /\.local$/; + $maildomain = $domain if valid_fqdn($domain); last if $maildomain; } @@@ -896,15 -931,17 +929,15 @@@ return $maildomain; } -sub maildomain -{ - return maildomain_net() || maildomain_mta() || $mail_domain_default; +sub maildomain { + return maildomain_net() || maildomain_mta() || 'localhost.localdomain'; } # Returns 1 if the message was sent, and 0 otherwise. # In actuality, the whole program dies when there # is an error sending a message. -sub send_message -{ +sub send_message { my @recipients = unique_email_list(@to); @cc = (grep { my $cc = extract_valid_address($_); not grep { $cc eq $_ } @recipients @@@ -1001,18 -1038,18 +1034,18 @@@ X-Mailer: git-send-email $gitversio if ($smtp_encryption eq 'ssl') { $smtp_server_port ||= 465; # ssmtp require Net::SMTP::SSL; - $mail_domain ||= maildomain(); + $smtp_domain ||= maildomain(); $smtp ||= Net::SMTP::SSL->new($smtp_server, - Hello => $mail_domain, + Hello => $smtp_domain, Port => $smtp_server_port); } else { require Net::SMTP; - $mail_domain ||= maildomain(); + $smtp_domain ||= maildomain(); $smtp ||= Net::SMTP->new((defined $smtp_server_port) ? "$smtp_server:$smtp_server_port" : $smtp_server, - Hello => $mail_domain, + Hello => $smtp_domain, Debug => $debug_net_smtp); if ($smtp_encryption eq 'tls' && $smtp) { require Net::SMTP::SSL; @@@ -1035,7 -1072,7 +1068,7 @@@ die "Unable to initialize SMTP properly. Check config and use --smtp-debug. ", "VALUES: server=$smtp_server ", "encryption=$smtp_encryption ", - "maildomain=$mail_domain", + "hello=$smtp_domain", defined $smtp_server_port ? "port=$smtp_server_port" : ""; } @@@ -1221,6 -1258,18 +1254,18 @@@ foreach my $t (@files) or die "(cc-cmd) failed to close pipe to '$cc_cmd'"; } + if ($broken_encoding{$t} && !$has_content_type) { + $has_content_type = 1; + push @xh, "MIME-Version: 1.0", + "Content-Type: text/plain; charset=$auto_8bit_encoding", + "Content-Transfer-Encoding: 8bit"; + $body_encoding = $auto_8bit_encoding; + } + + if ($broken_encoding{$t} && !is_rfc2047_quoted($subject)) { + $subject = quote_rfc2047($subject, $auto_8bit_encoding); + } + if (defined $author and $author ne $sender) { $message = "From: $author\n\n$message"; if (defined $author_encoding) { @@@ -1233,6 -1282,7 +1278,7 @@@ } } else { + $has_content_type = 1; push @xh, 'MIME-Version: 1.0', "Content-Type: text/plain; charset=$author_encoding", @@@ -1310,3 -1360,17 +1356,17 @@@ sub file_has_nonascii } return 0; } + + sub body_or_subject_has_nonascii { + my $fn = shift; + open(my $fh, '<', $fn) + or die "unable to open $fn: $!\n"; + while (my $line = <$fh>) { + last if $line =~ /^$/; + return 1 if $line =~ /^Subject.*[^[:ascii:]]/; + } + while (my $line = <$fh>) { + return 1 if $line =~ /[^[:ascii:]]/; + } + return 0; + }