当我在寻呼机中查看消息时,杂音将在UTC的Date标头中显示时间,而不是本地时区。索引视图正确显示本地时间。我发现这条旧的邮件列表帖子描述了如何获取本地时间以显示在屏幕底部的状态栏中,但这仍然不能“固定”时间在屏幕顶部的Date标头中。有什么方法可以使寻呼机将Date标头时间转换为本地时间?
当我在寻呼机中查看消息时,杂音将在UTC的Date标头中显示时间,而不是本地时区。索引视图正确显示本地时间。我发现这条旧的邮件列表帖子描述了如何获取本地时间以显示在屏幕底部的状态栏中,但这仍然不能“固定”时间在屏幕顶部的Date标头中。有什么方法可以使寻呼机将Date标头时间转换为本地时间?
Answers:
在您.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"
sed
命令依赖于命令的e
修饰符s
。该修饰符是GNU扩展,而macOS sed
是BSD 扩展。
索引中的格式由index_format
设置控制-由mutt生成。该Date
头不受狗控制,它包括与只是获取显示的消息标题。如果显示UTC时间,是因为发送服务器在生成标头时决定使用UTC。更改消息的唯一方法是实际更改消息本身,无论是在收到消息时还是在查看消息时。
对其进行更改意味着向您的邮件传递代理添加筛选器,但是它必须足够复杂以解析现有的Date
标头并重写它。几乎可以肯定的是,当您查看信息时,仅将信息重新格式化即可。您可以将display_filter
属性设置为可执行文件,它将在显示可执行文件之前通过您的可执行文件通过管道发送任何消息。
您需要编写一个程序或Shell脚本来读取消息的每一行,并用Date标头替换该行,或者找到一个现有的脚本(这里可能有一个可行的脚本,尽管看起来似乎不应该如此)需要包含一个临时文件)
http://www.mail-archive.com/mutt-users@mutt.org/msg44341.html
这建议使用“ pager_format”,使其在本地时区显示字母日期:
设置pager_format =“%4C%Z%[!%b%e at%I:%M%p]%.20n%s%*-(%P)”
根据Gilles的建议,这是一个使用临时文件和的版本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:
标头进行代码注入攻击-如果您进入子外壳,则需要验证/清除输入。
这是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"
并在muttrc中显示LocalDate ::
unignore localdate
display_filter
中.muttrc
。
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:
标头的代码注入攻击-如果您进入子外壳,则需要验证/清除输入,否则从安全角度考虑,脚本是可以的。但是,对于在您浏览的每条消息上运行的脚本来说,它都是很沉重的。
我按照Michael回答结尾处的描述制作了一个shell脚本,为我完成了这项工作:
#!/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
formail
(例如procmail软件包的reformail
一部分)或(maildrop的一部分)提取现有的Date:
标头,然后放置一个新的标头。注意边缘情况,例如Date:
标头丢失或格式错误。
filter.sed
文件中。谢谢!