苹果邮件的.emlx数据结构文档(用于转换目的)?

8
这似乎是一颗稀有的宝石:如何找到关于Apple Mail的.emlx文件结构(以及它们的部分变体和目录结构含义)的文档。文档似乎不存在于Apple的网站上,也无法通过Google找到任何合理的提及。
这样做的目的是创建一个bash/ruby/python/插入脚本语言的脚本,将这些文件的混乱转换为可用/易弯曲的东西,比如Maildir或Mbox。最终目标是将用户的/Library/Mail存储的快照迁移到现有的Dovecot设置中,该设置使用Maildir的形式。
是的,我知道这个程序,但它并没有解决我想要的解决方案。手动转换20个邮箱并将它们手动插入现有安装中需要更多的时间,而只是编写一个将消息消化成其他内容然后自动存储到应该存储的位置的脚本会更加节省时间。别管还有可能有半打以上的用户需要执行此过程。所以编写脚本值得我的时间。
请在待删除的重复问题上投票关闭,而不是在此问题上投票关闭。出现Chrome浏览器偶尔发布故障的情况。
跟进:看起来这种格式确实没有记录,大多数来源都是通过逆向工程获得的。如果我有时间,我会尝试自己做到这一点;如果成功,我将发布第二次跟进以介绍我的发现详情。

https://gist.github.com/karlcow/5276813 似乎包含一些未知来源的Python代码,实现了以下答案中大致的内容。 - tripleee
5个回答

4

有关emlx格式的更多信息。

邮件消息由以下几部分组成:

  • 第一行是消息的字节计数
  • 消息的MIME转储
  • 一个XML属性列表

XML属性列表包含某些代码,例如

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>date-sent</key>
        <real>1362211252</real>
        <key>flags</key>
        <integer>8590195713</integer>
        <key>original-mailbox</key>
        <string>imap://****@127.0.0.1:143/mail/2013/03</string>
        <key>remote-id</key>
        <string>252</string>
        <key>subject</key>
        <string>Re: Foobar</string>
</dict>

这些标志被jwz描述为一个30位整数,与此处相同,涉及IT技术相关内容。

0      read                      1 << 0
1      deleted                   1 << 1
2      answered                  1 << 2
3      encrypted                 1 << 3
4      flagged                   1 << 4
5      recent                    1 << 5
6      draft                     1 << 6
7      initial (no longer used)  1 << 7
8      forwarded                 1 << 8
9      redirected                1 << 9
10-15  attachment count          3F << 10 (6 bits)
16-22  priority level            7F << 16 (7 bits)
23     signed                    1 << 23
24     is junk                   1 << 24
25     is not junk               1 << 25
26-28  font size delta           7 << 26 (3 bits)
29     junk mail level recorded  1 << 29
30     highlight text in toc     1 << 30
31     (unused)

发送一条简单的消息并删除一些细节,以便您可以查看emlx文件的完整数据结构。

875       
X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on ******.*********.***
X-Spam-Level: 
X-Spam-Status: No, score=-3.2 required=4.2 tests=BAYES_00,RP_MATCHES_RCVD,
        SPF_PASS,TVD_SPACE_RATIO autolearn=ham version=3.3.2
Received: from [127.0.0.1] (******.*********.*** [***.**.**.**])
        by ******.*********.*** (8.14.5/8.14.5) with ESMTP id r2TN8m4U099571
        for <****@*********.***>; Fri, 29 Mar 2013 19:08:48 -0400 (EDT)
        (envelope-from ****@*********.***)
Subject: very simple
From: Karl Dubost <****@*********.***>
Content-Type: text/plain; charset=us-ascii
Message-Id: <4E83618E-BB56-404F-8595-87352648ADC7@*********.***>
Date: Fri, 29 Mar 2013 19:09:06 -0400
To: Karl Dubost <****@*********.***>
Content-Transfer-Encoding: 7bit
Mime-Version: 1.0 (Apple Message framework v1283)
X-Mailer: Apple Mail (2.1283)

