From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <pmg-devel-bounces@lists.proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9])
	by lore.proxmox.com (Postfix) with ESMTPS id 799F21FF168
	for <inbox@lore.proxmox.com>; Mon, 14 Oct 2024 20:05:41 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
	by firstgate.proxmox.com (Proxmox) with ESMTP id 1BD6E9B96;
	Mon, 14 Oct 2024 20:06:11 +0200 (CEST)
From: Stoiko Ivanov <s.ivanov@proxmox.com>
To: pmg-devel@lists.proxmox.com
Date: Mon, 14 Oct 2024 20:05:47 +0200
Message-Id: <20241014180549.27671-2-s.ivanov@proxmox.com>
X-Mailer: git-send-email 2.39.5
In-Reply-To: <20241014180549.27671-1-s.ivanov@proxmox.com>
References: <20241014180549.27671-1-s.ivanov@proxmox.com>
MIME-Version: 1.0
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.070 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 DMARC_MISSING             0.1 Missing DMARC policy
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to
 Validity was blocked. See
 https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more
 information.
 RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to
 Validity was blocked. See
 https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more
 information.
 RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to
 Validity was blocked. See
 https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more
 information.
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pmg-devel] [PATCH pmg-api v4 1/2] utils: allow specifying plain
 and/or html for finalize_report()
X-BeenThere: pmg-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox Mail Gateway development discussion
 <pmg-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pmg-devel>, 
 <mailto:pmg-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pmg-devel/>
List-Post: <mailto:pmg-devel@lists.proxmox.com>
List-Help: <mailto:pmg-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel>, 
 <mailto:pmg-devel-request@lists.proxmox.com?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: pmg-devel-bounces@lists.proxmox.com
Sender: "pmg-devel" <pmg-devel-bounces@lists.proxmox.com>

To support both plain-text and HTML emails when sending reports,
PMG::Utils::finalize_report() now checks if a template has a
plain-text equivalent - (`.plain.tt` instead of `.tt` as suffix).

if either template file is empty (or non-existant) the corresponding
part is simply left-out.

This should enable admins top optionally send plain-text only reports,
or multipart mails with both text/plain and text/html, while not
changing the current behavior

Co-developed-by: Christoph Heiss <c.heiss@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
---
 src/PMG/Backup.pm        |  2 +-
 src/PMG/CLI/pmgqm.pm     |  6 ++--
 src/PMG/CLI/pmgreport.pm |  2 +-
 src/PMG/Utils.pm         | 77 +++++++++++++++++++++++++++++++++-------
 4 files changed, 70 insertions(+), 17 deletions(-)

diff --git a/src/PMG/Backup.pm b/src/PMG/Backup.pm
index ab7e628..c820d6b 100644
--- a/src/PMG/Backup.pm
+++ b/src/PMG/Backup.pm
@@ -418,7 +418,7 @@ sub send_backup_notification {
     my $tt = PMG::Config::get_template_toolkit();
 
     my $mailfrom = "Proxmox Mail Gateway <postmaster>";
-    PMG::Utils::finalize_report($tt, 'backup-notification.tt', $vars, $mailfrom, $email);
+    PMG::Utils::finalize_report($tt, 'backup-notification', $vars, $mailfrom, $email);
 
 }
 
diff --git a/src/PMG/CLI/pmgqm.pm b/src/PMG/CLI/pmgqm.pm
index 987ddc9..7016161 100755
--- a/src/PMG/CLI/pmgqm.pm
+++ b/src/PMG/CLI/pmgqm.pm
@@ -261,14 +261,14 @@ __PACKAGE__->register_method ({
 	my $domains = PVE::INotify::read_file('domains');
 	my $domainregex = PMG::Utils::domain_regex([keys %$domains]);
 
-	my $template = "spamreport-${reportstyle}.tt";
+	my $template = "spamreport-${reportstyle}";
 	my $found = 0;
 	foreach my $path (@$PMG::Config::tt_include_path) {
-	    if (-f "$path/$template") { $found = 1; last; }
+	    if (-f "$path/$template.tt") { $found = 1; last; }
 	}
 	if (!$found) {
 	    warn "unable to find template '$template' - using default\n";
-	    $template = "spamreport-verbose.tt";
+	    $template = "spamreport-verbose";
 	}
 
 	my $sth = $dbh->prepare(
diff --git a/src/PMG/CLI/pmgreport.pm b/src/PMG/CLI/pmgreport.pm
index 3403e44..99adfd2 100644
--- a/src/PMG/CLI/pmgreport.pm
+++ b/src/PMG/CLI/pmgreport.pm
@@ -359,7 +359,7 @@ __PACKAGE__->register_method ({
 	}
 
 	my $mailfrom = "Proxmox Mail Gateway <postmaster>";
-	PMG::Utils::finalize_report($tt, 'pmgreport.tt', $vars, $mailfrom, $email, $param->{debug});
+	PMG::Utils::finalize_report($tt, 'pmgreport', $vars, $mailfrom, $email, $param->{debug});
 
 	return undef;
     }});
diff --git a/src/PMG/Utils.pm b/src/PMG/Utils.pm
index 5d9ded4..9069f81 100644
--- a/src/PMG/Utils.pm
+++ b/src/PMG/Utils.pm
@@ -1248,32 +1248,85 @@ sub format_uptime {
     }
 }
 
