git-send-email-scripton commit [PATCH] Convert from using quoted-printable to just 8bit encoding on all emails. (9133261)
   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;
  24use Mail::Sendmail qw(sendmail %mailcfg);
  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
  32# Example reply to:
  33#$initial_reply_to = ''; #<20050203173208.GA23964@foobar.com>';
  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';
 172        $mailcfg{mime} = 0;
 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}