3 # Copyright 2002,2005 Greg Kroah-Hartman <greg@kroah.com>
4 # Copyright 2005 Ryan Anderson <ryan@michonline.com>
8 # Ported to support git "mbox" format files by Ryan Anderson <ryan@michonline.com>
10 # Sends a collection of emails to the given email addresses, disturbingly fast.
12 # Supports two formats:
13 # 1. mbox format files (ignoring most headers and MIME formatting - this is designed for sending patches)
14 # 2. The original format support by Greg's script:
15 # first line of the message is who to CC,
16 # and second line is the subject of the message.
22 use POSIX qw
/strftime/;
27 use File
::Temp qw
/ tempdir tempfile /;
28 use File
::Spec
::Functions
qw(catdir catfile);
30 use Cwd
qw(abs_path cwd);
34 Getopt
::Long
::Configure qw
/ pass_through /;
38 my ($class, $reason) = @_;
39 return bless \
$reason, shift;
43 die "Cannot use readline on FakeTerm: $$self";
50 git send-email [options] <file | directory | rev-list options >
51 git send-email --dump-aliases
54 --from <str> * Email From:
55 --[no-]to <str> * Email To:
56 --[no-]cc <str> * Email Cc:
57 --[no-]bcc <str> * Email Bcc:
58 --subject <str> * Email "Subject:"
59 --in-reply-to <str> * Email "In-Reply-To:"
60 --[no-]xmailer * Add "X-Mailer:" header (default).
61 --[no-]annotate * Review each patch that will be sent in an editor.
62 --compose * Open an editor for introduction.
63 --compose-encoding <str> * Encoding to assume for introduction.
64 --8bit-encoding <str> * Encoding to assume 8bit mails if undeclared
65 --transfer-encoding <str> * Transfer encoding to use (quoted-printable, 8bit, base64)
68 --envelope-sender <str> * Email envelope sender.
69 --smtp-server <str:int> * Outgoing SMTP server to use. The port
70 is optional. Default 'localhost'.
71 --smtp-server-option <str> * Outgoing SMTP server option to use.
72 --smtp-server-port <int> * Outgoing SMTP server port.
73 --smtp-user <str> * Username for SMTP-AUTH.
74 --smtp-pass <str> * Password for SMTP-AUTH; not necessary.
75 --smtp-encryption <str> * tls or ssl; anything else disables.
76 --smtp-ssl * Deprecated. Use '--smtp-encryption ssl'.
77 --smtp-ssl-cert-path <str> * Path to ca-certificates (either directory or file).
78 Pass an empty string to disable certificate
80 --smtp-domain <str> * The domain name sent to HELO/EHLO handshake
81 --smtp-auth <str> * Space-separated list of allowed AUTH mechanisms.
82 This setting forces to use one of the listed mechanisms.
83 --smtp-debug <0|1> * Disable, enable Net::SMTP debug.
86 --identity <str> * Use the sendemail.<id> options.
87 --to-cmd <str> * Email To: via `<str> \$patch_path`
88 --cc-cmd <str> * Email Cc: via `<str> \$patch_path`
89 --suppress-cc <str> * author, self, sob, cc, cccmd, body, bodycc, all.
90 --[no-]cc-cover * Email Cc: addresses in the cover letter.
91 --[no-]to-cover * Email To: addresses in the cover letter.
92 --[no-]signed-off-by-cc * Send to Signed-off-by: addresses. Default on.
93 --[no-]suppress-from * Send to self. Default off.
94 --[no-]chain-reply-to * Chain In-Reply-To: fields. Default off.
95 --[no-]thread * Use In-Reply-To: field. Default on.
98 --confirm <str> * Confirm recipients before sending;
99 auto, cc, compose, always, or never.
100 --quiet * Output one line of info per email.
101 --dry-run * Don't actually send the emails.
102 --[no-]validate * Perform patch sanity checks. Default on.
103 --[no-]format-patch * understand any non optional arguments as
104 `git format-patch` ones.
105 --force * Send even if safety checks would prevent it.
108 --dump-aliases * Dump configured aliases and exit.
114 # most mail servers generate the Date: header, but not all...
115 sub format_2822_time
{
117 my @localtm = localtime($time);
118 my @gmttm = gmtime($time);
119 my $localmin = $localtm[1] + $localtm[2] * 60;
120 my $gmtmin = $gmttm[1] + $gmttm[2] * 60;
121 if ($localtm[0] != $gmttm[0]) {
122 die __
("local zone differs from GMT by a non-minute interval\n");
124 if ((($gmttm[6] + 1) % 7) == $localtm[6]) {
126 } elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {
128 } elsif ($gmttm[6] != $localtm[6]) {
129 die __
("local time offset greater than or equal to 24 hours\n");
131 my $offset = $localmin - $gmtmin;
132 my $offhour = $offset / 60;
133 my $offmin = abs($offset % 60);
134 if (abs($offhour) >= 24) {
135 die __
("local time offset greater than or equal to 24 hours\n");
138 return sprintf("%s, %2d %s %d %02d:%02d:%02d %s%02d%02d",
139 qw(Sun Mon Tue Wed Thu Fri Sat)[$localtm[6]],
141 qw(Jan Feb Mar Apr May Jun
142 Jul Aug Sep Oct Nov Dec)[$localtm[4]],
147 ($offset >= 0) ?
'+' : '-',
153 my $have_email_valid = eval { require Email
::Valid
; 1 };
154 my $have_mail_address = eval { require Mail
::Address
; 1 };
158 # Regexes for RFC 2047 productions.
159 my $re_token = qr/[^][()<>@,;:\\"\/?
.= \000-\037\177-\377]+/;
160 my $re_encoded_text = qr/[^? \000-\037\177-\377]+/;
161 my $re_encoded_word = qr/=\?($re_token)\?($re_token)\?($re_encoded_text)\?=/;
163 # Variables we fill in automatically, or via prompting:
164 my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
165 $initial_reply_to,$initial_subject,@files,
166 $author,$sender,$smtp_authpass,$annotate,$use_xmailer,$compose,$time);
171 #$initial_reply_to = ''; #<20050203173208.GA23964@foobar.com>';
173 my $repo = eval { Git
->repository() };
174 my @repo = $repo ?
($repo) : ();
176 $ENV{"GIT_SEND_EMAIL_NOTTY"}
177 ? new Term
::ReadLine
'git-send-email', \
*STDIN
, \
*STDOUT
178 : new Term
::ReadLine
'git-send-email';
181 $term = new FakeTerm
"$@: going non-interactive";
184 # Behavior modification variables
185 my ($quiet, $dry_run) = (0, 0);
187 my $compose_filename;
189 my $dump_aliases = 0;
191 # Handle interactive edition of files.
196 if (!defined($editor)) {
197 $editor = Git
::command_oneline
('var', 'GIT_EDITOR');
199 if (defined($multiedit) && !$multiedit) {
201 system('sh', '-c', $editor.' "$@"', $editor, $_);
202 if (($?
& 127) || ($?
>> 8)) {
203 die(__
("the editor exited uncleanly, aborting everything"));
207 system('sh', '-c', $editor.' "$@"', $editor, @_);
208 if (($?
& 127) || ($?
>> 8)) {
209 die(__
("the editor exited uncleanly, aborting everything"));
214 # Variables with corresponding config settings
215 my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc);
216 my ($cover_cc, $cover_to);
217 my ($to_cmd, $cc_cmd);
218 my ($smtp_server, $smtp_server_port, @smtp_server_options);
219 my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
220 my ($identity, $aliasfiletype, @alias_files, $smtp_domain, $smtp_auth);
221 my ($validate, $confirm);
223 my ($auto_8bit_encoding);
224 my ($compose_encoding);
225 my ($target_xfer_encoding);
227 my ($debug_net_smtp) = 0; # Net::SMTP, see send_message()
229 my %config_bool_settings = (
230 "thread" => [\
$thread, 1],
231 "chainreplyto" => [\
$chain_reply_to, 0],
232 "suppressfrom" => [\
$suppress_from, undef],
233 "signedoffbycc" => [\
$signed_off_by_cc, undef],
234 "cccover" => [\
$cover_cc, undef],
235 "tocover" => [\
$cover_to, undef],
236 "signedoffcc" => [\
$signed_off_by_cc, undef], # Deprecated
237 "validate" => [\
$validate, 1],
238 "multiedit" => [\
$multiedit, undef],
239 "annotate" => [\
$annotate, undef],
240 "xmailer" => [\
$use_xmailer, 1]
243 my %config_settings = (
244 "smtpserver" => \
$smtp_server,
245 "smtpserverport" => \
$smtp_server_port,
246 "smtpserveroption" => \
@smtp_server_options,
247 "smtpuser" => \
$smtp_authuser,
248 "smtppass" => \
$smtp_authpass,
249 "smtpdomain" => \
$smtp_domain,
250 "smtpauth" => \
$smtp_auth,
251 "to" => \
@initial_to,
253 "cc" => \
@initial_cc,
255 "aliasfiletype" => \
$aliasfiletype,
257 "suppresscc" => \
@suppress_cc,
258 "envelopesender" => \
$envelope_sender,
259 "confirm" => \
$confirm,
261 "assume8bitencoding" => \
$auto_8bit_encoding,
262 "composeencoding" => \
$compose_encoding,
263 "transferencoding" => \
$target_xfer_encoding,
266 my %config_path_settings = (
267 "aliasesfile" => \
@alias_files,
268 "smtpsslcertpath" => \
$smtp_ssl_cert_path,
271 # Handle Uncouth Termination
275 print color
("reset"), "\n";
277 # SMTP password masked
280 # tmp files from --compose
281 if (defined $compose_filename) {
282 if (-e
$compose_filename) {
283 printf __
("'%s' contains an intermediate version ".
284 "of the email you were composing.\n"),
287 if (-e
($compose_filename . ".final")) {
288 printf __
("'%s.final' contains the composed email.\n"),
296 $SIG{TERM
} = \
&signal_handler
;
297 $SIG{INT
} = \
&signal_handler
;
299 # Begin by accumulating all the variables (defined above), that we will end up
300 # needing, first, from the command line:
303 my $rc = GetOptions
("h" => \
$help,
304 "dump-aliases" => \
$dump_aliases);
306 die __
("--dump-aliases incompatible with other options\n")
307 if !$help and $dump_aliases and @ARGV;
309 "sender|from=s" => \
$sender,
310 "in-reply-to=s" => \
$initial_reply_to,
311 "subject=s" => \
$initial_subject,
312 "to=s" => \
@initial_to,
313 "to-cmd=s" => \
$to_cmd,
315 "cc=s" => \
@initial_cc,
317 "bcc=s" => \
@bcclist,
318 "no-bcc" => \
$no_bcc,
319 "chain-reply-to!" => \
$chain_reply_to,
320 "no-chain-reply-to" => sub {$chain_reply_to = 0},
321 "smtp-server=s" => \
$smtp_server,
322 "smtp-server-option=s" => \
@smtp_server_options,
323 "smtp-server-port=s" => \
$smtp_server_port,
324 "smtp-user=s" => \
$smtp_authuser,
325 "smtp-pass:s" => \
$smtp_authpass,
326 "smtp-ssl" => sub { $smtp_encryption = 'ssl' },
327 "smtp-encryption=s" => \
$smtp_encryption,
328 "smtp-ssl-cert-path=s" => \
$smtp_ssl_cert_path,
329 "smtp-debug:i" => \
$debug_net_smtp,
330 "smtp-domain:s" => \
$smtp_domain,
331 "smtp-auth=s" => \
$smtp_auth,
332 "identity=s" => \
$identity,
333 "annotate!" => \
$annotate,
334 "no-annotate" => sub {$annotate = 0},
335 "compose" => \
$compose,
337 "cc-cmd=s" => \
$cc_cmd,
338 "suppress-from!" => \
$suppress_from,
339 "no-suppress-from" => sub {$suppress_from = 0},
340 "suppress-cc=s" => \
@suppress_cc,
341 "signed-off-cc|signed-off-by-cc!" => \
$signed_off_by_cc,
342 "no-signed-off-cc|no-signed-off-by-cc" => sub {$signed_off_by_cc = 0},
343 "cc-cover|cc-cover!" => \
$cover_cc,
344 "no-cc-cover" => sub {$cover_cc = 0},
345 "to-cover|to-cover!" => \
$cover_to,
346 "no-to-cover" => sub {$cover_to = 0},
347 "confirm=s" => \
$confirm,
348 "dry-run" => \
$dry_run,
349 "envelope-sender=s" => \
$envelope_sender,
350 "thread!" => \
$thread,
351 "no-thread" => sub {$thread = 0},
352 "validate!" => \
$validate,
353 "no-validate" => sub {$validate = 0},
354 "transfer-encoding=s" => \
$target_xfer_encoding,
355 "format-patch!" => \
$format_patch,
356 "no-format-patch" => sub {$format_patch = 0},
357 "8bit-encoding=s" => \
$auto_8bit_encoding,
358 "compose-encoding=s" => \
$compose_encoding,
360 "xmailer!" => \
$use_xmailer,
361 "no-xmailer" => sub {$use_xmailer = 0},
369 die __
("Cannot run git format-patch from outside a repository\n")
370 if $format_patch and not $repo;
372 # Now, let's fill any that aren't set in with defaults:
377 foreach my $setting (keys %config_bool_settings) {
378 my $target = $config_bool_settings{$setting}->[0];
379 $$target = Git
::config_bool
(@repo, "$prefix.$setting") unless (defined $$target);
382 foreach my $setting (keys %config_path_settings) {
383 my $target = $config_path_settings{$setting};
384 if (ref($target) eq "ARRAY") {
386 my @values = Git
::config_path
(@repo, "$prefix.$setting");
387 @
$target = @values if (@values && defined $values[0]);
391 $$target = Git
::config_path
(@repo, "$prefix.$setting") unless (defined $$target);
395 foreach my $setting (keys %config_settings) {
396 my $target = $config_settings{$setting};
397 next if $setting eq "to" and defined $no_to;
398 next if $setting eq "cc" and defined $no_cc;
399 next if $setting eq "bcc" and defined $no_bcc;
400 if (ref($target) eq "ARRAY") {
402 my @values = Git
::config
(@repo, "$prefix.$setting");
403 @
$target = @values if (@values && defined $values[0]);
407 $$target = Git
::config
(@repo, "$prefix.$setting") unless (defined $$target);
411 if (!defined $smtp_encryption) {
412 my $enc = Git
::config
(@repo, "$prefix.smtpencryption");
414 $smtp_encryption = $enc;
415 } elsif (Git
::config_bool
(@repo, "$prefix.smtpssl")) {
416 $smtp_encryption = 'ssl';
421 # read configuration from [sendemail "$identity"], fall back on [sendemail]
422 $identity = Git
::config
(@repo, "sendemail.identity") unless (defined $identity);
423 read_config
("sendemail.$identity") if (defined $identity);
424 read_config
("sendemail");
426 # fall back on builtin bool defaults
427 foreach my $setting (values %config_bool_settings) {
428 ${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]}));
431 # 'default' encryption is none -- this only prevents a warning
432 $smtp_encryption = '' unless (defined $smtp_encryption);
434 # Set CC suppressions
437 foreach my $entry (@suppress_cc) {
438 die sprintf(__
("Unknown --suppress-cc field: '%s'\n"), $entry)
439 unless $entry =~ /^(?:all|cccmd|cc|author|self|sob|body|bodycc)$/;
440 $suppress_cc{$entry} = 1;
444 if ($suppress_cc{'all'}) {
445 foreach my $entry (qw
(cccmd cc author self sob body bodycc
)) {
446 $suppress_cc{$entry} = 1;
448 delete $suppress_cc{'all'};
451 # If explicit old-style ones are specified, they trump --suppress-cc.
452 $suppress_cc{'self'} = $suppress_from if defined $suppress_from;
453 $suppress_cc{'sob'} = !$signed_off_by_cc if defined $signed_off_by_cc;
455 if ($suppress_cc{'body'}) {
456 foreach my $entry (qw
(sob bodycc
)) {
457 $suppress_cc{$entry} = 1;
459 delete $suppress_cc{'body'};
462 # Set confirm's default value
463 my $confirm_unconfigured = !defined $confirm;
464 if ($confirm_unconfigured) {
465 $confirm = scalar %suppress_cc ?
'compose' : 'auto';
467 die sprintf(__
("Unknown --confirm setting: '%s'\n"), $confirm)
468 unless $confirm =~ /^(?:auto|cc|compose|always|never)/;
470 # Debugging, print out the suppressions.
472 print "suppressions:\n";
473 foreach my $entry (keys %suppress_cc) {
474 printf " %-5s -> $suppress_cc{$entry}\n", $entry;
478 my ($repoauthor, $repocommitter);
479 ($repoauthor) = Git
::ident_person
(@repo, 'author');
480 ($repocommitter) = Git
::ident_person
(@repo, 'committer');
482 sub parse_address_line
{
483 if ($have_mail_address) {
484 return map { $_->format } Mail
::Address
->parse($_[0]);
486 return Git
::parse_mailboxes
($_[0]);
491 return quotewords
('\s*,\s*', 1, @_);
496 sub parse_sendmail_alias
{
499 printf STDERR __
("warning: sendmail alias with quotes is not supported: %s\n"), $_;
500 } elsif (/:include:/) {
501 printf STDERR __
("warning: `:include:` not supported: %s\n"), $_;
503 printf STDERR __
("warning: `/file` or `|pipe` redirection not supported: %s\n"), $_;
504 } elsif (/^(\S+?)\s*:\s*(.+)$/) {
505 my ($alias, $addr) = ($1, $2);
506 $aliases{$alias} = [ split_addrs
($addr) ];
508 printf STDERR __
("warning: sendmail line is not recognized: %s\n"), $_;
512 sub parse_sendmail_aliases
{
517 next if /^\s*$/ || /^\s*#/;
518 $s .= $_, next if $s =~ s/\\$// || s/^\s+//;
519 parse_sendmail_alias
($s) if $s;
522 $s =~ s/\\$//; # silently tolerate stray '\' on last line
523 parse_sendmail_alias
($s) if $s;
527 # multiline formats can be supported in the future
528 mutt
=> sub { my $fh = shift; while (<$fh>) {
529 if (/^\s*alias\s+(?:-group\s+\S+\s+)*(\S+)\s+(.*)$/) {
530 my ($alias, $addr) = ($1, $2);
531 $addr =~ s/#.*$//; # mutt allows # comments
532 # commas delimit multiple addresses
533 my @addr = split_addrs
($addr);
535 # quotes may be escaped in the file,
536 # unescape them so we do not double-escape them later.
537 s/\\"/"/g foreach @addr;
538 $aliases{$alias} = \
@addr
540 mailrc
=> sub { my $fh = shift; while (<$fh>) {
541 if (/^alias\s+(\S+)\s+(.*?)\s*$/) {
542 # spaces delimit multiple addresses
543 $aliases{$1} = [ quotewords
('\s+', 0, $2) ];
545 pine
=> sub { my $fh = shift; my $f='\t[^\t]*';
546 for (my $x = ''; defined($x); $x = $_) {
548 $x .= $1 while(defined($_ = <$fh>) && /^ +(.*)$/);
549 $x =~ /^(\S+)$f\t\(?([^\t]+?)\)?(:?$f){0,2}$/ or next;
550 $aliases{$1} = [ split_addrs
($2) ];
552 elm
=> sub { my $fh = shift;
554 if (/^(\S+)\s+=\s+[^=]+=\s(\S+)/) {
555 my ($alias, $addr) = ($1, $2);
556 $aliases{$alias} = [ split_addrs
($addr) ];
559 sendmail
=> \
&parse_sendmail_aliases
,
560 gnus
=> sub { my $fh = shift; while (<$fh>) {
561 if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) {
562 $aliases{$1} = [ $2 ];
566 if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {
567 foreach my $file (@alias_files) {
568 open my $fh, '<', $file or die "opening $file: $!\n";
569 $parse_alias{$aliasfiletype}->($fh);
575 print "$_\n" for (sort keys %aliases);
579 # is_format_patch_arg($f) returns 0 if $f names a patch, or 1 if
580 # $f is a revision list specification to be passed to format-patch.
581 sub is_format_patch_arg
{
585 $repo->command('rev-parse', '--verify', '--quiet', $f);
586 if (defined($format_patch)) {
587 return $format_patch;
589 die sprintf(__
<<EOF, $f, $f);
590 File '%s' exists but it could also be the range of commits
591 to produce patches for. Please disambiguate by...
593 * Saying "./%s" if you mean a file; or
594 * Giving --format-patch option if you mean a range.
596 } catch Git
::Error
::Command with
{
597 # Not a valid revision. Treat it as a filename.
602 # Now that all the defaults are set, process the rest of the command line
603 # arguments and collect up the files that need to be processed.
605 while (defined(my $f = shift @ARGV)) {
607 push @rev_list_opts, "--", @ARGV;
609 } elsif (-d
$f and !is_format_patch_arg
($f)) {
611 or die sprintf(__
("Failed to opendir %s: %s"), $f, $!);
613 push @files, grep { -f
$_ } map { catfile
($f, $_) }
616 } elsif ((-f
$f or -p
$f) and !is_format_patch_arg
($f)) {
619 push @rev_list_opts, $f;
623 if (@rev_list_opts) {
624 die __
("Cannot run git format-patch from outside a repository\n")
626 push @files, $repo->command('format-patch', '-o', tempdir
(CLEANUP
=> 1), @rev_list_opts);
629 @files = handle_backup_files
(@files);
632 foreach my $f (@files) {
634 my $error = validate_patch
($f);
635 $error and die sprintf(__
("fatal: %s: %s\nwarning: no patches were sent\n"),
643 print $_,"\n" for (@files);
646 print STDERR __
("\nNo patch files specified!\n\n");
650 sub get_patch_subject
{
652 open (my $fh, '<', $fn);
653 while (my $line = <$fh>) {
654 next unless ($line =~ /^Subject: (.*)$/);
659 die sprintf(__
("No subject line in %s?"), $fn);
663 # Note that this does not need to be secure, but we will make a small
664 # effort to have it be unique
665 $compose_filename = ($repo ?
666 tempfile
(".gitsendemail.msg.XXXXXX", DIR
=> $repo->repo_path()) :
667 tempfile
(".gitsendemail.msg.XXXXXX", DIR
=> "."))[1];
668 open my $c, ">", $compose_filename
669 or die sprintf(__
("Failed to open for writing %s: %s"), $compose_filename, $!);
672 my $tpl_sender = $sender || $repoauthor || $repocommitter || '';
673 my $tpl_subject = $initial_subject || '';
674 my $tpl_reply_to = $initial_reply_to || '';
676 print $c <<EOT1, Git::prefix_lines("GIT: ", __ <<EOT2), <<EOT3;
677 From $tpl_sender # This line is ignored.
679 Lines beginning in "GIT:" will be removed.
680 Consider including an overall diffstat or table of contents
681 for the patch you are writing.
683 Clear the body content if you don't wish to send a summary.
686 Subject: $tpl_subject
687 In-Reply-To: $tpl_reply_to
691 print $c get_patch_subject($f);
696 do_edit($compose_filename, @files);
698 do_edit($compose_filename);
701 open my $c2, ">", $compose_filename . ".final"
702 or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!);
704 open $c, "<", $compose_filename
705 or die sprintf(__("Failed to open %s: %s"), $compose_filename, $!);
707 my $need_8bit_cte = file_has_nonascii($compose_filename);
709 my $summary_empty = 1;
710 if (!defined $compose_encoding) {
711 $compose_encoding = "UTF-8";
716 $summary_empty = 0 unless (/^\n$/);
719 if ($need_8bit_cte) {
720 print $c2 "MIME-Version: 1.0\n",
721 "Content-Type: text/plain; ",
722 "charset=$compose_encoding\n",
723 "Content-Transfer-Encoding: 8bit\n";
725 } elsif (/^MIME-Version:/i) {
727 } elsif (/^Subject:\s*(.+)\s*$/i) {
728 $initial_subject = $1;
729 my $subject = $initial_subject;
731 quote_subject($subject, $compose_encoding) .
733 } elsif (/^In-Reply-To:\s*(.+)\s*$/i) {
734 $initial_reply_to = $1;
736 } elsif (/^From:\s*(.+)\s*$/i) {
739 } elsif (/^(?:To|Cc|Bcc):/i) {
740 print __("To/Cc/Bcc fields are not interpreted yet, they have been ignored\n");
748 if ($summary_empty) {
749 print __("Summary email is empty, skipping it\n");
752 } elsif ($annotate) {
757 my ($prompt, %arg) = @_;
758 my $valid_re = $arg{valid_re};
759 my $default = $arg{default};
760 my $confirm_only = $arg{confirm_only};
763 return defined $default ? $default : undef
764 unless defined $term->IN and defined fileno($term->IN) and
765 defined $term->OUT and defined fileno($term->OUT);
767 $resp = $term->readline($prompt);
768 if (!defined $resp) { # EOF
770 return defined $default ? $default : undef;
772 if ($resp eq '' and defined $default) {
775 if (!defined $valid_re or $resp =~ /$valid_re/) {
779 my $yesno = $term->readline(
780 # TRANSLATORS: please keep [y/N] as is.
781 sprintf(__("Are you sure you want to use <%s> [y/N]? "), $resp));
782 if (defined $yesno && $yesno =~ /y/i) {
792 sub file_declares_8bit_cte {
794 open (my $fh, '<', $fn);
795 while (my $line = <$fh>) {
796 last if ($line =~ /^$/);
797 return 1 if ($line =~ /^Content-Transfer-Encoding: .*8bit.*$/);
803 foreach my $f (@files) {
804 next unless (body_or_subject_has_nonascii($f)
805 && !file_declares_8bit_cte($f));
806 $broken_encoding{$f} = 1;
809 if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
810 print __("The following files are 8bit, but do not declare " .
811 "a Content-Transfer-Encoding.\n");
812 foreach my $f (sort keys %broken_encoding) {
815 $auto_8bit_encoding = ask(__("Which 8bit encoding should I declare [UTF-8]? "),
816 valid_re => qr/.{4}/, confirm_only => 1,
822 if (get_patch_subject($f) =~ /\Q*** SUBJECT HERE ***\E/) {
823 die sprintf(__("Refusing to send because the patch\n\t%s\n"
824 . "has the template subject '*** SUBJECT HERE ***'. "
825 . "Pass --force if you really want to send.\n"), $f);
830 if (defined $sender) {
831 $sender =~ s/^\s+|\s+$//g;
832 ($sender) = expand_aliases($sender);
834 $sender = $repoauthor || $repocommitter || '';
837 # $sender could be an already sanitized address
838 # (e.g. sendemail.from could be manually sanitized by user).
839 # But it's a no-op to run sanitize_address on an already sanitized address.
840 $sender = sanitize_address($sender);
842 my $to_whom = __("To whom should the emails be sent (if anyone)?");
844 if (!@initial_to && !defined $to_cmd) {
845 my $to = ask("$to_whom ",
847 valid_re => qr/\@.*\./, confirm_only => 1);
848 push @initial_to, parse_address_line($to) if defined $to; # sanitized/validated later
853 return map { expand_one_alias($_) } @_;
856 my %EXPANDED_ALIASES;
857 sub expand_one_alias {
859 if ($EXPANDED_ALIASES{$alias}) {
860 die sprintf(__("fatal: alias '%s' expands to itself\n"), $alias);
862 local $EXPANDED_ALIASES{$alias} = 1;
863 return $aliases{$alias} ? expand_aliases(@{$aliases{$alias}}) : $alias;
866 @initial_to = process_address_list(@initial_to);
867 @initial_cc = process_address_list(@initial_cc);
868 @bcclist = process_address_list(@bcclist);
870 if ($thread && !defined $initial_reply_to && $prompting) {
871 $initial_reply_to = ask(
872 __("Message-ID to be used as In-Reply-To for the first email (if any)? "),
874 valid_re => qr/\@.*\./, confirm_only => 1);
876 if (defined $initial_reply_to) {
877 $initial_reply_to =~ s/^\s*<?//;
878 $initial_reply_to =~ s/>?\s*$//;
879 $initial_reply_to = "<$initial_reply_to>" if $initial_reply_to ne '';
882 if (!defined $smtp_server) {
883 foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {
889 $smtp_server ||= 'localhost'; # could be 127.0.0.1, too... *shrug*
892 if ($compose && $compose > 0) {
893 @files = ($compose_filename . ".final", @files);
896 # Variables we set as part of the loop over files
897 our ($message_id, %mail, $subject, $reply_to, $references, $message,
898 $needs_confirm, $message_num, $ask_default);
900 sub extract_valid_address
{
902 my $local_part_regexp = qr/[^<>"\s@]+/;
903 my $domain_regexp = qr/[^.<>"\s@]+(?:\.[^.<>"\s@]+)+/;
905 # check for a local address:
906 return $address if ($address =~ /^($local_part_regexp)$/);
908 $address =~ s/^\s*<(.*)>\s*$/$1/;
909 if ($have_email_valid) {
910 return scalar Email
::Valid
->address($address);
913 # less robust/correct than the monster regexp in Email::Valid,
914 # but still does a 99% job, and one less dependency
915 return $1 if $address =~ /($local_part_regexp\@$domain_regexp)/;
919 sub extract_valid_address_or_die
{
921 $address = extract_valid_address
($address);
922 die sprintf(__
("error: unable to extract a valid address from: %s\n"), $address)
927 sub validate_address
{
929 while (!extract_valid_address
($address)) {
930 printf STDERR __
("error: unable to extract a valid address from: %s\n"), $address;
931 # TRANSLATORS: Make sure to include [q] [d] [e] in your
932 # translation. The program will only accept English input
934 $_ = ask
(__
("What to do with this address? ([q]uit|[d]rop|[e]dit): "),
935 valid_re
=> qr/^(?:quit|q|drop|d|edit|e)/i,
940 cleanup_compose_files
();
943 $address = ask
("$to_whom ",
945 valid_re
=> qr/\@.*\./, confirm_only
=> 1);
950 sub validate_address_list
{
951 return (grep { defined $_ }
952 map { validate_address
($_) } @_);
955 # Usually don't need to change anything below here.
957 # we make a "fake" message id by taking the current number
958 # of seconds since the beginning of Unix time and tacking on
959 # a random number to the end, in case we are called quicker than
960 # 1 second since the last time we were called.
962 # We'll setup a template for the message id, using the "from" address:
964 my ($message_id_stamp, $message_id_serial);
965 sub make_message_id
{
967 if (!defined $message_id_stamp) {
968 $message_id_stamp = strftime
("%Y%m%d%H%M%S.$$", gmtime(time));
969 $message_id_serial = 0;
971 $message_id_serial++;
972 $uniq = "$message_id_stamp-$message_id_serial";
975 for ($sender, $repocommitter, $repoauthor) {
976 $du_part = extract_valid_address
(sanitize_address
($_));
977 last if (defined $du_part and $du_part ne '');
979 if (not defined $du_part or $du_part eq '') {
980 require Sys
::Hostname
;
981 $du_part = 'user@' . Sys
::Hostname
::hostname
();
983 my $message_id_template = "<%s-%s>";
984 $message_id = sprintf($message_id_template, $uniq, $du_part);
985 #print "new message id = $message_id\n"; # Was useful for debugging
990 $time = time - scalar $#files;
992 sub unquote_rfc2047
{
995 my $sep = qr/[ \t]+/;
996 s
{$re_encoded_word(?
:$sep$re_encoded_word)*}{
997 my @words = split $sep, $&;
1003 if ($encoding eq 'q' || $encoding eq 'Q') {
1006 s/=([0-9A-F]{2})/chr(hex($1))/egi;
1008 # other encodings not supported yet
1013 return wantarray ?
($_, $charset) : $_;
1018 my $encoding = shift || 'UTF-8';
1019 s/([^-a-zA-Z0-9!*+\/])/sprintf
("=%02X", ord($1))/eg
;
1020 s/(.*)/=\?$encoding\?q\?$1\?=/;
1024 sub is_rfc2047_quoted
{
1027 $s =~ m/^(?:"[[:ascii:]]*"|$re_encoded_word)$/o;
1030 sub subject_needs_rfc2047_quoting
{
1033 return ($s =~ /[^[:ascii:]]/) || ($s =~ /=\?/);
1037 local $subject = shift;
1038 my $encoding = shift || 'UTF-8';
1040 if (subject_needs_rfc2047_quoting
($subject)) {
1041 return quote_rfc2047
($subject, $encoding);
1046 # use the simplest quoting being able to handle the recipient
1047 sub sanitize_address
{
1048 my ($recipient) = @_;
1050 # remove garbage after email address
1051 $recipient =~ s/(.*>).*$/$1/;
1053 my ($recipient_name, $recipient_addr) = ($recipient =~ /^(.*?)\s*(<.*)/);
1055 if (not $recipient_name) {
1059 # if recipient_name is already quoted, do nothing
1060 if (is_rfc2047_quoted
($recipient_name)) {
1064 # remove non-escaped quotes
1065 $recipient_name =~ s/(^|[^\\])"/$1/g;
1067 # rfc2047 is needed if a non-ascii char is included
1068 if ($recipient_name =~ /[^[:ascii:]]/) {
1069 $recipient_name = quote_rfc2047
($recipient_name);
1072 # double quotes are needed if specials or CTLs are included
1073 elsif ($recipient_name =~ /[][()<>@,;:\\".\000-\037\177]/) {
1074 $recipient_name =~ s/([\\\r])/\\$1/g;
1075 $recipient_name = qq["$recipient_name"];
1078 return "$recipient_name $recipient_addr";
1082 sub sanitize_address_list
{
1083 return (map { sanitize_address
($_) } @_);
1086 sub process_address_list
{
1087 my @addr_list = map { parse_address_line
($_) } @_;
1088 @addr_list = expand_aliases
(@addr_list);
1089 @addr_list = sanitize_address_list
(@addr_list);
1090 @addr_list = validate_address_list
(@addr_list);
1094 # Returns the local Fully Qualified Domain Name (FQDN) if available.
1096 # Tightly configured MTAa require that a caller sends a real DNS
1097 # domain name that corresponds the IP address in the HELO/EHLO
1098 # handshake. This is used to verify the connection and prevent
1099 # spammers from trying to hide their identity. If the DNS and IP don't
1100 # match, the receiveing MTA may deny the connection.
1102 # Here is a deny example of Net::SMTP with the default "localhost.localdomain"
1104 # Net::SMTP=GLOB(0x267ec28)>>> EHLO localhost.localdomain
1105 # Net::SMTP=GLOB(0x267ec28)<<< 550 EHLO argument does not match calling host
1107 # This maildomain*() code is based on ideas in Perl library Test::Reporter
1108 # /usr/share/perl5/Test/Reporter/Mail/Util.pm ==> sub _maildomain ()
1112 return defined $domain && !($^O
eq 'darwin' && $domain =~ /\.local$/) && $domain =~ /\./;
1115 sub maildomain_net
{
1118 if (eval { require Net
::Domain
; 1 }) {
1119 my $domain = Net
::Domain
::domainname
();
1120 $maildomain = $domain if valid_fqdn
($domain);
1126 sub maildomain_mta
{
1129 if (eval { require Net
::SMTP
; 1 }) {
1130 for my $host (qw(mailhost localhost)) {
1131 my $smtp = Net
::SMTP
->new($host);
1132 if (defined $smtp) {
1133 my $domain = $smtp->domain;
1136 $maildomain = $domain if valid_fqdn
($domain);
1138 last if $maildomain;
1147 return maildomain_net
() || maildomain_mta
() || 'localhost.localdomain';
1150 sub smtp_host_string
{
1151 if (defined $smtp_server_port) {
1152 return "$smtp_server:$smtp_server_port";
1154 return $smtp_server;
1158 # Returns 1 if authentication succeeded or was not necessary
1159 # (smtp_user was not specified), and 0 otherwise.
1161 sub smtp_auth_maybe
{
1162 if (!defined $smtp_authuser || $auth) {
1166 # Workaround AUTH PLAIN/LOGIN interaction defect
1167 # with Authen::SASL::Cyrus
1169 require Authen
::SASL
;
1170 Authen
::SASL
->import(qw(Perl));
1173 # Check mechanism naming as defined in:
1174 # https://tools.ietf.org/html/rfc4422#page-8
1175 if ($smtp_auth && $smtp_auth !~ /^(\b[A-Z0-9-_]{1,20}\s*)*$/) {
1176 die "invalid smtp auth: '${smtp_auth}'";
1179 # TODO: Authentication may fail not because credentials were
1180 # invalid but due to other reasons, in which we should not
1181 # reject credentials.
1182 $auth = Git
::credential
({
1183 'protocol' => 'smtp',
1184 'host' => smtp_host_string
(),
1185 'username' => $smtp_authuser,
1186 # if there's no password, "git credential fill" will
1187 # give us one, otherwise it'll just pass this one.
1188 'password' => $smtp_authpass
1193 my $sasl = Authen
::SASL
->new(
1194 mechanism
=> $smtp_auth,
1196 user
=> $cred->{'username'},
1197 pass
=> $cred->{'password'},
1198 authname
=> $cred->{'username'},
1202 return !!$smtp->auth($sasl);
1205 return !!$smtp->auth($cred->{'username'}, $cred->{'password'});
1211 sub ssl_verify_params
{
1213 require IO
::Socket
::SSL
;
1214 IO
::Socket
::SSL
->import(qw
/SSL_VERIFY_PEER SSL_VERIFY_NONE/);
1217 print STDERR
"Not using SSL_VERIFY_PEER due to out-of-date IO::Socket::SSL.\n";
1221 if (!defined $smtp_ssl_cert_path) {
1222 # use the OpenSSL defaults
1223 return (SSL_verify_mode
=> SSL_VERIFY_PEER
());
1226 if ($smtp_ssl_cert_path eq "") {
1227 return (SSL_verify_mode
=> SSL_VERIFY_NONE
());
1228 } elsif (-d
$smtp_ssl_cert_path) {
1229 return (SSL_verify_mode
=> SSL_VERIFY_PEER
(),
1230 SSL_ca_path
=> $smtp_ssl_cert_path);
1231 } elsif (-f
$smtp_ssl_cert_path) {
1232 return (SSL_verify_mode
=> SSL_VERIFY_PEER
(),
1233 SSL_ca_file
=> $smtp_ssl_cert_path);
1235 die sprintf(__
("CA path \"%s\" does not exist"), $smtp_ssl_cert_path);
1239 sub file_name_is_absolute
{
1242 # msys does not grok DOS drive-prefixes
1243 if ($^O
eq 'msys') {
1244 return ($path =~ m
#^/# || $path =~ m#^[a-zA-Z]\:#)
1247 require File
::Spec
::Functions
;
1248 return File
::Spec
::Functions
::file_name_is_absolute
($path);
1251 # Returns 1 if the message was sent, and 0 otherwise.
1252 # In actuality, the whole program dies when there
1253 # is an error sending a message.
1256 my @recipients = unique_email_list
(@to);
1257 @cc = (grep { my $cc = extract_valid_address_or_die
($_);
1258 not grep { $cc eq $_ || $_ =~ /<\Q${cc}\E>$/ } @recipients
1261 my $to = join (",\n\t", @recipients);
1262 @recipients = unique_email_list
(@recipients,@cc,@bcclist);
1263 @recipients = (map { extract_valid_address_or_die
($_) } @recipients);
1264 my $date = format_2822_time
($time++);
1265 my $gitversion = '@@GIT_VERSION@@';
1266 if ($gitversion =~ m/..GIT_VERSION../) {
1267 $gitversion = Git
::version
();
1270 my $cc = join(",\n\t", unique_email_list
(@cc));
1273 $ccline = "\nCc: $cc";
1275 make_message_id
() unless defined($message_id);
1277 my $header = "From: $sender
1281 Message-Id: $message_id
1284 $header .= "X-Mailer: git-send-email $gitversion\n";
1288 $header .= "In-Reply-To: $reply_to\n";
1289 $header .= "References: $references\n";
1292 $header .= join("\n", @xh) . "\n";
1295 my @sendmail_parameters = ('-i', @recipients);
1296 my $raw_from = $sender;
1297 if (defined $envelope_sender && $envelope_sender ne "auto") {
1298 $raw_from = $envelope_sender;
1300 $raw_from = extract_valid_address
($raw_from);
1301 unshift (@sendmail_parameters,
1302 '-f', $raw_from) if(defined $envelope_sender);
1304 if ($needs_confirm && !$dry_run) {
1305 print "\n$header\n";
1306 if ($needs_confirm eq "inform") {
1307 $confirm_unconfigured = 0; # squelch this message for the rest of this run
1308 $ask_default = "y"; # assume yes on EOF since user hasn't explicitly asked for confirmation
1310 The Cc list above has been expanded by additional
1311 addresses found in the patch commit message. By default
1312 send-email prompts before sending whenever this occurs.
1313 This behavior is controlled by the sendemail.confirm
1314 configuration setting.
1316 For additional information, run 'git send-email --help'.
1317 To retain the current behavior, but squelch this message,
1318 run 'git config --global sendemail.confirm auto'.
1322 # TRANSLATORS: Make sure to include [y] [n] [q] [a] in your
1323 # translation. The program will only accept English input
1325 $_ = ask
(__
("Send this email? ([y]es|[n]o|[q]uit|[a]ll): "),
1326 valid_re
=> qr/^(?:yes|y|no|n|quit|q|all|a)/i,
1327 default => $ask_default);
1328 die __
("Send this email reply required") unless defined $_;
1332 cleanup_compose_files
();
1339 unshift (@sendmail_parameters, @smtp_server_options);
1342 # We don't want to send the email.
1343 } elsif (file_name_is_absolute
($smtp_server)) {
1344 my $pid = open my $sm, '|-';
1345 defined $pid or die $!;
1347 exec($smtp_server, @sendmail_parameters) or die $!;
1349 print $sm "$header\n$message";
1350 close $sm or die $!;
1353 if (!defined $smtp_server) {
1354 die __
("The required SMTP server is not properly defined.")
1358 my $use_net_smtp_ssl = version
->parse($Net::SMTP
::VERSION
) < version
->parse("2.34");
1359 $smtp_domain ||= maildomain
();
1361 if ($smtp_encryption eq 'ssl') {
1362 $smtp_server_port ||= 465; # ssmtp
1363 require IO
::Socket
::SSL
;
1365 # Suppress "variable accessed once" warning.
1368 $IO::Socket
::SSL
::DEBUG
= 1;
1371 # Net::SMTP::SSL->new() does not forward any SSL options
1372 IO
::Socket
::SSL
::set_client_defaults
(
1373 ssl_verify_params
());
1375 if ($use_net_smtp_ssl) {
1376 require Net
::SMTP
::SSL
;
1377 $smtp ||= Net
::SMTP
::SSL
->new($smtp_server,
1378 Hello
=> $smtp_domain,
1379 Port
=> $smtp_server_port,
1380 Debug
=> $debug_net_smtp);
1383 $smtp ||= Net
::SMTP
->new($smtp_server,
1384 Hello
=> $smtp_domain,
1385 Port
=> $smtp_server_port,
1386 Debug
=> $debug_net_smtp,
1391 $smtp_server_port ||= 25;
1392 $smtp ||= Net
::SMTP
->new($smtp_server,
1393 Hello
=> $smtp_domain,
1394 Debug
=> $debug_net_smtp,
1395 Port
=> $smtp_server_port);
1396 if ($smtp_encryption eq 'tls' && $smtp) {
1397 if ($use_net_smtp_ssl) {
1398 $smtp->command('STARTTLS');
1400 if ($smtp->code != 220) {
1401 die sprintf(__
("Server does not support STARTTLS! %s"), $smtp->message);
1403 require Net
::SMTP
::SSL
;
1404 $smtp = Net
::SMTP
::SSL
->start_SSL($smtp,
1405 ssl_verify_params
())
1406 or die sprintf(__
("STARTTLS failed! %s"), IO
::Socket
::SSL
::errstr
());
1409 $smtp->starttls(ssl_verify_params
())
1410 or die sprintf(__
("STARTTLS failed! %s"), IO
::Socket
::SSL
::errstr
());
1412 $smtp_encryption = '';
1413 # Send EHLO again to receive fresh
1414 # supported commands
1415 $smtp->hello($smtp_domain);
1420 die __
("Unable to initialize SMTP properly. Check config and use --smtp-debug."),
1421 " VALUES: server=$smtp_server ",
1422 "encryption=$smtp_encryption ",
1423 "hello=$smtp_domain",
1424 defined $smtp_server_port ?
" port=$smtp_server_port" : "";
1427 smtp_auth_maybe
or die $smtp->message;
1429 $smtp->mail( $raw_from ) or die $smtp->message;
1430 $smtp->to( @recipients ) or die $smtp->message;
1431 $smtp->data or die $smtp->message;
1432 $smtp->datasend("$header\n") or die $smtp->message;
1433 my @lines = split /^/, $message;
1434 foreach my $line (@lines) {
1435 $smtp->datasend("$line") or die $smtp->message;
1437 $smtp->dataend() or die $smtp->message;
1438 $smtp->code =~ /250|200/ or die sprintf(__
("Failed to send %s\n"), $subject).$smtp->message;
1441 printf($dry_run ? __
("Dry-Sent %s\n") : __
("Sent %s\n"), $subject);
1443 print($dry_run ? __
("Dry-OK. Log says:\n") : __
("OK. Log says:\n"));
1444 if (!file_name_is_absolute
($smtp_server)) {
1445 print "Server: $smtp_server\n";
1446 print "MAIL FROM:<$raw_from>\n";
1447 foreach my $entry (@recipients) {
1448 print "RCPT TO:<$entry>\n";
1451 print "Sendmail: $smtp_server ".join(' ',@sendmail_parameters)."\n";
1453 print $header, "\n";
1455 print __
("Result: "), $smtp->code, ' ',
1456 ($smtp->message =~ /\n([^\n]+\n)$/s), "\n";
1458 print __
("Result: OK\n");
1465 $reply_to = $initial_reply_to;
1466 $references = $initial_reply_to || '';
1467 $subject = $initial_subject;
1470 foreach my $t (@files) {
1471 open my $fh, "<", $t or die sprintf(__
("can't open file %s"), $t);
1474 my $sauthor = undef;
1475 my $author_encoding;
1476 my $has_content_type;
1479 my $has_mime_version;
1483 my $input_format = undef;
1487 # First unfold multiline header fields
1490 if (/^\s+\S/ and @header) {
1491 chomp($header[$#header]);
1493 $header[$#header] .= $_;
1498 # Now parse the header
1501 $input_format = 'mbox';
1505 if (!defined $input_format && /^[-A-Za-z]+:\s/) {
1506 $input_format = 'mbox';
1509 if (defined $input_format && $input_format eq 'mbox') {
1510 if (/^Subject:\s+(.*)$/i) {
1513 elsif (/^From:\s+(.*)$/i) {
1514 ($author, $author_encoding) = unquote_rfc2047
($1);
1515 $sauthor = sanitize_address
($author);
1516 next if $suppress_cc{'author'};
1517 next if $suppress_cc{'self'} and $sauthor eq $sender;
1518 printf(__
("(mbox) Adding cc: %s from line '%s'\n"),
1519 $1, $_) unless $quiet;
1522 elsif (/^To:\s+(.*)$/i) {
1523 foreach my $addr (parse_address_line
($1)) {
1524 printf(__
("(mbox) Adding to: %s from line '%s'\n"),
1525 $addr, $_) unless $quiet;
1529 elsif (/^Cc:\s+(.*)$/i) {
1530 foreach my $addr (parse_address_line
($1)) {
1531 my $qaddr = unquote_rfc2047
($addr);
1532 my $saddr = sanitize_address
($qaddr);
1533 if ($saddr eq $sender) {
1534 next if ($suppress_cc{'self'});
1536 next if ($suppress_cc{'cc'});
1538 printf(__
("(mbox) Adding cc: %s from line '%s'\n"),
1539 $addr, $_) unless $quiet;
1543 elsif (/^Content-type:/i) {
1544 $has_content_type = 1;
1545 if (/charset="?([^ "]+)/) {
1546 $body_encoding = $1;
1550 elsif (/^MIME-Version/i) {
1551 $has_mime_version = 1;
1554 elsif (/^Message-Id: (.*)/i) {
1557 elsif (/^Content-Transfer-Encoding: (.*)/i) {
1558 $xfer_encoding = $1 if not defined $xfer_encoding;
1560 elsif (!/^Date:\s/i && /^[-A-Za-z]+:\s+\S/) {
1565 # In the traditional
1566 # "send lots of email" format,
1569 # So let's support that, too.
1570 $input_format = 'lots';
1571 if (@cc == 0 && !$suppress_cc{'cc'}) {
1572 printf(__
("(non-mbox) Adding cc: %s from line '%s'\n"),
1573 $_, $_) unless $quiet;
1575 } elsif (!defined $subject) {
1580 # Now parse the message body
1583 if (/^(Signed-off-by|Cc): ([^>]*>?)/i) {
1585 my ($what, $c) = ($1, $2);
1587 my $sc = sanitize_address
($c);
1588 if ($sc eq $sender) {
1589 next if ($suppress_cc{'self'});
1591 next if $suppress_cc{'sob'} and $what =~ /Signed-off-by/i;
1592 next if $suppress_cc{'bodycc'} and $what =~ /Cc/i;
1595 printf(__
("(body) Adding cc: %s from line '%s'\n"),
1596 $c, $_) unless $quiet;
1601 push @to, recipients_cmd
("to-cmd", "to", $to_cmd, $t)
1603 push @cc, recipients_cmd
("cc-cmd", "cc", $cc_cmd, $t)
1604 if defined $cc_cmd && !$suppress_cc{'cccmd'};
1606 if ($broken_encoding{$t} && !$has_content_type) {
1607 $xfer_encoding = '8bit' if not defined $xfer_encoding;
1608 $has_content_type = 1;
1609 push @xh, "Content-Type: text/plain; charset=$auto_8bit_encoding";
1610 $body_encoding = $auto_8bit_encoding;
1613 if ($broken_encoding{$t} && !is_rfc2047_quoted
($subject)) {
1614 $subject = quote_subject
($subject, $auto_8bit_encoding);
1617 if (defined $sauthor and $sauthor ne $sender) {
1618 $message = "From: $author\n\n$message";
1619 if (defined $author_encoding) {
1620 if ($has_content_type) {
1621 if ($body_encoding eq $author_encoding) {
1622 # ok, we already have the right encoding
1625 # uh oh, we should re-encode
1629 $xfer_encoding = '8bit' if not defined $xfer_encoding;
1630 $has_content_type = 1;
1632 "Content-Type: text/plain; charset=$author_encoding";
1636 if (defined $target_xfer_encoding) {
1637 $xfer_encoding = '8bit' if not defined $xfer_encoding;
1638 $message = apply_transfer_encoding
(
1639 $message, $xfer_encoding, $target_xfer_encoding);
1640 $xfer_encoding = $target_xfer_encoding;
1642 if (defined $xfer_encoding) {
1643 push @xh, "Content-Transfer-Encoding: $xfer_encoding";
1645 if (defined $xfer_encoding or $has_content_type) {
1646 unshift @xh, 'MIME-Version: 1.0' unless $has_mime_version;
1650 $confirm eq "always" or
1651 ($confirm =~ /^(?:auto|cc)$/ && @cc) or
1652 ($confirm =~ /^(?:auto|compose)$/ && $compose && $message_num == 1));
1653 $needs_confirm = "inform" if ($needs_confirm && $confirm_unconfigured && @cc);
1655 @to = process_address_list
(@to);
1656 @cc = process_address_list
(@cc);
1658 @to = (@initial_to, @to);
1659 @cc = (@initial_cc, @cc);
1661 if ($message_num == 1) {
1662 if (defined $cover_cc and $cover_cc) {
1665 if (defined $cover_to and $cover_to) {
1670 my $message_was_sent = send_message
();
1672 # set up for the next message
1673 if ($thread && $message_was_sent &&
1674 ($chain_reply_to || !defined $reply_to || length($reply_to) == 0 ||
1675 $message_num == 1)) {
1676 $reply_to = $message_id;
1677 if (length $references > 0) {
1678 $references .= "\n $message_id";
1680 $references = "$message_id";
1683 $message_id = undef;
1686 # Execute a command (e.g. $to_cmd) to get a list of email addresses
1687 # and return a results array
1688 sub recipients_cmd
{
1689 my ($prefix, $what, $cmd, $file) = @_;
1692 open my $fh, "-|", "$cmd \Q$file\E"
1693 or die sprintf(__
("(%s) Could not execute '%s'"), $prefix, $cmd);
1694 while (my $address = <$fh>) {
1695 $address =~ s/^\s*//g;
1696 $address =~ s/\s*$//g;
1697 $address = sanitize_address
($address);
1698 next if ($address eq $sender and $suppress_cc{'self'});
1699 push @addresses, $address;
1700 printf(__
("(%s) Adding %s: %s from: '%s'\n"),
1701 $prefix, $what, $address, $cmd) unless $quiet;
1704 or die sprintf(__
("(%s) failed to close pipe to '%s'"), $prefix, $cmd);
1708 cleanup_compose_files
();
1710 sub cleanup_compose_files
{
1711 unlink($compose_filename, $compose_filename . ".final") if $compose;
1714 $smtp->quit if $smtp;
1716 sub apply_transfer_encoding
{
1717 my $message = shift;
1721 return $message if ($from eq $to and $from ne '7bit');
1723 require MIME
::QuotedPrint
;
1724 require MIME
::Base64
;
1726 $message = MIME
::QuotedPrint
::decode
($message)
1727 if ($from eq 'quoted-printable');
1728 $message = MIME
::Base64
::decode
($message)
1729 if ($from eq 'base64');
1731 die __
("cannot send message as 7bit")
1732 if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
1734 if ($to eq '7bit' or $to eq '8bit');
1735 return MIME
::QuotedPrint
::encode
($message, "\n", 0)
1736 if ($to eq 'quoted-printable');
1737 return MIME
::Base64
::encode
($message, "\n")
1738 if ($to eq 'base64');
1739 die __
("invalid transfer encoding");
1742 sub unique_email_list
{
1746 foreach my $entry (@_) {
1747 my $clean = extract_valid_address_or_die
($entry);
1748 $seen{$clean} ||= 0;
1749 next if $seen{$clean}++;
1750 push @emails, $entry;
1755 sub validate_patch
{
1759 my $validate_hook = catfile
(catdir
($repo->repo_path(), 'hooks'),
1760 'sendemail-validate');
1762 if (-x
$validate_hook) {
1763 my $target = abs_path
($fn);
1764 # The hook needs a correct cwd and GIT_DIR.
1765 my $cwd_save = cwd
();
1766 chdir($repo->wc_path() or $repo->repo_path())
1767 or die("chdir: $!");
1768 local $ENV{"GIT_DIR"} = $repo->repo_path();
1769 $hook_error = "rejected by sendemail-validate hook"
1770 if system($validate_hook, $target);
1771 chdir($cwd_save) or die("chdir: $!");
1773 return $hook_error if $hook_error;
1776 open(my $fh, '<', $fn)
1777 or die sprintf(__
("unable to open %s: %s\n"), $fn, $!);
1778 while (my $line = <$fh>) {
1779 if (length($line) > 998) {
1780 return sprintf(__
("%s: patch contains a line longer than 998 characters"), $.);
1787 my ($last, $lastlen, $file, $known_suffix) = @_;
1788 my ($suffix, $skip);
1791 if (defined $last &&
1792 ($lastlen < length($file)) &&
1793 (substr($file, 0, $lastlen) eq $last) &&
1794 ($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) {
1795 if (defined $known_suffix && $suffix eq $known_suffix) {
1796 printf(__
("Skipping %s with backup suffix '%s'.\n"), $file, $known_suffix);
1799 # TRANSLATORS: please keep "[y|N]" as is.
1800 my $answer = ask
(sprintf(__
("Do you really want to send %s? [y|N]: "), $file),
1801 valid_re
=> qr/^(?:y|n)/i,
1803 $skip = ($answer ne 'y');
1805 $known_suffix = $suffix;
1809 return ($skip, $known_suffix);
1812 sub handle_backup_files
{
1814 my ($last, $lastlen, $known_suffix, $skip, @result);
1815 for my $file (@file) {
1816 ($skip, $known_suffix) = handle_backup
($last, $lastlen,
1817 $file, $known_suffix);
1818 push @result, $file unless $skip;
1820 $lastlen = length($file);
1825 sub file_has_nonascii
{
1827 open(my $fh, '<', $fn)
1828 or die sprintf(__
("unable to open %s: %s\n"), $fn, $!);
1829 while (my $line = <$fh>) {
1830 return 1 if $line =~ /[^[:ascii:]]/;
1835 sub body_or_subject_has_nonascii
{
1837 open(my $fh, '<', $fn)
1838 or die sprintf(__
("unable to open %s: %s\n"), $fn, $!);
1839 while (my $line = <$fh>) {
1840 last if $line =~ /^$/;
1841 return 1 if $line =~ /^Subject.*[^[:ascii:]]/;
1843 while (my $line = <$fh>) {
1844 return 1 if $line =~ /[^[:ascii:]]/;