all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pmg-devel] [PATCH pmg-api] dkim: local mail: fix `Date` header formatting under different locales
@ 2025-09-01 12:12 Christoph Heiss
  0 siblings, 0 replies; only message in thread
From: Christoph Heiss @ 2025-09-01 12:12 UTC (permalink / raw)
  To: pmg-devel

This was reported in the community forum to cause problems if the
(shell) locale was set to something different than 'C' or 'en_US.UTF-8'
[0].

Tl;dr: A different locale would cause the `Date` header to be formatted
according to that locale, instead of following the RFC2822 format.

E.g. under the locale `de_DE.UTF-8`, the header would look like this:

  Date: Mo, 25 Aug 2025 00:01:04 +0200

instead of the correct format of:

  Date: Mon, 25 Aug 2025 00:01:04 +0200

`perldoc POSIX` documents the following under strftime:

> For example, the specifiers `aAbBcpZ` change according to the locale
> settings of the user, [..]

Tested this by running the following, before and after:

  export LC_TIME=de_DE.UTF-8
  unset LC_ALL # ensure LC_TIME is used
  pmgreport

.. and verifying that the date header is now correct.

[0] https://forum.proxmox.com/threads/datumsprobleme-mit-den-pmg-reports.170245

Fixes: 77cfddd ("dkim: local mail: add Date header")
Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
 src/PMG/RuleDB/Notify.pm |  3 +--
 src/PMG/SMTP.pm          |  3 +--
 src/PMG/Utils.pm         | 28 ++++++++++++++++++++--
 src/tests/Makefile       |  6 ++++-
 src/tests/test_utils.pl  | 52 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 85 insertions(+), 7 deletions(-)
 create mode 100755 src/tests/test_utils.pl

diff --git a/src/PMG/RuleDB/Notify.pm b/src/PMG/RuleDB/Notify.pm
index caee64b..6adedb2 100644
--- a/src/PMG/RuleDB/Notify.pm
+++ b/src/PMG/RuleDB/Notify.pm
@@ -8,7 +8,6 @@ use MIME::Head;
 use MIME::Entity;
 use MIME::Words qw(encode_mimewords);
 use Encode qw(decode encode);
-use POSIX qw(strftime);
 
 use PVE::SafeSyslog;
 
@@ -249,7 +248,7 @@ sub execute {
         From => $from_header,
         To => $to,
         Subject => encode_mimewords(encode('UTF-8', $subject), "Charset" => "UTF-8"),
-        Date => strftime("%a, %d %b %Y %T %z", localtime()),
+        Date => PMG::Utils::format_date_header(localtime()),
         Data => encode('UTF-8', $body),
     );
 
diff --git a/src/PMG/SMTP.pm b/src/PMG/SMTP.pm
index 58c952d..dcb2795 100644
--- a/src/PMG/SMTP.pm
+++ b/src/PMG/SMTP.pm
@@ -5,7 +5,6 @@ use warnings;
 use IO::Socket;
 use Encode;
 use MIME::Entity;
-use POSIX qw(strftime);
 
 use PVE::SafeSyslog;
 
@@ -295,7 +294,7 @@ EOF
         Type => 'multipart/report; report-type=delivery-status;',
         To => $sender,
         From => $from_header,
-        Date => strftime("%a, %d %b %Y %T %z", localtime()),
+        Date => PMG::Utils::format_date_header(localtime()),
         Subject => 'Undelivered Mail',
     );
 
diff --git a/src/PMG/Utils.pm b/src/PMG/Utils.pm
index 890096f..0e47ad2 100644
--- a/src/PMG/Utils.pm
+++ b/src/PMG/Utils.pm
@@ -26,7 +26,7 @@ use MIME::Words;
 use Net::Cmd;
 use Net::IP;
 use Net::SMTP;
-use POSIX qw(strftime);
+use POSIX qw(strftime setlocale);
 use RRDs;
 use Socket;
 use Time::HiRes qw (gettimeofday);
@@ -1360,7 +1360,7 @@ sub finalize_report {
         Type => ($html && $plaintext) ? 'multipart/alternative' : 'multipart/related',
         To => $data->{pmail_raw},
         From => $mailfrom,
-        Date => strftime("%a, %d %b %Y %T %z", localtime()),
+        Date => format_date_header(localtime()),
         Subject => bencode_header(decode_entities($title)),
     );
 
