From 94100185f81bcaf576a46eaecadf7b90e41517bf Mon Sep 17 00:00:00 2001
From: Magnus Enger <magnus@libriotech.no>
Date: Mon, 12 Dec 2022 13:41:20 +0000
Subject: [PATCH] Bug 29354: Make overdue_notices.pl send .html

If you have EmailOverduesNoEmail = Send and specify "--html somedir",
overdue_notices.pl will send a file by email that contains partial
HTML, as a file called attachment.txt. This patch fixes that.

To reproduce in koha-testing-docker:
- EmailOverduesNoEmail = Send
- Make sure you have a loan that was due yesterday, by backdating the
  due date
- Set up an overdue action to send "Overdue Notice" (ODUE) to the
  category you made the loan to above, when a loan is one day overdue
- Run this command:
  $ sudo koha-shell -c "perl misc/cronjobs/overdue_notices.pl -v -t -html /tmp/" kohadev
- Look at the file /tmp/notices-<DATE>.html and make sure it is a full
  HTML document, with <html>, <head>, <body> etc.
- Create a report like this:
  SELECT message_id, letter_id, borrowernumber, subject, CONCAT( '<pre>', content, '</pre>' ) AS content,
    metadata, letter_code, message_transport_type, time_queued, updated_on, to_address, content_type, failure_code
  FROM message_queue
  WHERE subject = 'Overdue Notices'
  ORDER BY message_id DESC
- Run the report and verify there is a line like this in the "content"
  of the newest message:
  Content-Type: text/plain; name=attachment.txt
- A part of the "content" will be a block of several lines of gibberish
  (base64) that look something like "RGVhciAga29oYSwNCg0KQWN...". Copy
  this block of text to somewhere like base64decode.org and decode the
  text. You should see a fragment of HTML, without <html>, <head>,
  <body> etc.

To test:
- Apply the patch
- Run overdue_notices.pl again, with the same arguments as above
- Make sure /tmp/notices-<DATE>.html is still a full HTML document
- Re-run the report, and make sure you now have this in the "content":
  Content-Type: text/html; name=attachment.html
- Decode the base64 and make sure it is now a full HTML document, with
  <html>, <head>, <body> etc.
- Re-run overdue_notices.pl as above, but replace "-html /tmp/" with
  "-csv /tmp/test.csv"
- Make sure /tmp/test.csv and the decoded base64 from the report
  contains CSV data
- Re-run overdue_notices.pl as above, but replace "-html /tmp/" with
  "-text /tmp/"
- Make sure /tmp/notices-<DATE>.txt and the decoded base64 from the
  report contains no HTML

Note:
- The actual text from the different messages will be enclosed in
  <pre>-tags
- If you have HTML in your ODUE message template and run with -v, you
  will have warnings saying "The following terms were not matched and
  replaced"
These are due to Bug 14347, and are not adressed by the current patch.

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
---
 misc/cronjobs/overdue_notices.pl | 69 +++++++++++++++++++++++---------
 1 file changed, 49 insertions(+), 20 deletions(-)

diff --git a/misc/cronjobs/overdue_notices.pl b/misc/cronjobs/overdue_notices.pl
index f8fc79203c..19e6aef27b 100755
--- a/misc/cronjobs/overdue_notices.pl
+++ b/misc/cronjobs/overdue_notices.pl
@@ -435,18 +435,7 @@ if ( defined $htmlfilename ) {
     open $fh, ">:encoding(UTF-8)",File::Spec->catdir ($htmlfilename,"notices-".$today->ymd().".html");
   }
   
-  print $fh "<html>\n";
-  print $fh "<head>\n";
-  print $fh "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
-  print $fh "<style type='text/css'>\n";
-  print $fh "pre {page-break-after: always;}\n";
-  print $fh "pre {white-space: pre-wrap;}\n";
-  print $fh "pre {white-space: -moz-pre-wrap;}\n";
-  print $fh "pre {white-space: -o-pre-wrap;}\n";
-  print $fh "pre {word-wrap: break-work;}\n";
-  print $fh "</style>\n";
-  print $fh "</head>\n";
-  print $fh "<body>\n";
+  print $fh _get_html_start();
 }
 elsif ( defined $text_filename ) {
   if ( $text_filename eq '' ) {
@@ -848,16 +837,19 @@ END_SQL
         if ( defined $csvfilename ) {
             my $delimiter = C4::Context->csv_delimiter;
             $content = join($delimiter, qw(title name surname address1 address2 zipcode city country email itemcount itemsinfo due_date issue_date)) . "\n";
+            $content .= join( "\n", @output_chunks );
+        } elsif ( defined $htmlfilename ) {
+            $content = _get_html_start();
+            $content .= join( "\n", @output_chunks );
+            $content .= _get_html_end();
+        } else {
+            $content = join( "\n", @output_chunks );
         }
-        else {
-            $content = "";
-        }
-        $content .= join( "\n", @output_chunks );
 
         if ( C4::Context->preference('EmailOverduesNoEmail') ) {
             my $attachment = {
-                filename => defined $csvfilename ? 'attachment.csv' : 'attachment.txt',
-                type => 'text/plain',
+                filename => defined $csvfilename ? 'attachment.csv' : defined $htmlfilename ? 'attachment.html' : 'attachment.txt',
+                type => defined $htmlfilename ? 'text/html' : 'text/plain',
                 content => $content,
             };
 
@@ -885,8 +877,7 @@ if ($csvfilename) {
 }
 
 if ( defined $htmlfilename ) {
-  print $fh "</body>\n";
-  print $fh "</html>\n";
+  print $fh _get_html_end();
   close $fh;
 } elsif ( defined $text_filename ) {
   close $fh;
@@ -946,4 +937,42 @@ sub prepare_letter_for_printing {
     return $return;
 }
 
+=head2 _get_html_start
+
+Return the start of a HTML document, including html, head and the start body
+tags. This should be usable both in the HTML file written to disc, and in the
+attachment.html sent as email.
+
+=cut
+
+sub _get_html_start {
+
+    return "<html>
+<head>
+<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
+<style type='text/css'>
+pre {page-break-after: always;}
+pre {white-space: pre-wrap;}
+pre {white-space: -moz-pre-wrap;}
+pre {white-space: -o-pre-wrap;}
+pre {word-wrap: break-work;}
+</style>
+</head>
+<body>";
+
+}
+
+=head2 _get_html_end
+
+Return the end of an HTML document, namely the closing body and html tags.
+
+=cut
+
+sub _get_html_end {
+
+    return "</body>
+</html>";
+
+}
+
 cronlogaction({ action => 'End', info => "COMPLETED" });
-- 
2.30.2