@@ -87,8 +87,10 @@ sub usage {
87
87
88
88
Automating:
89
89
--identity <str> * Use the sendemail.<id> options.
90
- --to-cmd <str> * Email To: via `<str> \$ patch_path`
91
- --cc-cmd <str> * Email Cc: via `<str> \$ patch_path`
90
+ --to-cmd <str> * Email To: via `<str> \$ patch_path`.
91
+ --cc-cmd <str> * Email Cc: via `<str> \$ patch_path`.
92
+ --header-cmd <str> * Add headers via `<str> \$ patch_path`.
93
+ --no-header-cmd * Disable any header command in use.
92
94
--suppress-cc <str> * author, self, sob, cc, cccmd, body, bodycc, misc-by, all.
93
95
--[no-]cc-cover * Email Cc: addresses in the cover letter.
94
96
--[no-]to-cover * Email To: addresses in the cover letter.
@@ -202,7 +204,7 @@ sub format_2822_time {
202
204
$author ,$sender ,$smtp_authpass ,$annotate ,$compose ,$time );
203
205
# Things we either get from config, *or* are overridden on the
204
206
# command-line.
205
- my ($no_cc , $no_to , $no_bcc , $no_identity );
207
+ my ($no_cc , $no_to , $no_bcc , $no_identity , $no_header_cmd );
206
208
my (@config_to , @getopt_to );
207
209
my (@config_cc , @getopt_cc );
208
210
my (@config_bcc , @getopt_bcc );
@@ -269,7 +271,7 @@ sub do_edit {
269
271
# Variables with corresponding config settings
270
272
my ($suppress_from , $signed_off_by_cc );
271
273
my ($cover_cc , $cover_to );
272
- my ($to_cmd , $cc_cmd );
274
+ my ($to_cmd , $cc_cmd , $header_cmd );
273
275
my ($smtp_server , $smtp_server_port , @smtp_server_options );
274
276
my ($smtp_authuser , $smtp_encryption , $smtp_ssl_cert_path );
275
277
my ($batch_size , $relogin_delay );
@@ -318,6 +320,7 @@ sub do_edit {
318
320
" tocmd" => \$to_cmd ,
319
321
" cc" => \@config_cc ,
320
322
" cccmd" => \$cc_cmd ,
323
+ " headercmd" => \$header_cmd ,
321
324
" aliasfiletype" => \$aliasfiletype ,
322
325
" bcc" => \@config_bcc ,
323
326
" suppresscc" => \@suppress_cc ,
@@ -519,6 +522,8 @@ sub config_regexp {
519
522
" compose" => \$compose ,
520
523
" quiet" => \$quiet ,
521
524
" cc-cmd=s" => \$cc_cmd ,
525
+ " header-cmd=s" => \$header_cmd ,
526
+ " no-header-cmd" => \$no_header_cmd ,
522
527
" suppress-from!" => \$suppress_from ,
523
528
" no-suppress-from" => sub {$suppress_from = 0},
524
529
" suppress-cc=s" => \@suppress_cc ,
@@ -1783,16 +1788,16 @@ sub pre_process_file {
1783
1788
$subject = $initial_subject ;
1784
1789
$message = " " ;
1785
1790
$message_num ++;
1786
- # First unfold multiline header fields
1791
+ # Retrieve and unfold header fields.
1792
+ my @header_lines = ();
1787
1793
while (<$fh >) {
1788
1794
last if / ^\s *$ / ;
1789
- if (/ ^\s +\S / and @header ) {
1790
- chomp ($header [$#header ]);
1791
- s / ^\s +/ / ;
1792
- $header [$#header ] .= $_ ;
1793
- } else {
1794
- push (@header , $_ );
1795
- }
1795
+ push (@header_lines , $_ );
1796
+ }
1797
+ @header = unfold_headers(@header_lines );
1798
+ # Add computed headers, if applicable.
1799
+ unless ($no_header_cmd || ! $header_cmd ) {
1800
+ push @header , invoke_header_cmd($header_cmd , $t );
1796
1801
}
1797
1802
# Now parse the header
1798
1803
foreach (@header ) {
@@ -2033,15 +2038,64 @@ sub process_file {
2033
2038
}
2034
2039
}
2035
2040
2041
+ # Execute a command and return its output lines as an array. Blank
2042
+ # lines which do not appear at the end of the output are reported as
2043
+ # errors.
2044
+ sub execute_cmd {
2045
+ my ($prefix , $cmd , $file ) = @_ ;
2046
+ my @lines = ();
2047
+ my $seen_blank_line = 0;
2048
+ open my $fh , " -|" , " $cmd \Q $file \E "
2049
+ or die sprintf (__(" (%s ) Could not execute '%s '" ), $prefix , $cmd );
2050
+ while (my $line = <$fh >) {
2051
+ die sprintf (__(" (%s ) Malformed output from '%s '" ), $prefix , $cmd )
2052
+ if $seen_blank_line ;
2053
+ if ($line =~ / ^$ / ) {
2054
+ $seen_blank_line = $line =~ / ^$ / ;
2055
+ next ;
2056
+ }
2057
+ push @lines , $line ;
2058
+ }
2059
+ close $fh
2060
+ or die sprintf (__(" (%s ) failed to close pipe to '%s '" ), $prefix , $cmd );
2061
+ return @lines ;
2062
+ }
2063
+
2064
+ # Process headers lines, unfolding multiline headers as defined by RFC
2065
+ # 2822.
2066
+ sub unfold_headers {
2067
+ my @headers ;
2068
+ foreach (@_ ) {
2069
+ last if / ^\s *$ / ;
2070
+ if (/ ^\s +\S / and @headers ) {
2071
+ chomp ($headers [$#headers ]);
2072
+ s / ^\s +/ / ;
2073
+ $headers [$#headers ] .= $_ ;
2074
+ } else {
2075
+ push (@headers , $_ );
2076
+ }
2077
+ }
2078
+ return @headers ;
2079
+ }
2080
+
2081
+ # Invoke the provided CMD with FILE as an argument, which should
2082
+ # output RFC 2822 email headers. Fold multiline headers and return the
2083
+ # headers as an array.
2084
+ sub invoke_header_cmd {
2085
+ my ($cmd , $file ) = @_ ;
2086
+ my @lines = execute_cmd(" header-cmd" , $header_cmd , $file );
2087
+ return unfold_headers(@lines );
2088
+ }
2089
+
2036
2090
# Execute a command (e.g. $to_cmd) to get a list of email addresses
2037
2091
# and return a results array
2038
2092
sub recipients_cmd {
2039
2093
my ($prefix , $what , $cmd , $file , $quiet ) = @_ ;
2040
-
2094
+ my @lines = ();
2041
2095
my @addresses = ();
2042
- open my $fh , " -| " , " $cmd \Q $file \E "
2043
- or die sprintf (__( " ( %s ) Could not execute ' %s ' " ), $prefix , $cmd );
2044
- while ( my $address = < $fh > ) {
2096
+
2097
+ @lines = execute_cmd( $prefix , $cmd , $file );
2098
+ for my $address ( @lines ) {
2045
2099
$address =~ s / ^\s *// g ;
2046
2100
$address =~ s /\s *$// g ;
2047
2101
$address = sanitize_address($address );
@@ -2050,8 +2104,6 @@ sub recipients_cmd {
2050
2104
printf (__(" (%s ) Adding %s : %s from: '%s '\n " ),
2051
2105
$prefix , $what , $address , $cmd ) unless $quiet ;
2052
2106
}
2053
- close $fh
2054
- or die sprintf (__(" (%s ) failed to close pipe to '%s '" ), $prefix , $cmd );
2055
2107
return @addresses ;
2056
2108
}
2057
2109
0 commit comments