邮件服务器:在 Maildir 文件上将 "Date:" header 日期年份从 "yy" 转换为 "yyyy"

Mailserver: convert "Date:" header date year from "yy" to "yyyy" on Maildir files

我使用 SMTP 和 IMAP 的 Postfix 和 Dovecot。它们在最新的 CentOS 7 可用版本上,消息以 Maildir 格式存储。

我们已经和Google达成了协议,我们的邮箱会很快转移给他们。

自上世纪九十年代以来,我们就有了这种邮件服务器基础设施。因此,一些消息具有旧的 "Date" header 格式,年份字段为 "yy"。由于 Google 要求它是 "yyyy",他们告诉我,在 Imap 导入到他们的云之前,我需要在每条需要的消息上转换此信息。这遵循 RFC2060 和 3501。

这是一所大学,这些旧消息包含应保留的研究数据。

这是一个例子:

日期:17 年 4 月 20 日,星期四 15:45:15 +0000

应该是:

日期:2017 年 4 月 20 日,星期四 15:45:15 +0000

我一直在寻找脚本来执行此修复,方法是保留 header、日期,并且只修复每个需要的文件中的年份,而不更改文件时间戳(一些邮件客户端将其用作排序方法)。但是我还没有找到。

那么,有没有人可以帮助我?

谢谢。

您可以使用touch命令恢复文件修改后的时间戳。 假设文件名是input_file.

orinal_time=$(stat -c "%y"input_file)  #store the orignal timestamp

#do yy->yyyy conversion, this is just example. key here is %Y for conversion
date -d"Thu, 20 Apr 17 15:45:15 +0000" "+%a,%d %b %Y %T %z" >input_file.tmp && mv input_file.tmp input_file

#restore the orignal timestamp

 touch -d "$orinal_time" input_file

您不能在不更改时间戳的情况下修改文件;但您可以保留原始时间戳并使用 touch 将其应用回来,如单独的答案中所示。

找到损坏的 Date: headers 也不是太难,特别是如果消息是由一小组客户端发送的,这些客户端都以相同的方式统一损坏。但是,您可以在野外发现很多很多不同的 RFC 违规行为,因此可能会执行测试 运行 提取所有 Date: headers ,在您继续之前,它们不是预期的格式之一有修改。

find Maildir -type f -exec sh -c 'for f; do
     sed -n "/^$/q;/^[Dd][Aa][Tt][Ee]:/p" "$f"; done' _ {} +

-exec ... + 是一个模仿 xargs 的 GNU 扩展,它将尽可能多的找到的文件作为参数传递给由 -exec 启动的进程。

您可以在 [Dd][Aa][Tt][Ee]: 之后扩充正则表达式以搜索匹配特定错误 Date: 格式的日期 headers。

如果您可以验证所有错误消息都与您的示例相似,

sed -i '1,/^$/!b;s/^\([Dd][Aa][Tt][Ee]: [A-Z][a-z][a-z], [ 0-3][0-9] [A-Z][a-z][a-z] \)\([7-9][0-9] \)/9/;s/^\([Dd][Aa][Tt][Ee]: [A-Z][a-z][a-z], [ 0-3][0-9] [A-Z][a-z][a-z] \)\([01][0-9] \)/0/'

可能至少是修复错误消息的良好开端。

将所有内容放在一起,最终脚本可能类似于

find Maildir -type f -exec sh -c 'for f; do
        timestamp=$(stat -c "%y" "$f")
        sed -i "1,/^$/!b;s/^\(Date: [A-Z][a-z][a-z], [ 0-3][0-9] [A-Z][a-z][a-z] \)\([7-9][0-9] \)/9/;s/^\(Date: [A-Z][a-z][a-z], [ 0-3][0-9] [A-Z][a-z][a-z] \)\([01][0-9] \)/0/" "$f"
        touch -d "$timestamp" "$f"
done' _ {} +

我的预测是,如果您需要处理来自 Lotus、Yahoo! 和微软。最麻烦的可能是那些被错误地本地化的 - 你可能会猜到 Märtz 是三月,但祝你好运 marraskuu 或十一月...