Comment configurer mutt pour afficher l'en-tête de date dans mon fuseau horaire local dans le pager?

13

Lorsque je consulte un message dans le pager, mutt affiche l'heure dans l'en-tête Date en UTC plutôt que mon fuseau horaire local. La vue d'index affiche correctement l'heure locale. J'ai trouvé cet ancien message de liste de diffusion qui décrit comment afficher l'heure locale dans la barre d'état en bas de l'écran, mais cela ne "fixe" toujours pas l'heure dans l'en-tête Date en haut de l'écran. Existe-t-il un moyen d'obtenir le pager pour convertir l'heure de l'en-tête Date en heure locale?

Ben Williams
la source

Réponses:

3

Dans votre, .muttrcajoutez la ligne suivante:

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\""

Cela changera l'en- Date:tête du message (pour l'affichage uniquement) en votre fuseau horaire local si l'en-tête contenait une date au format RFC valide. Si le format de date fourni était incorrect (nous avons affaire à des entrées utilisateur non fiables après tout), il sera conservé. Pour lutter contre une éventuelle tentative d'injection du code shell à travers l'en-tête, le sedmodèle implémente une liste blanche basée sur le RFC 5322 (ce RFC définit le format du Date:champ).

Notez que muttlimite la ligne de commande à pas plus de 255 caractères, j'ai donc optimisé la sedcommande d' origine qui avait une liste blanche plus stricte pour tenir dans 255 octets. Si vous prévoyez de faire autre chose avec le message, alors la sedcommande complète que vous pouvez mettre dans un script est:

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"
galaxie
la source
Est-il possible de faire fonctionner cela sur macOS? J'aimerais l'inclure dans mon filter.seddossier. Merci!
Philipp L.
Il n'y en a pas, sauf si vous utilisez GNU sed (par exemple via Homebrew) - les sedcommandes ci-dessus dépendent du emodificateur de la scommande. Ce modificateur est une extension GNU et macOS sedest celui de BSD.
galaxy
La réponse de @viric est bonne. Pas besoin de changer de message via le filtre.
Jangid
@Jangid, veuillez lire la demande d'origine et elle demande spécifiquement l'affichage correct d'une zone locale en haut de la page et non dans la ligne d'état.
galaxy
@galaxy Oh! Oui. Je viens de le remarquer. Correct.
Jangid
11

Le formatage dans l'index est contrôlé par le index_formatparamètre - il est généré par mutt. L'en- Datetête n'est pas contrôlé par mutt, c'est un en-tête inclus avec le message qui vient d'être affiché. S'il affiche l'heure UTC, c'est que le serveur d'envoi a décidé d'utiliser UTC lors de la génération de l'en-tête. La seule façon de le modifier consiste à modifier réellement le message lui-même, soit lorsque vous le recevez, soit lorsque vous le consultez.

Le modifier au fur et à mesure de son entrée signifie ajouter un filtre à votre agent de distribution de courrier, mais il doit être suffisamment sophistiqué pour analyser l'en- Datetête existant et le réécrire. Il est presque certainement préférable de simplement reformater le message lorsque vous le regardez. Vous pouvez définir la display_filterpropriété sur un fichier exécutable, et il dirigera tout message que vous ouvrez via l'exécutable avant de l'afficher.

Vous devrez écrire un programme ou un script shell qui lit chaque ligne du message et remplace celle par l'en-tête Date, ou trouver un script existant (il y en a un ici qui pourrait fonctionner, bien qu'il ne semble pas qu'il devrait vraiment être nécessaire pour impliquer un fichier temporaire)

Michael Mrozek
la source
5

En suivant les conseils de Gilles, voici une version qui utilise un fichier temporaire et 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
la source
Ceci est sensible aux attaques par injection de code via un en- Date:tête mal formé - si vous allez dans un sous-shell, vous devez valider / assainir l'entrée.
galaxy
2

Voici une solution procmail:

# 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"

Et afficher LocalDate: dans muttrc:

unignore localdate
bouffon
la source
comment invoquez-vous cela?
Janus Troelsen
@JanusTroelsen, je crois que vous attribuez le script à display_filterin .muttrc.
galaxy
2

set display_filter="/PATH/TO/THIS/PYTHON/FILE"dans votre .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
la source
La ligne commentée est sensible aux attaques par injection de code via un en- Date:tête mal formé - si vous entrez dans un sous-shell, vous devez valider / nettoyer l'entrée, sinon le script est OK du point de vue de la sécurité. Cependant, il est assez lourd pour un script qui s'exécute sur chaque message que vous parcourez.
galaxy
2

Solution Perl obligatoire qui préserve l'en-tête "Date" tout en ajoutant un en-tête "Local-Date" supplémentaire pour contenir la version locale:

#!/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
la source
0

J'ai fait un script shell comme décrit à la fin de la réponse de Michael qui fait le travail pour moi:

#!/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
la source
1
L'analyse des e-mails est assez délicate. Je recommande d'utiliser un outil dédié comme formail(une partie du package procmail ) ou reformail(une partie de maildrop ) pour extraire l'en- Date:tête existant et en mettre un nouveau en place. Prenez soin des cas marginaux tels qu'un en- Date:tête manquant ou mal formaté.
Gilles 'SO- arrête d'être méchant'