Wie konfiguriere ich mutt so, dass der Datumskopf in meiner lokalen Zeitzone im Pager angezeigt wird?

13

Wenn ich eine Nachricht im Pager Mutt anzeige, wird die Uhrzeit im Date-Header in UTC und nicht in meiner lokalen Zeitzone angezeigt. Die Indexansicht zeigt die Ortszeit korrekt an. Ich habe diesen alten Mailinglisten-Beitrag gefunden , in dem beschrieben wird, wie die Ortszeit in der Statusleiste am unteren Bildschirmrand angezeigt wird, aber die Uhrzeit in der Datumskopfzeile am oberen Bildschirmrand wird dadurch immer noch nicht "korrigiert". Gibt es eine Möglichkeit, den Pager zu veranlassen, die Date-Header-Zeit in die Ortszeit umzuwandeln?

Ben Williams
quelle

Antworten:

3

Fügen .muttrcSie folgende Zeile hinzu:

set display_filter="exec sed -r \"s/^Date:\\s*(([F-Wa-u]{3},\\s*)?[[:digit:]]{1,2}\\s+[A-Sa-y]{3}\\s+[[:digit:]]{4}\\s+[[:digit:]]{1,2}:[[:digit:]]{1,2}(:[[:digit:]]{1,2})?\\s+[+-][[:digit:]]{4})/date +'Date: %a, %d %b %Y %H:%M:%S %z' -d '\\1'/e\""

Dadurch wird der Date:Header in der Nachricht (nur zur Anzeige) in Ihre lokale Zeitzone geändert, wenn der Header ein gültiges Datum im RFC-Format enthielt. Wenn das angegebene Datumsformat falsch war (es handelt sich immerhin um nicht vertrauenswürdige Benutzereingaben), wird es beibehalten. Um einem möglichen Versuch, den Shell-Code durch den Header sedeinzufügen, entgegenzuwirken, implementiert das Muster eine auf RFC 5322 basierende Whitelist (diese RFC definiert das Format des Date:Felds).

Beachten Sie, dass muttdie Befehlszeile nicht länger als 255 Zeichen ist. Daher habe ich den ursprünglichen sedBefehl optimiert, der eine strengere Whitelist für 255 Bytes enthält. Wenn Sie vorhaben, andere Aktionen mit der Nachricht auszuführen, können Sie den folgenden vollständigen sedBefehl in ein Skript einfügen:

sed -r "s/^Date:\s*(((Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s*)?[[:digit:]]{1,2}\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+[[:digit:]]{4}\s+[[:digit:]]{1,2}:[[:digit:]]{1,2}(:[[:digit:]]{1,2})?\s+[+-][[:digit:]]{4})/date +'Date: %a, %d %b %Y %H:%M:%S %z' -d '\1'/e"
Galaxis
quelle
Gibt es eine Möglichkeit, das unter macOS zum Laufen zu bringen? Das möchte ich in meine filter.sedAkte aufnehmen. Vielen Dank!
Philipp L.
Dies ist nicht der Fall, es sei denn, Sie verwenden GNU sed (z. B. über Homebrew). Die obigen sedBefehle beruhen auf dem eModifikator für den sBefehl. Dieser Modifikator ist eine GNU-Erweiterung und macOS'es sedist die BSD- Erweiterung .
Galaxy
Answer by @viric ist gut. Keine Notwendigkeit, die Nachricht per Filter zu ändern.
Jangid
@Jangid, bitte lesen Sie die ursprüngliche Anfrage und sie fragt ausdrücklich nach der korrekten Anzeige einer lokalen Zone oben auf der Seite und nicht in der Statuszeile.
Galaxy
@galaxy Oh! Ja. Ich habe das gerade bemerkt. Richtig.
Jangid
11

Die Formatierung im Index wird von der index_formatEinstellung gesteuert - sie wird von mutt generiert. Der DateHeader wird nicht von mutt gesteuert, sondern ist ein Header, der in der gerade angezeigten Nachricht enthalten ist. Wenn die UTC-Zeit angezeigt wird, hat der sendende Server beim Generieren des Headers entschieden, UTC zu verwenden. Die einzige Möglichkeit, diese zu ändern, besteht darin, die Nachricht selbst zu ändern, entweder wenn Sie sie empfangen oder wenn Sie sie anzeigen.

Wenn Sie den Posteingang ändern, müssen Sie Ihrem E-Mail-Zustellungsagenten einen Filter hinzufügen. Dieser muss jedoch so ausgefeilt sein, dass der vorhandene DateHeader analysiert und neu geschrieben werden kann. Es ist mit ziemlicher Sicherheit besser, wenn Mutt die Nachricht beim Betrachten neu formatiert. Sie können die display_filterEigenschaft auf eine ausführbare Datei festlegen. Jede Nachricht, die Sie öffnen, wird durch die ausführbare Datei geleitet, bevor sie angezeigt wird.

