Como configurar o mutt para exibir o cabeçalho da data no meu fuso horário local no pager?

13

Quando visualizo uma mensagem no pager mutt, a hora é exibida no cabeçalho Data no UTC, e não no meu fuso horário local. A exibição do índice exibe a hora local corretamente. Encontrei essa postagem antiga da lista de discussão que descreve como obter o horário local para exibição na barra de status na parte inferior da tela, mas isso ainda não "corrige" o horário no cabeçalho Data na parte superior da tela. Existe alguma maneira de fazer o pager converter a hora do cabeçalho da data para a hora local?

Ben Williams
fonte

Respostas:

3

No seu, .muttrcadicione a seguinte linha:

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

Isso mudará o Date:cabeçalho da mensagem (apenas para exibição) para o fuso horário local se o cabeçalho contiver uma data formatada por RFC válida. Se o formato da data fornecido estiver incorreto (afinal, estamos lidando com entradas não confiáveis ​​do usuário), ele será preservado. Para combater uma possível tentativa de injetar o código do shell no cabeçalho, o sedpadrão implementa uma lista de permissões baseada no RFC 5322 (este RFC define o formato do Date:campo).

Observe que o muttlimite da linha de comando não deve ter mais do que 255 caracteres; portanto, otimizei o sedcomando original que tinha uma lista de permissões mais rígida para caber em 255 bytes. Se você planeja fazer outras coisas com a mensagem, o sedcomando completo que você pode colocar em um 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"
galáxia
fonte
Existe a possibilidade de fazer isso funcionar no macOS? Eu gostaria de incluir isso no meu filter.sedarquivo. Obrigado!
Philipp L.
Não há, a menos que você esteja usando o GNU sed (por exemplo, via Homebrew) - os sedcomandos acima dependem do emodificador para o scomando. Esse modificador é uma extensão GNU e o macOS'es sedé o BSD.
galaxy
Responder por @viric é bom. Não há necessidade de alterar a mensagem via filtro.
Jangid 16/07/19
@ Wangid, leia a solicitação original e solicita especificamente a exibição adequada de uma zona local na parte superior da página e não na linha de status.
galaxy
@galaxy Oh! sim. Só notei isso. Corrigir.
Jangid 17/07
11

A formatação no índice é controlada pela index_formatconfiguração - é gerada pelo mutt. O Datecabeçalho não é controlado pelo mutt, é um cabeçalho incluído na mensagem que apenas é exibida. Se ele mostra a hora UTC, é porque o servidor de envio decidiu usar UTC ao gerar o cabeçalho. A única maneira de alterá-lo é realmente alterar a própria mensagem, quando você a recebe ou quando a exibe.

Alterá-lo da forma que ele significa significa adicionar um filtro ao seu agente de entrega de correio, mas ele precisa ser sofisticado o suficiente para analisar o Datecabeçalho existente e reescrevê-lo. É quase certamente melhor apenas reformar a mensagem quando você olha para ela. Você pode definir a display_filterpropriedade como um arquivo executável e canalizará qualquer mensagem que você abrir através do executável antes de exibi-lo.

Você precisará escrever um programa ou script de shell que leia cada linha da mensagem e substitua a linha pelo cabeçalho Date ou encontre um script existente (há um aqui que pode funcionar, embora não pareça realmente necessário envolver um arquivo temporário)

Michael Mrozek
fonte
5

Seguindo o conselho de Gilles, aqui está uma versão que usa um arquivo temporário 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"
Ben Williams
fonte
Isso é suscetível a ataques de injeção de código por meio de um Date:cabeçalho mal formado - se você entrar em um subshell, precisará validar / higienizar a entrada.
galáxia
2

Aqui está uma solução 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 exiba LocalDate: no muttrc:

unignore localdate
fraff
fonte
como você invoca isso?
Janus Troelsen
@JanusTroelsen, acredito que você atribuiu o script a display_filterin .muttrc.
galaxy.
2

set display_filter="/PATH/TO/THIS/PYTHON/FILE"no seu .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
fonte
A linha comentada é suscetível a ataques de injeção de código por meio de um Date:cabeçalho malformado - se você entrar em um subshell, precisará validar / higienizar a entrada, caso contrário, o script está OK do ponto de vista de segurança. No entanto, é bastante pesado para um script executado em todas as mensagens que você navega.
galaxy.
2

Solução Perl obrigatória que preserva o cabeçalho "Data" ao adicionar um cabeçalho "Data local" extra para conter a versão em horário local:

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

Eu criei um script de shell, conforme descrito no final da resposta de Michael, que faz o trabalho para mim:

#!/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
fonte
1
A análise de emails é bastante complicada. Eu recomendo usar uma ferramenta dedicada como formail(parte do pacote procmail ) ou reformail(parte do maildrop ) para extrair o Date:cabeçalho existente e colocar um novo no lugar. Cuide de casos extremos, como um Date:cabeçalho ausente ou malformado .
Gilles 'SO- stop be evil'