From 674724ead5125eda63364b71c7527c6f6e71eeaa Mon Sep 17 00:00:00 2001 From: Andrew Ruthven Date: Mon, 27 Jun 2022 17:54:08 +1200 Subject: [PATCH] Add YAML support, improve GPG support. --- merge.pl | 157 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 109 insertions(+), 48 deletions(-) diff --git a/merge.pl b/merge.pl index 55b205e..53d41e1 100755 --- a/merge.pl +++ b/merge.pl @@ -35,14 +35,18 @@ $dir ||= shift; # If we're given a directory then look for the merge files in there. if (defined $dir) { - $vars = "$dir/merge.csv" - if $vars eq '' && -f "$dir/merge.csv"; + for my $file (qw/merge.csv data.csv data.yml/) { + if ($vars eq '' && -f "$dir/$file") { + $vars = "$dir/$file"; + last; + } + } $template = "$dir/merge.yml" if $template eq '' && -f "$dir/merge.yml"; } # Sanity check. -die "Sorry, where is the variables file?" +die "Sorry, where is the variables/data file?" unless -f $vars; die "Sorry, where is the template file?" unless -f $template; @@ -76,32 +80,85 @@ if ($tmplData->{'encrypt'} || $tmplData->{'sign'}) { $mg = new Mail::GnuPG(%mg_opts); } -my $IN = new FileHandle; -open($IN, $vars) - || die "Failed to open $vars for reading: $!\n"; - -# Work out the headers for the CSV file. -my $headers = $csv->getline($IN); -die "Nothing in $vars!" unless @$headers; -$csv->column_names(@$headers); +my $gpg = { + mg => $mg, + failed => [], + succeeded => [], +}; my $mimetypes; -if ($tmplData->{'attachment_col'}) { - die "You've specified an attachment column, but it isn't present!\n" - unless grep {/$tmplData->{'attachment_col'}/} @$headers; + +if ($vars =~ /csv$/) { + merge_with_csv($tmplData, $vars, $gpg, $tt); +} elsif ($vars =~ /ya?ml$/) { + merge_with_yaml($tmplData, $vars, $gpg, $tt); +} + +gpg_summary($gpg); +exit; + +sub merge_with_csv { + my ($tmplData, $vars, $gpg, $tt) = @_; + + my $IN = new FileHandle; + open($IN, $vars) + || die "Failed to open $vars for reading: $!\n"; + + # Work out the headers for the CSV file. + my $headers = $csv->getline($IN); + die "Nothing in $vars!" unless @$headers; + $csv->column_names(@$headers); + + if ($tmplData->{'attachment_col'}) { + die "You've specified an attachment column, but it isn't present!\n" + unless grep {/$tmplData->{'attachment_col'}/} @$headers; + } + + while (my $cols = $csv->getline_hr($IN) ) { + last unless %$cols; + + merge_message($tmplData, $cols, $gpg, $tt); + } + + close $IN; } -my @gpg_failed_addresses; -my @gpg_succeeded_addresses; +sub merge_with_yaml { + my ($tmplData, $vars, $gpg, $tt) = @_; + + my $data = LoadFile $vars + || die "Failed to load $vars"; -while (my $cols = $csv->getline_hr($IN) ) { - last unless %$cols; + # Work out the keys for the YAML file. + my $headers = []; + + for my $item (@{ $data }) { + for my $key (keys %{ $item }) { + if (! grep @{ $headers }, $key) { + push @{ $headers }, $key; + } + } + } + + if ($tmplData->{'attachment_col'}) { + die "You've specified an attachment column, but it isn't present!\n" + unless grep {/$tmplData->{'attachment_col'}/} @$headers; + } + + for my $item (@{ $data }) { + merge_message($tmplData, $item, $gpg, $tt); + } +} + +sub merge_message { + my ($tmplData, $cols, $gpg, $tt) = @_; if ($verbose) { print "\n\nTemplate variables:\n"; - for my $key (sort keys %$cols) { - print "$key: " . ($cols->{$key} || '') . "\n"; - } + print Dump($cols); +# for my $key (sort keys %$cols) { +# print "$key: " . ($cols->{$key} || '') . "\n"; +# } print "\n"; } @@ -142,15 +199,17 @@ while (my $cols = $csv->getline_hr($IN) ) { print "\n\n"; } - my $bcc = $tmplData->{'bcc'}; - my $cc = $tmplData->{'cc'}; + my $bcc = $tmplData->{'bcc'}; + my $cc = $tmplData->{'cc'}; + my $reply_to = $tmplData->{'reply_to'}; my $email_address = $cols->{'email'} || $cols->{'email_address'}; if ($send) { # If we're sending email, then send it, optionally with a BCC. print "Sending to $email_address" . - ($bcc ? "\n BCC " . (ref($bcc) eq 'ARRAY' ? join(", ", @{$bcc}) : $bcc) . " " : '') . - ($cc ? "\n cC " . (ref($cc) eq 'ARRAY' ? join(", ", @{$cc}) : $cc) . " " : '') . "\n"; + ($bcc ? "\n BCC " . (ref($bcc) eq 'ARRAY' ? join(", ", @{$bcc}) : $bcc) . " " : '') . + ($cc ? "\n cC " . (ref($cc) eq 'ARRAY' ? join(", ", @{$cc}) : $cc) . " " : '') . + ($reply_to ? "\n Reply To $reply_to" : '') . "\n"; my @emails = ( $email_address ); @@ -163,11 +222,12 @@ while (my $cols = $csv->getline_hr($IN) ) { } my $mail = MIME::Entity->build( - To => \@emails, - From => $tmplData->{'from'}, - Subject => $tmplData->{'subject'}, - Bcc => $tmplData->{'bcc'}, - Cc => $tmplData->{'bc'}, + To => \@emails, + From => $tmplData->{'from'}, + Subject => $tmplData->{'subject'}, + Bcc => $tmplData->{'bcc'}, + Cc => $tmplData->{'bc'}, + 'Reply-To' => $tmplData->{'reply_to'}, %fields ); @@ -190,35 +250,35 @@ while (my $cols = $csv->getline_hr($IN) ) { # Possibly GPG Encrypt and Sign the message. if ($tmplData->{'encrypt'} && $tmplData->{'sign'}) { - my $ret = $mg->mime_signencrypt($mail, @emails); + my $ret = $gpg->{'mg'}->mime_signencrypt($mail, @emails); if ($ret != 0) { - warn "Sorry, gpg encrypt error: " . join(", ", @{ $mg->{last_message} }) . "\n"; - push @gpg_failed_addresses, @emails; + warn "Sorry, gpg encrypt error: " . join(", ", @{ $gpg->{'mg'}->{last_message} }) . "\n"; + push @{ $gpg->{'failed'} }, @emails; next; } # Possibly GPG Sign the message. } elsif ($tmplData->{'sign'}) { - my $ret = $mg->mime_sign($mail, $tmplData->{'from'}); + my $ret = $gpg->{'mg'}->mime_sign($mail, $tmplData->{'from'}); if ($ret != 0) { - die "Sorry, gpg sign error: " . join(", ", @{ $mg->{last_message} }) . "\n"; + die "Sorry, gpg sign error: " . join(", ", @{ $gpg->{'mg'}->{last_message} }) . "\n"; } # Possibly GPG Encrypt the message. } elsif ($tmplData->{'encrypt'}) { - my $ret = $mg->mime_encrypt($mail, @emails); + my $ret = $gpg->{'mg'}->mime_encrypt($mail, @emails); if ($ret != 0) { - warn "Sorry, gpg encrypt error: " . join(", ", @{ $mg->{last_message} }) . "\n"; - push @gpg_failed_addresses, @emails; + warn "Sorry, gpg encrypt error: " . join(", ", @{ $gpg->{'mg'}->{last_message} }) . "\n"; + push @{ $gpg->{'failed'} }, @emails; next; } } $mail->send('sendmail'); - push @gpg_succeeded_addresses, @emails if defined $mg; + push @{ $gpg->{'succeeded'} }, @emails if defined $gpg->{'mg'}; } else { # Say who we want to send to. @@ -228,14 +288,15 @@ while (my $cols = $csv->getline_hr($IN) ) { } } -close $IN; +sub gpg_summary { + my $gpg = shift; -if (scalar(@gpg_succeeded_addresses) > 0) { - print "Sent GPG encrypted messages to the following addresses:\n"; - print " ", join("\n ", uniq(@gpg_succeeded_addresses)) . "\n\n"; -} -if (scalar(@gpg_failed_addresses) > 0) { - print "Failed to send GPG encrypted messages to the following addresses:\n"; - print " ", join("\n ", uniq(@gpg_failed_addresses)) . "\n\n"; + if (scalar(@{ $gpg->{'succeeded'} }) > 0) { + print "Sent GPG encrypted messages to the following addresses:\n"; + print " ", join("\n ", uniq(@{ $gpg->{'succeeded'} })) . "\n\n"; + } + if (scalar(@{ $gpg->{'failed'} }) > 0) { + print "Failed to send GPG encrypted messages to the following addresses:\n"; + print " ", join("\n ", uniq(@{ $gpg->{'failed'} })) . "\n\n"; + } } - -- 2.30.2