message Foo
-- 
Karl Dubost
http://www.la-grange.net/karl/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>date-sent</key>
        <real>1364598546</real>
        <key>flags</key>
        <integer>8590195713</integer>
        <key>original-mailbox</key>
        <string>imap://********@127.0.0.1:11143/mail/2013/03</string>
        <key>remote-id</key>
        <string>41147</string>
        <key>subject</key>
        <string>very simple</string>
</dict>
</plist>

你好Karl!- 感谢你在这方面的工作 - 但我一直无法读取emlx文件中的plist部分。 - DrLou

3
这是一个用Ruby编写的emlx2mbox转换器:Mailbox Converter
我认为它并没有依据规范的任何文档编写,但经历了多次更新,因此希望能够处理格式中至少的一些怪异情况。源代码大约有250行,看起来易读且有很好的注释。

虽然这不是关于数据结构的文档,但至少它是功能性的源代码,对于朝着正确方向迈出的一步加1。 :) - Avery Payne
代码没有产生任何可用的输出?啊!我的眼睛!护目镜!它们什么也做不了!!! - Avery Payne
我怀疑没有关于emlx的公共文档,因为我见过的每个emlx工具都表明它们是通过逆向工程格式来实现的。如果这个rb不起作用,那么我猜你有荣幸制作一个更好的版本。 :) - Matt G
看起来我就是在那里。但是,谢谢您至少提供了一个尝试解决这个问题的工具。从我所看到的内容来看,有一个数字指示器(大小?),然后是消息,最后是一些XML标记。我猜测修剪XML,丢弃数字,保留剩余部分可能会解决问题。 - Avery Payne

2
截至2020年,Python拥有一个轻量级的emlx库(http://github.com/mikez/emlx)。
pip install emlx

然后

>>> import emlx
>>> m = emlx.read("12345.emlx")

>>> m.headers
{'Subject': 'Re: Emlx library ✉️',
 'From': 'Michael <michael@example.com>',
 'Date': 'Thu, 30 Jan 2020 20:25:43 +0100',
 'Content-Type': 'text/plain; charset=utf-8',
 ...}
>>> m.headers['Subject']
'Re: Emlx library ✉️'

>>> m.plist
{'color': '000000',
 'conversation-id': 12345,
 'date-last-viewed': 1580423184,
 'flags': {...},
 ...}

>>> m.flags
{'read': True, 'answered': True, 'attachment_count': 2}

1
我正在使用mailcore2来解析.eml消息。为了使它能够与.emlx一起使用,我只需要删除第一行(包含一个数字)。消息本身配备了消息长度,因此无需删除末尾的XML块。
以下是我在objective-c/cocoa中的操作方式(MCOMessageParser来自mailcore2框架):
-(Documents *)ParseEmlMessageforPath: (NSString*)fullpath filename:(NSString*)filename{
NSLog(@"fullpath = %@", fullpath);
NSError * error;
error = nil;
NSData *fileContents = [NSData dataWithContentsOfFile:fullpath options:NSDataReadingMappedIfSafe error:&error];
if (error) { 
     [[NSApplication sharedApplication] presentError:error];
}
MCOMessageParser * parser;
if (fileContents) {
    if ([[fullpath pathExtension] isEqualToString:@"emlx"]) {
        NSData * linefeed = [(NSString*)@"\n" dataUsingEncoding:NSUTF8StringEncoding ];
        NSInteger filelength = [fileContents length];
        NSRange  xx = NSMakeRange(0, 20); 
        NSRange pos = [fileContents rangeOfData:linefeed options:0 range:xx] ;
        if (pos.location != NSNotFound) {
            NSData *subcontent = [fileContents subdataWithRange:(NSRange){pos.location+1, filelength-(pos.location)-1}];
            parser = [MCOMessageParser messageParserWithData:subcontent];
        } else {
            return nil;
        }

    } else {
        parser = [MCOMessageParser messageParserWithData:fileContents];

    }

然后你就完成了...


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接