@@ -1726,4 +1726,28 @@ sub test_regex {
     return undef;
 }
 
+=head3 format_date_header
+
+Returns a RFC2822-formatted timestamp for usage in the Date header.
+
+Takes the same parameters as C<POSIX::strftime(fmt, ..)>, i.e. C<$sec>,
+C<$min>, C<$hour>, C<$mday>, C<$mon>, C<$year>, C<$wday>, C<$yday>, C<$isdst>
+in that exact order - as e.g. returned by C<localtime()>.
+
+For example:
+
+    use PMG::Utils;
+    my $date = PMG::Utils::format_date_header(localtime());
+
+=cut
+
+sub format_date_header {
+    # ensure that we always use the right locale for formatting `Date` headers
+    my $old_locale = setlocale(POSIX::LC_TIME, 'C') // 'C';
+    my $date = strftime('%a, %d %b %Y %T %z', @_);
+    setlocale(POSIX::LC_TIME, 'C');
+
+    return $date;
+}
+
 1;
diff --git a/src/tests/Makefile b/src/tests/Makefile
index dc35796..68f77e4 100644
--- a/src/tests/Makefile
+++ b/src/tests/Makefile
@@ -4,7 +4,8 @@ export PERLLIB = ..
 
 all:
 
-check:
+.PHONY: check
+check: test-utils
 	./create_testdb.pl
 	./init_testdb.pl
 	./print_testdb.pl > testdb.txt.new
@@ -17,6 +18,9 @@ check:
 #	test_proxy.pl		\
 #	test_unpack.pl
 
+.PHONY: test-utils
+test-utils:
+	./test_utils.pl
 
 clean:
 	rm -rf *~ proxytest_report.out test.cfg testdb.txt.new
diff --git a/src/tests/test_utils.pl b/src/tests/test_utils.pl
new file mode 100755
index 0000000..8abcc8b
--- /dev/null
+++ b/src/tests/test_utils.pl
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+use POSIX qw(setlocale strftime);
+
+use PMG::Utils;
+
+subtest 'format_date_header works' => sub {
+    cmp_ok(length(PMG::Utils::format_date_header(localtime())), '>=', 30);
+    is(
+        PMG::Utils::format_date_header(47, 55, 12, 1, 8, 125, 1, 243, 1),
+        'Mon, 01 Sep 2025 12:55:47 +0200',
+    );
+    is(
+        PMG::Utils::format_date_header(59, 2, 8, 2, 0, 125, 4, 2, 0),
+        'Thu, 02 Jan 2025 08:02:59 +0100',
+    );
+};
+
+subtest 'format_date_header works with other locales' => sub {
+    # also check correctness under some other locale
+    my $old_locale = setlocale(POSIX::LC_TIME);
+
+    if (!defined(setlocale(POSIX::LC_TIME, "de_DE.UTF-8"))) {
+        # if the locale is not available, setlocale() returns undef
+        # in that case, the tests below do not make sense
+        plan(skip_all => "due to 'de_DE.UTF-8' locale not available");
+    }
+
+    # first check if the other locale indeed produces another format
+    is(
+        strftime('%a, %d %b %Y %T %z', 47, 55, 12, 1, 8, 125, 1, 243, 1),
+        'Mo, 01 Sep 2025 12:55:47 +0200',
+    );
+
+    cmp_ok(length(PMG::Utils::format_date_header(localtime())), '>=', 30);
+    is(
+        PMG::Utils::format_date_header(47, 55, 12, 1, 8, 125, 1, 243, 1),
+        'Mon, 01 Sep 2025 12:55:47 +0200',
+    );
+    is(
+        PMG::Utils::format_date_header(59, 2, 8, 2, 0, 125, 4, 2, 0),
+        'Thu, 02 Jan 2025 08:02:59 +0100',
+    );
+
+    setlocale(POSIX::LC_TIME, $old_locale);
+};
+
+done_testing();
-- 
2.50.1



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


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-09-01 12:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-01 12:12 [pmg-devel] [PATCH pmg-api] dkim: local mail: fix `Date` header formatting under different locales Christoph Heiss

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal