Come configuro mutt per visualizzare l'intestazione della data nel mio fuso orario locale nel cercapersone?


13

Quando visualizzo un messaggio nel cercapersone, il mutt visualizza l'ora nell'intestazione della data in UTC anziché il mio fuso orario locale. La vista indice mostra l'ora locale correttamente. Ho trovato questo vecchio post della mailing list che descrive come ottenere l'ora locale da visualizzare nella barra di stato nella parte inferiore dello schermo, ma questo non "risolve" l'ora nell'intestazione della data nella parte superiore dello schermo. Esiste un modo per convincere il cercapersone a convertire l'ora dell'intestazione della data in ora locale?

Risposte:


3

Nel tuo .muttrcaggiungere la seguente riga:

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

Ciò modificherà l' Date:intestazione nel messaggio (solo per la visualizzazione) nel fuso orario locale se l'intestazione conteneva una data in formato RFC valida. Se il formato della data fornito non era corretto (dopo tutto abbiamo a che fare con input dell'utente non attendibile) verrà conservato. Per combattere un possibile tentativo di iniettare il codice shell attraverso l'intestazione, il sedmodello implementa una whitelist basata su RFC 5322 (questo RFC definisce il formato del Date:campo).

Si noti che muttlimita la lunghezza della riga di comando non più lunga di 255 caratteri, quindi ho ottimizzato il sedcomando originale che aveva una whitelist più rigida per adattarsi a 255 byte. Se hai intenzione di fare altre cose con il messaggio, il sedcomando completo che puoi inserire in uno script è:

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"

C'è una possibilità per farlo funzionare su macOS? Vorrei includerlo nel mio filter.sedfile. Grazie!
Philipp L.

Non lo è, a meno che tu non stia usando GNU sed (ad es. Tramite Homebrew) - i sedcomandi precedenti si basano sul emodificatore del scomando. Quel modificatore è un'estensione GNU e macOS sedè quello BSD.
galassia

La risposta di @viric è buona. Non è necessario modificare il messaggio tramite filtro.
Jangid,

@Jangid, si prega di leggere la richiesta originale e richiede specificamente la corretta visualizzazione di una zona locale nella parte superiore della pagina e non nella riga di stato.
galaxy

@galaxy Oh! sì. L'ho appena notato. Corretta.
Jangid,

11

La formattazione nell'indice è controllata index_formatdall'impostazione: è generata da mutt. L' Dateintestazione non è controllata da mutt, è un'intestazione inclusa nel messaggio che viene appena visualizzato. Se mostra l'ora UTC è perché il server mittente ha deciso di utilizzare UTC durante la generazione dell'intestazione. L'unico modo per cambiarlo è in realtà cambiare il messaggio stesso, quando lo ricevi o quando lo visualizzi.

Cambiarlo quando arriva significa aggiungere un filtro all'agente di consegna della posta, ma deve essere abbastanza sofisticato da analizzare l' Dateintestazione esistente e riscriverlo. È quasi certamente meglio che mutt riformatta il messaggio quando lo guardi. È possibile impostare la display_filterproprietà su un file eseguibile e verrà reindirizzato qualsiasi messaggio aperto tramite l'eseguibile prima di visualizzarlo.

Avrai bisogno di scrivere uno script di programma o di shell che legge ogni riga del messaggio e sostituisce quella con l'intestazione data, o trovare uno script esistente (ce n'è uno qui che il lavoro potrebbe, anche se non sembra come dovrebbe davvero essere necessario per coinvolgere un file temporaneo)



5

Seguendo il consiglio di Gilles, ecco una versione che utilizza un file temporaneo e 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"

Questo è suscettibile agli attacchi di iniezione di codice attraverso Date:un'intestazione non valida : se si entra in una sottostruttura, è necessario convalidare / disinfettare l'input.
galassia

2

Ecco una soluzione 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"

E visualizza LocalDate: in muttrc:

unignore localdate

come si invoca questo?
Janus Troelsen,

@JanusTroelsen, credo che si assegna lo script display_filterin .muttrc.
galassia,

2

set display_filter="/PATH/TO/THIS/PYTHON/FILE"nel tuo .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)

La riga commentata è suscettibile agli attacchi di iniezione di codice attraverso Date:un'intestazione non valida - se si entra in una sottostruttura è necessario convalidare / disinfettare l'input, altrimenti lo script è OK dal punto di vista della sicurezza. Tuttavia, è piuttosto pesante per uno script che viene eseguito su ogni messaggio che navighi.
galassia

2

Soluzione Perl obbligatoria che conserva l'intestazione "Date" mentre si aggiunge un'intestazione "Local-Date" aggiuntiva per contenere la versione localtime:

#!/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;

0

Ho realizzato uno script di shell come descritto alla fine della risposta di Michael che fa il lavoro per me:

#!/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

1
L'analisi delle e-mail è piuttosto complicata. Consiglio di usare uno strumento dedicato come formail(parte del pacchetto procmail ) o reformail(parte di maildrop ) per estrarre l' Date:intestazione esistente e metterne una nuova in atto. Prenditi cura di casi limite come Date:un'intestazione mancante o malformattata .
Gilles 'SO- smetti di essere malvagio' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.