From 35ac61764499c272d2760de2b2a432be412ecede Mon Sep 17 00:00:00 2001 From: "Eric Wong (Contractor, The Linux Foundation)" Date: Tue, 6 Mar 2018 04:15:38 +0000 Subject: favor Received: date over Date: header globally The first Received: header is believable since it typically hits the user's mail server and can be treated as relatively trustworthy. We still show the Date: in per-message (permalink) views, which may expose users for having incorrect Date: headers, but all the ISO YYYY-MM-DD dates we display will match what we see. --- lib/PublicInbox/MsgTime.pm | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 lib/PublicInbox/MsgTime.pm (limited to 'lib/PublicInbox/MsgTime.pm') diff --git a/lib/PublicInbox/MsgTime.pm b/lib/PublicInbox/MsgTime.pm new file mode 100644 index 00000000..87664f4b --- /dev/null +++ b/lib/PublicInbox/MsgTime.pm @@ -0,0 +1,51 @@ +# Copyright (C) 2018 all contributors +# License: AGPL-3.0+ +package PublicInbox::MsgTime; +use strict; +use warnings; +use base qw(Exporter); +our @EXPORT_OK = qw(msg_timestamp); +use Date::Parse qw(str2time); +use Time::Zone qw(tz_offset); + +sub msg_timestamp ($) { + my ($hdr) = @_; # Email::MIME::Header + my ($ts, $zone); + my $mid; + my @recvd = $hdr->header_raw('Received'); + foreach my $r (@recvd) { + $zone = undef; + $r =~ /\s*(\d+\s+[[:alpha:]]+\s+\d{2,4}\s+ + \d+\D\d+(?:\D\d+)\s+([\+\-]\d+))/sx or next; + $zone = $2; + $ts = eval { str2time($1) } and last; + $mid ||= $hdr->header_raw('Message-ID'); + warn "no date in $mid Received: $r\n"; + } + unless (defined $ts) { + my @date = $hdr->header_raw('Date'); + foreach my $d (@date) { + $zone = undef; + $ts = eval { str2time($d) }; + if ($@) { + $mid ||= $hdr->header_raw('Message-ID'); + warn "bad Date: $d in $mid: $@\n"; + } elsif ($d =~ /\s+([\+\-]\d+)\s*\z/) { + $zone = $1; + } + } + } + $ts = time unless defined $ts; + return $ts unless wantarray; + + $zone ||= '+0000'; + # "-1200" is the furthest westermost zone offset, + # but git fast-import is liberal so we use "-1400" + if ($zone >= 1400 || $zone <= -1400) { + warn "bogus TZ offset: $zone, ignoring and assuming +0000\n"; + $zone = '+0000'; + } + ($ts, $zone); +} + +1; -- cgit v1.2.3-24-ge0c7