]> git.etc.gen.nz Git - mail-merge.git/commitdiff
Add YAML support, improve GPG support.
authorAndrew Ruthven <puck@catalystcloud.nz>
Mon, 27 Jun 2022 05:54:08 +0000 (17:54 +1200)
committerAndrew Ruthven <puck@catalyst.net.nz>
Mon, 27 Jun 2022 05:54:08 +0000 (17:54 +1200)
merge.pl

index 55b205ed8bea42d4dc1794dc4826f5ecf65027c6..53d41e110f791db404a951f05fce58a21fcf4895 100755 (executable)
--- 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";
+  }
 }
-