46
49
--cc Specify an initial "Cc:" list for the entire series
52
--cc-cmd Specify a command to execute per file which adds
53
per file specific cc address entries
49
55
--bcc Specify a list of email addresses that should be Bcc:
52
--compose Use \$EDITOR to edit an introductory message for the
58
--compose Use \$GIT_EDITOR, core.editor, \$EDITOR, or \$VISUAL to edit
59
an introductory message for the patch series.
55
61
--subject Specify the initial "Subject:" line.
56
62
Only necessary if --compose is also set. If --compose
64
70
email sent, rather than to the first email sent.
67
--no-signed-off-cc Suppress the automatic addition of email addresses
68
that appear in Signed-off-by: or Cc: lines to the cc:
69
list. Note: Using this option is not recommended.
73
--signed-off-cc Automatically add email addresses that appear in
74
Signed-off-by: or Cc: lines to the cc: list. Defaults to on.
71
76
--smtp-server If set, specifies the outgoing SMTP server to use.
72
77
Defaults to localhost.
74
79
--suppress-from Suppress sending emails to yourself if your address
75
appears in a From: line.
80
appears in a From: line. Defaults to off.
82
--thread Specify that the "In-Reply-To:" header should be set on all
83
emails. Defaults to on.
77
85
--quiet Make git-send-email less verbose. One line per email
78
86
should be all that is output.
136
144
# Variables we fill in automatically, or via prompting:
137
145
my (@to,@cc,@initial_cc,@bcclist,@xh,
138
$initial_reply_to,$initial_subject,@files,$from,$compose,$time);
146
$initial_reply_to,$initial_subject,@files,$author,$sender,$compose,$time);
140
# Behavior modification variables
141
my ($chain_reply_to, $quiet, $suppress_from, $no_signed_off_cc,
142
$dry_run) = (1, 0, 0, 0, 0);
144
149
my $envelope_sender;
154
159
$term = new FakeTerm "$@: going non-interactive";
157
my $def_chain = $repo->config_bool('sendemail.chainreplyto');
158
if (defined $def_chain and not $def_chain) {
162
# Behavior modification variables
163
my ($quiet, $dry_run) = (0, 0);
165
# Variables with corresponding config settings
166
my ($thread, $chain_reply_to, $suppress_from, $signed_off_cc, $cc_cmd);
168
my %config_settings = (
169
"thread" => [\$thread, 1],
170
"chainreplyto" => [\$chain_reply_to, 1],
171
"suppressfrom" => [\$suppress_from, 0],
172
"signedoffcc" => [\$signed_off_cc, 1],
173
"cccmd" => [\$cc_cmd, ""],
176
foreach my $setting (keys %config_settings) {
177
my $config = $repo->config_bool("sendemail.$setting");
178
${$config_settings{$setting}->[0]} = (defined $config) ? $config : $config_settings{$setting}->[1];
162
181
@bcclist = $repo->config('sendemail.bcc');
167
186
# Begin by accumulating all the variables (defined above), that we will end up
168
187
# needing, first, from the command line:
170
my $rc = GetOptions("from=s" => \$from,
189
my $rc = GetOptions("sender|from=s" => \$sender,
171
190
"in-reply-to=s" => \$initial_reply_to,
172
191
"subject=s" => \$initial_subject,
177
196
"smtp-server=s" => \$smtp_server,
178
197
"compose" => \$compose,
179
198
"quiet" => \$quiet,
180
"suppress-from" => \$suppress_from,
181
"no-signed-off-cc|no-signed-off-by-cc" => \$no_signed_off_cc,
199
"cc-cmd=s" => \$cc_cmd,
200
"suppress-from!" => \$suppress_from,
201
"signed-off-cc|signed-off-by-cc!" => \$signed_off_cc,
182
202
"dry-run" => \$dry_run,
183
203
"envelope-sender=s" => \$envelope_sender,
204
"thread!" => \$thread,
204
225
# Now, let's fill any that aren't set in with defaults:
206
my ($author) = $repo->ident_person('author');
207
my ($committer) = $repo->ident_person('committer');
227
my ($repoauthor) = $repo->ident_person('author');
228
my ($repocommitter) = $repo->ident_person('committer');
210
231
my @alias_files = $repo->config('sendemail.aliasesfile');
224
245
$aliases{$1} = [ split(/\s+/, $2) ];
226
247
pine => sub { my $fh = shift; while (<$fh>) {
227
if (/^(\S+)\s+(.*)$/) {
248
if (/^(\S+)\t.*\t(.*)$/) {
228
249
$aliases{$1} = [ split(/\s*,\s*/, $2) ];
230
251
gnus => sub { my $fh = shift; while (<$fh>) {
265
($sender) = expand_aliases($sender) if defined $sender;
244
267
my $prompting = 0;
245
if (!defined $from) {
246
$from = $author || $committer;
268
if (!defined $sender) {
269
$sender = $repoauthor || $repocommitter;
248
$_ = $term->readline("Who should the emails appear to be from? [$from] ");
271
$_ = $term->readline("Who should the emails appear to be from? [$sender] ");
249
272
} while (!defined $_);
252
print "Emails will be sent from: ", $from, "\n";
274
$sender = $_ if ($_);
275
print "Emails will be sent from: ", $sender, "\n";
276
299
@to = expand_aliases(@to);
277
@to = (map { sanitize_address_rfc822($_) } @to);
300
@to = (map { sanitize_address($_) } @to);
278
301
@initial_cc = expand_aliases(@initial_cc);
279
302
@bcclist = expand_aliases(@bcclist);
290
if (!defined $initial_reply_to && $prompting) {
313
if ($thread && !defined $initial_reply_to && $prompting) {
292
315
$_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ",
293
316
$initial_reply_to);
294
317
} while (!defined $_);
296
319
$initial_reply_to = $_;
297
$initial_reply_to =~ s/(^\s+|\s+$)//g;
320
$initial_reply_to =~ s/^\s+<?/</;
321
$initial_reply_to =~ s/>?\s+$/>/;
300
324
if (!$smtp_server) {
315
339
# effort to have it be unique
316
340
open(C,">",$compose_filename)
317
341
or die "Failed to open for writing $compose_filename: $!";
318
print C "From $from # This line is ignored.\n";
342
print C "From $sender # This line is ignored.\n";
319
343
printf C "Subject: %s\n\n", $initial_subject;
321
345
GIT: Please enter your email below.
329
my $editor = $ENV{EDITOR};
330
$editor = 'vi' unless defined $editor;
353
my $editor = $ENV{GIT_EDITOR} || $repo->config("core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
331
354
system($editor, $compose_filename);
333
356
open(C2,">",$compose_filename . ".final")
412
436
# 1 second since the last time we were called.
414
438
# We'll setup a template for the message id, using the "from" address:
415
my $message_id_from = extract_valid_address($from);
416
my $message_id_template = "<%s-git-send-email-$message_id_from>";
440
my ($message_id_stamp, $message_id_serial);
418
441
sub make_message_id
421
my $pseudo_rand = int (rand(4200));
422
$message_id = sprintf $message_id_template, "$date$pseudo_rand";
444
if (!defined $message_id_stamp) {
445
$message_id_stamp = sprintf("%s-%s", time, $$);
446
$message_id_serial = 0;
448
$message_id_serial++;
449
$uniq = "$message_id_stamp-$message_id_serial";
452
for ($sender, $repocommitter, $repoauthor) {
453
$du_part = extract_valid_address(sanitize_address($_));
454
last if (defined $du_part and $du_part ne '');
456
if (not defined $du_part or $du_part eq '') {
457
use Sys::Hostname qw();
458
$du_part = 'user@' . Sys::Hostname::hostname();
460
my $message_id_template = "<%s-git-send-email-%s>";
461
$message_id = sprintf($message_id_template, $uniq, $du_part);
423
462
#print "new message id = $message_id\n"; # Was useful for debugging
439
# If an address contains a . in the name portion, the name must be quoted.
440
sub sanitize_address_rfc822
478
# use the simplest quoting being able to handle the recipient
442
481
my ($recipient) = @_;
443
my ($recipient_name) = ($recipient =~ /^(.*?)\s+</);
444
if ($recipient_name && $recipient_name =~ /\./ && $recipient_name !~ /^".*"$/) {
445
my ($name, $addr) = ($recipient =~ /^(.*?)(\s+<.*)/);
446
$recipient = "\"$name\"$addr";
482
my ($recipient_name, $recipient_addr) = ($recipient =~ /^(.*?)\s*(<.*)/);
484
if (not $recipient_name) {
488
# if recipient_name is already quoted, do nothing
489
if ($recipient_name =~ /^(".*"|=\?utf-8\?q\?.*\?=)$/) {
493
# rfc2047 is needed if a non-ascii char is included
494
if ($recipient_name =~ /[^[:ascii:]]/) {
495
$recipient_name =~ s/([^-a-zA-Z0-9!*+\/])/sprintf("=%02X", ord($1))/eg;
496
$recipient_name =~ s/(.*)/=\?utf-8\?q\?$1\?=/;
499
# double quotes are needed if specials or CTLs are included
500
elsif ($recipient_name =~ /[][()<>@,;:\\".\000-\037\177]/) {
501
$recipient_name =~ s/(["\\\r])/\\$1/;
502
$recipient_name = "\"$recipient_name\"";
505
return "$recipient_name $recipient_addr";
453
511
my @recipients = unique_email_list(@to);
454
@cc = (map { sanitize_address_rfc822($_) } @cc);
512
@cc = (map { sanitize_address($_) } @cc);
455
513
my $to = join (",\n\t", @recipients);
456
514
@recipients = unique_email_list(@recipients,@cc,@bcclist);
457
515
@recipients = (map { extract_valid_address($_) } @recipients);
467
525
$ccline = "\nCc: $cc";
469
$from = sanitize_address_rfc822($from);
470
my $header = "From: $from
527
my $sanitized_sender = sanitize_address($sender);
530
my $header = "From: $sanitized_sender
472
532
Subject: $subject
474
534
Message-Id: $message_id
475
535
X-Mailer: git-send-email $gitversion
537
if ($thread && $reply_to) {
479
539
$header .= "In-Reply-To: $reply_to\n";
480
540
$header .= "References: $references\n";
486
546
my @sendmail_parameters = ('-i', @recipients);
487
my $raw_from = $from;
547
my $raw_from = $sanitized_sender;
488
548
$raw_from = $envelope_sender if (defined $envelope_sender);
489
549
$raw_from = extract_valid_address($raw_from);
490
550
unshift (@sendmail_parameters,
522
582
print "Sendmail: $smtp_server ".join(' ',@sendmail_parameters)."\n";
524
print "From: $from\nSubject: $subject\nCc: $cc\nTo: $to\n\n";
584
print "From: $sanitized_sender\nSubject: $subject\nCc: $cc\nTo: $to\n\n";
526
586
print "Result: ", $smtp->code, ' ',
527
587
($smtp->message =~ /\n([^\n]+\n)$/s), "\n";
534
594
$reply_to = $initial_reply_to;
535
595
$references = $initial_reply_to || '';
537
596
$subject = $initial_subject;
539
598
foreach my $t (@files) {
540
599
open(F,"<",$t) or die "can't open file $t";
542
my $author_not_sender = undef;
543
602
@cc = @initial_cc;
545
604
my $input_format = undef;
563
622
} elsif (/^(Cc|From):\s+(.*)$/) {
564
if (unquote_rfc2047($2) eq $from) {
623
if (unquote_rfc2047($2) eq $sender) {
566
624
next if ($suppress_from);
568
626
elsif ($1 eq 'From') {
569
$author_not_sender = $2;
627
$author = unquote_rfc2047($2);
571
629
printf("(mbox) Adding cc: %s from line '%s'\n",
572
630
$2, $_) unless $quiet;
613
if (defined $author_not_sender) {
614
$author_not_sender = unquote_rfc2047($author_not_sender);
615
$message = "From: $author_not_sender\n\n$message";
673
open(F, "$cc_cmd $t |")
674
or die "(cc-cmd) Could not execute '$cc_cmd'";
680
printf("(cc-cmd) Adding cc: %s from: '%s'\n",
681
$c, $cc_cmd) unless $quiet;
684
or die "(cc-cmd) failed to close pipe to '$cc_cmd'";
687
if (defined $author) {
688
$message = "From: $author\n\n$message";