]> git.ipfire.org Git - thirdparty/git.git/blame - git-send-email-script
[PATCH] Convert from using quoted-printable to just 8bit encoding on all emails.
[thirdparty/git.git] / git-send-email-script
CommitLineData
83b24437
RA
1#!/usr/bin/perl -w
2# horrible hack of a script to send off a large number of email messages, one after
3# each other, all chained together. This is useful for large numbers of patches.
4#
5# Use at your own risk!!!!
6#
7# greg kroah-hartman Jan 8, 2002
8# <greg@kroah.com>
9#
10# GPL v2 (See COPYING)
11#
12# Ported to support git "mbox" format files by Ryan Anderson <ryan@michonline.com>
13#
14# Sends emails to the email listed on the command line.
15#
16# updated to give a valid subject and CC the owner of the patch - Jan 2005
17# first line of the message is who to CC,
18# and second line is the subject of the message.
19#
20
21use strict;
22use warnings;
23use Term::ReadLine;
9133261f 24use Mail::Sendmail qw(sendmail %mailcfg);
83b24437
RA
25use Getopt::Long;
26use Data::Dumper;
27use Email::Valid;
28
29# Variables we fill in automatically, or via prompting:
30my (@to,@cc,$initial_reply_to,$initial_subject,@files,$from);
31
9133261f 32# Example reply to:
83b24437 33#$initial_reply_to = ''; #<20050203173208.GA23964@foobar.com>';
83b24437
RA
34
35my $term = new Term::ReadLine 'git-send-email';
36
37# Begin by accumulating all the variables (defined above), that we will end up
38# needing, first, from the command line:
39
40my $rc = GetOptions("from=s" => \$from,
41 "in-reply-to=s" => \$initial_reply_to,
42 "subject=s" => \$initial_subject,
43 "to=s" => \@to,
44 );
45
46# Now, let's fill any that aren't set in with defaults:
47
48open(GITVAR,"-|","git-var","-l")
49 or die "Failed to open pipe from git-var: $!";
50
51my ($author,$committer);
52while(<GITVAR>) {
53 chomp;
54 my ($var,$data) = split /=/,$_,2;
55 my @fields = split /\s+/, $data;
56
57 my $ident = join(" ", @fields[0...(@fields-3)]);
58
59 if ($var eq 'GIT_AUTHOR_IDENT') {
60 $author = $ident;
61 } elsif ($var eq 'GIT_COMMITTER_IDENT') {
62 $committer = $ident;
63 }
64}
65close(GITVAR);
66
67
68if (!defined $from) {
69 $from = $author || $committer;
70 1 while (!defined ($_ = $term->readline("Who should the emails appear to be from? ",
71 $from)));
72 $from = $_;
73 print "Emails will be sent from: ", $from, "\n";
74}
75
76if (!@to) {
77 1 while (!defined ($_ = $term->readline("Who should the emails be sent to? ",
78 "")));
79 my $to = $_;
80 push @to, split /,/, $to;
81}
82
83if (!defined $initial_subject) {
84 1 while (!defined ($_ =
85 $term->readline("What subject should the emails start with? ",
86 $initial_subject)));
87 $initial_subject = $_;
88}
89
90if (!defined $initial_reply_to) {
91 1 while (!defined ($_ =
92 $term->readline("Message-ID to be used as In-Reply-To? ",
93 $initial_reply_to)));
94 $initial_reply_to = $_;
95}
96
97# Now that all the defaults are set, process the rest of the command line
98# arguments and collect up the files that need to be processed.
99for my $f (@ARGV) {
100 if (-d $f) {
101 opendir(DH,$f)
102 or die "Failed to opendir $f: $!";
103
104 push @files, map { +$f . "/" . $_ } grep !/^\.{1,2}$/,
105 sort readdir(DH);
106 } elsif (-f $f) {
107 push @files, $f;
108
109 } else {
110 print STDERR "Skipping $f - not found.\n";
111 }
112}
113
114if (@files) {
115 print $_,"\n" for @files;
116} else {
117 print <<EOT;
118git-send-email-script [options] <file | directory> [... file | directory ]
119Options:
120 --from Specify the "From:" line of the email to be sent.
121 --to Specify the primary "To:" line of the email.
122 --subject Specify the initial "Subject:" line.
123 --in-reply-to Specify the first "In-Reply-To:" header line.
124
125Error: Please specify a file or a directory on the command line.
126EOT
127 exit(1);
128}
129
130# Variables we set as part of the loop over files
131our ($message_id, $cc, %mail, $subject, $reply_to, $message);
132
133
134# Usually don't need to change anything below here.
135
136# we make a "fake" message id by taking the current number
137# of seconds since the beginning of Unix time and tacking on
138# a random number to the end, in case we are called quicker than
139# 1 second since the last time we were called.
140sub make_message_id
141{
142 my $date = `date "+\%s"`;
143 chomp($date);
144 my $pseudo_rand = int (rand(4200));
145 $message_id = "<$date$pseudo_rand\@foobar.com>";
146 print "new message id = $message_id\n";
147}
148
149
150
151$cc = "";
152
153sub send_message
154{
155 my %to;
156 $to{lc(Email::Valid->address($_))}++ for (@to);
157
158 my $to = join(",", keys %to);
159
160 %mail = ( To => $to,
161 From => $from,
162 CC => $cc,
163 Subject => $subject,
164 Message => $message,
165 'Reply-to' => $from,
166 'In-Reply-To' => $reply_to,
167 'Message-ID' => $message_id,
168 'X-Mailer' => "git-send-email-script",
169 );
170
171 $mail{smtp} = 'localhost';
9133261f 172 $mailcfg{mime} = 0;
83b24437
RA
173
174 #print Data::Dumper->Dump([\%mail],[qw(*mail)]);
175
176 sendmail(%mail) or die $Mail::Sendmail::error;
177
178 print "OK. Log says:\n", $Mail::Sendmail::log;
179 print "\n\n"
180}
181
182
183$reply_to = $initial_reply_to;
184make_message_id();
185$subject = $initial_subject;
186
187foreach my $t (@files) {
188 my $F = $t;
189 open(F,"<",$t) or die "can't open file $t";
190
191 @cc = ();
192 my $found_mbox = 0;
193 my $header_done = 0;
194 $message = "";
195 while(<F>) {
196 if (!$header_done) {
197 $found_mbox = 1, next if (/^From /);
198 chomp;
199
200 if ($found_mbox) {
201 if (/^Subject:\s+(.*)$/) {
202 $subject = $1;
203
204 } elsif (/^(Cc|From):\s+(.*)$/) {
205 printf("(mbox) Adding cc: %s from line '%s'\n",
206 $2, $_);
207 push @cc, $2;
208 }
209
210 } else {
211 # In the traditional
212 # "send lots of email" format,
213 # line 1 = cc
214 # line 2 = subject
215 # So let's support that, too.
216 if (@cc == 0) {
217 printf("(non-mbox) Adding cc: %s from line '%s'\n",
218 $_, $_);
219
220 push @cc, $_;
221
222 } elsif (!defined $subject) {
223 $subject = $_;
224 }
225 }
226
227 # A whitespace line will terminate the headers
228 if (m/^\s*$/) {
229 $header_done = 1;
230 }
231 } else {
232 $message .= $_;
233 if (/^Signed-off-by: (.*)$/i) {
234 my $c = $1;
235 chomp $c;
236 push @cc, $c;
237 printf("(sob) Adding cc: %s from line '%s'\n",
238 $c, $_);
239 }
240 }
241 }
242 close F;
243
244 my %clean_ccs;
245 $clean_ccs{lc(Email::Valid->address($_))}++ for @cc;
246
247 $cc = join(",", keys %clean_ccs);
248
249 send_message();
250
251 # set up for the next message
252 $reply_to = $message_id;
253 make_message_id();
254# $subject = "Re: ".$initial_subject;
255}