邮件服务器:在 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 或十一月...
我使用 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 或十一月...