Как настроить Mutt для отображения заголовка даты в моем местном часовом поясе в пейджере?

13

Когда я просматриваю сообщение в пейджере Mutt, отображается время в заголовке даты в формате UTC, а не мой местный часовой пояс. В индексном представлении отображается местное время правильно. Я нашел этот старый пост в списке рассылки, который описывает, как заставить отображать местное время в строке состояния в нижней части экрана, но это все еще не «фиксирует» время в заголовке «Дата» в верхней части экрана. Есть ли способ заставить пейджер конвертировать время заголовка даты в местное время?

Бен Уильямс
источник

Ответы:

3

В вашем .muttrcдобавьте следующую строку:

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

Это изменит Date:заголовок в сообщении (только для отображения) на ваш местный часовой пояс, если заголовок содержал действительную дату в формате RFC. Если предоставленный формат даты был неправильным (мы имеем дело с ненадежным пользовательским вводом в конце концов), он будет сохранен. Для борьбы с возможной попыткой ввести код оболочки через заголовок sedшаблон реализует белый список на основе RFC 5322 (этот RFC определяет формат Date:поля).

Обратите внимание, что muttдлина командной строки не должна превышать 255 символов, поэтому я оптимизировал исходную sedкоманду с более строгим белым списком, чтобы он умещался в 255 байтов. Если вы планируете делать с сообщением другие вещи, то полная sedкоманда, которую вы можете поместить в скрипт:

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"
галактика
источник
Есть ли возможность заставить это работать на macOS? Я хотел бы включить это в мой filter.sedфайл. Благодарность!
Филипп Л.
Нет, если вы не используете GNU sed (например, через Homebrew) - вышеприведенные sedкоманды зависят от eмодификатора sкоманды. Этот модификатор является расширением GNU, а macOS sed- BSD.
галактика
Ответ @viric это хорошо. Нет необходимости менять сообщение через фильтр.
Джангид
@Jangid, пожалуйста, прочитайте исходный запрос, и он специально запрашивает правильное отображение локальной зоны в верхней части страницы, а не в строке состояния.
галактика
@ galaxy Ой! да. Просто заметил это. Верный.
Джангид
11

Форматирование в индексе контролируется index_formatнастройкой - оно генерируется Mutt. DateЗаголовок не контролируется собачонка, это заголовок , который включается с сообщением , что только получает отображается. Если он показывает время UTC, это потому, что отправляющий сервер решил использовать UTC при создании заголовка. Единственный способ изменить его - это изменить само сообщение, когда вы его получаете или просматриваете.

Чтобы изменить его, нужно добавить фильтр к агенту доставки почты, но он должен быть достаточно сложным, чтобы проанализировать существующий Dateзаголовок и переписать его. Почти наверняка лучше, чтобы mutt переформатировал сообщение, когда вы на него смотрите. Вы можете установить для display_filterсвойства исполняемый файл, и он будет передавать любое сообщение, открытое вами, через исполняемый файл перед его отображением.

Вам нужно написать сценарий программы или оболочки , который считывает каждую строку сообщения и заменяет один с заголовком Date, или найти существующий скрипт (есть один здесь , что может работать, хотя это не кажется , что это действительно надо нужно будет задействовать временный файл)

Михаил Мрозек
источник
7

http://www.mail-archive.com/mutt-users@mutt.org/msg44341.html

Это предлагает использовать 'pager_format', чтобы он отображал дату письма в местном часовом поясе:

set pager_format = "% 4C% Z% [!% b% e при% I:% M% p]% .20n% s% * - (% P)"

viric
источник
Это работает очень хорошо, также для index_format.
Фил
5

Принимая совет Жиля, вот версия, которая использует временный файл и 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"
Бен Уильямс
источник
Это подвержено атакам внедрения кода через искаженный Date:заголовок - если вы заходите в подоболочку, вам нужно проверить / санировать ввод.
галактика
2

Вот решение 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"

И отобразить LocalDate: в muttrc:

unignore localdate
fraff
источник
как вы вызываете это?
Янус Троелсен
@JanusTroelsen, я полагаю, что вы назначаете сценарий для display_filterin .muttrc.
Галактика
2

set display_filter="/PATH/TO/THIS/PYTHON/FILE"в вашем .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)
Янус Троелсен
источник
Закомментированная строка подвержена атакам внедрения кода через искаженный Date:заголовок - если вы заходите в подоболочку, вам нужно проверить / дезинфицировать вход, иначе сценарий в порядке с точки зрения безопасности. Однако это довольно тяжело для сценария, который запускается для каждого просматриваемого сообщения.
Галактика
2

Обязательное решение Perl, которое сохраняет заголовок «Date» при добавлении дополнительного заголовка «Local-Date», чтобы содержать версию 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;
hyperair
источник
0

Я сделал сценарий оболочки, как описано в конце ответа Майкла, который делает эту работу за меня:

#!/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
Разбор электронных писем довольно сложно. Я рекомендую использовать специальный инструмент, такой как formail(часть пакета procmail ) или reformail(часть maildrop ), чтобы извлечь существующий Date:заголовок и поставить новый на место. Позаботьтесь о крайних случаях, таких как отсутствующий или неправильно отформатированный Date:заголовок.
Жиль "ТАК - перестань быть злым"