Sie müssen ein Programm oder ein Shell-Skript schreiben, das jede Zeile der Nachricht liest und die Zeile durch den Date-Header ersetzt, oder ein vorhandenes Skript suchen ( hier könnte eines funktionieren, obwohl es eigentlich nicht so zu sein scheint notwendig sein, um eine temporäre Datei einzubeziehen)

Michael Mrozek
quelle
5

Nach Gilles 'Rat ist hier eine Version, die eine temporäre Datei und verwendet formail.

#!/bin/bash
TMPFILE=$(mktemp)

# save the message to a file
cat - >"$TMPFILE"
# extract the date header
DATE=$( formail -xDate: < "$TMPFILE" )
# convert to the current timezone (defined by TZ)
DATE=$( date -R -d "$DATE" )
# output the modified message
echo "Date: $DATE"
formail -fI Date < "$TMPFILE"
# clean up
rm -f "$TMPFILE"
Ben Williams
quelle
Dies ist anfällig für Code-Injection-Angriffe über einen fehlerhaften Date:Header. Wenn Sie in eine Subshell wechseln, müssen Sie die Eingabe validieren / bereinigen.
Galaxy
2

Hier ist eine Procmail-Lösung:

# extract date from mail
:0
TMPDATE=| formail -x Date

# get local date
LOCALDATE=`date --rfc-2822 -d "$TMPDATE"`

# add it new header to the mail
:0 f
| formail -I "LocalDate: $LOCALDATE"

Und zeige LocalDate: in muttrc an:

unignore localdate
fraff
quelle
Wie rufen Sie das auf?
Janus Troelsen,
@JanusTroelsen, ich glaube, Sie weisen das Skript display_filterin zu .muttrc.
Galaxy
2

set display_filter="/PATH/TO/THIS/PYTHON/FILE"in deinem .muttrc.

Python 3.3:

#!/usr/bin/env python3
import sys
import re
# import subprocess
from email.utils import format_datetime, parsedate_to_datetime

in_headers = True
for line in sys.stdin.readlines():
    if line == "\n": in_headers = False
    match = re.match(r'^Date: (.+)', line)

    if not in_headers or not match:
        print(line, end="")
        continue

    date_string = match.group(1)
    # use this if you do not have python 3.3+
    # converted_date = subprocess.Popen(['date','-d',date_string], stdout=subprocess.PIPE).communicate()[0].strip()
    converted_date = format_datetime(parsedate_to_datetime(date_string).astimezone(tz=None))
    print('Date:', converted_date)
Janus Troelsen
quelle
Die kommentierte Zeile ist anfällig für Code-Injection-Angriffe durch einen fehlerhaften Date:Header. Wenn Sie in eine Subshell wechseln, müssen Sie die Eingabe validieren / bereinigen. Andernfalls ist das Skript aus Sicherheitsgründen in Ordnung. Für ein Skript, das für jede Nachricht ausgeführt wird, die Sie durchsuchen, ist es jedoch ziemlich schwer.
Galaxy
2

Obligatorische Perl-Lösung, die den "Date" -Header beibehält, während ein zusätzlicher "Local-Date" -Header hinzugefügt wird, der die localtime-Version enthält:

#!/usr/bin/perl -n

use Date::Parse;
use POSIX;
use strict;

if (/^Date: (.*)$/) {
    my $datestr = $1;
    my $date = strftime ("%a, %d %b %Y %H:%M:%S",
                         localtime (str2time ($datestr)));
    print "Local-Date: $date\n";
}

print;
hyperair
quelle
0

Ich habe ein Shell-Skript erstellt, wie am Ende von Michaels Antwort beschrieben, das die Arbeit für mich erledigt:

#!/bin/bash
while IFS= read -r LINE; do
    if [[ "${LINE}" =~ ^Date:\ .* ]]; then
        DATE=${LINE#Date: }
        # convert to the current timezone (defined by TZ)
        DATE=$(date -d "${DATE}")
        printf '%s' "Date: ${DATE}"
    elif [[ -n $LINE ]]; then
      # We've reach the end of the headers, so stop parsing
      echo
      exec cat
    else
        printf '%s\n' "${LINE}"
    fi
done
Ben Williams
quelle
1
Das Parsen von E-Mails ist ziemlich schwierig. Ich empfehle, ein spezielles Tool wie formail(Teil des procmail- Pakets) oder reformail(Teil von maildrop ) zu verwenden, um den vorhandenen Date:Header zu extrahieren und einen neuen zu platzieren. Achten Sie auf Randfälle wie fehlende oder falsch Date:formatierte Header.
Gilles 'SO- hör auf böse zu sein'