+# Sends a report to the given receiver, building the body from templates.
+# if either html or plain template is empty that part is not added.
+# The subject of the mail is derived from the title tag of the HTML template, with a fallback to
+# the value after `subject:` on a line of its own in the plaintext template.
+#
+# The resulting mail is then reinjected with an empty envelope sender.
+#
+# Parameters:
+#   * `tt` - The template toolkit instance to use
+#   * `template_base` - base name of the template. suffixed with 'tt' yields the HTML template.
+#      suffixed with 'plain.tt' yields the plain text template
+#   * `data` - Template variables to pass to the template processor
+#   * `mailfrom` - Sender address
+#   * `receiver` - Recipient address
+#   * `debug` - whether to enable debug mode, resulting mail is only     printed, not reinjected
 sub finalize_report {
-    my ($tt, $template, $data, $mailfrom, $receiver, $debug) = @_;
+    my ($tt, $template_base, $data, $mailfrom, $receiver, $debug) = @_;
+
+    my $html_template;
+    my $html_path;
+    for my $path (@$PMG::Config::tt_include_path) {
+	if (-f "$path/$template_base.tt") {
+	    $html_template = "$template_base.tt";
+	    $html_path = "$path/$template_base.tt";
+	    last;
+	}
+    }
 
     my $html = '';
 
-    $tt->process($template, $data, \$html) ||
-	die $tt->error() . "\n";
-
+    if (defined($html_template) && -s $html_path) {
+	$tt->process($html_template, $data, \$html) ||
+	    die $tt->error() . "\n";
+    }
     my $title;
     if ($html =~ m|^\s*<title>(.*)</title>|m) {
 	$title = $1;
-    } else {
-	die "unable to extract template title\n";
     }
 
+    my $plain_template;
+    my $plain_path;
+    for my $path (@$PMG::Config::tt_include_path) {
+	if (-f "$path/$template_base.plain.tt") {
+	    $plain_template = "$template_base.plain.tt";
+	    $plain_path = "$path/$template_base.plain.tt";
+	    last;
+	}
+    }
+
+    my $plaintext = '';
+    if (defined($plain_template) && -s $plain_path) {
+	$tt->process($plain_template, $data, \$plaintext) ||
+	    die $tt->error() . "\n";
+    }
+
+    if ($plaintext =~ s/^subject: (.+)$//m) {
+	$title //= $1;
+    }
+
+    die "unable to extract template title\n" if !defined($title);
+
     my $top = MIME::Entity->build(
-	Type    => "multipart/related",
+	Type    => ($html && $plaintext) ? 'multipart/alternative' : 'multipart/related',
 	To      => $data->{pmail_raw},
 	From    => $mailfrom,
 	Subject => bencode_header(decode_entities($title)));
 
-    $top->attach(
-	Data     => $html,
-	Type     => "text/html",
-	Encoding => $debug ? 'binary' : 'quoted-printable');
-
+    if ($html) {
+	$top->attach(
+	    Data     => $html,
+	    Type     => "text/html",
+	    Encoding => $debug ? 'binary' : 'quoted-printable');
+    }
+    if ($plaintext) {
+	$top->attach(
+	    Data     => $plaintext,
+	    Type     => 'text/plain; charset=utf-8',
+	    Encoding => '8-bit');
+    }
     if ($debug) {
 	$top->print();
 	return;
-- 
2.39.5



_______________________________________________
pmg-devel mailing list
pmg-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel