当前位置: 首页 > 知识库问答 >
问题:

Perl使用MIME::解析器解析没有部件的电子邮件正文

司马祖鹤
2023-03-14

我有一个perl脚本,使用MIME::E邮件来解析从stdin收到的电子邮件,但它不适用于没有部件的电子邮件。我没有能力在电子邮件发送前修改它们。

我希望能够识别电子邮件的重要部分,不管它是超文本标记语言还是文本,并将其存储在缓冲区中以便以后处理。这些电子邮件中的许多来自自动生成的邮件列表。

有时,它们似乎只有一个“内容类型”:没有边界的标题。

MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit

其他时候,它们有多个文本/普通部分,其中一个是电子邮件的正文,另一个是签名。

在这之后还有一些其他的标题行,但是主体只是显示而没有任何边界标记。

这是我两年前的一篇文章,展示了我是如何最终弄明白如何用email::MIME和multipart/mixed with subparts解析电子邮件的

use strict;
use MIME::Parser;
use MIME::Entity;
use Email::MIME;
use Email::Simple;
my $parser = MIME::Parser->new;
$parser->extract_uuencode(1);
$parser->extract_nested_messages(1);
$parser->output_to_core(1);
my $buf;
while(<STDIN> ){
        $buf .= $_; 
}

my $entity = $parser->parse_data($buf);

$entity->dump_skeleton;
my $num_parts = $entity->parts;
for (my $i=0; $i < $num_parts; $i++) {
    my $part = $entity->parts($i);
    my $content_type = $part->mime_type;
    my $body = $part->as_string;

    print "body: $body\n";
}

正文永远不会打印出来。仅来自dump_skeleton的以下内容:

Content-type: text/plain
Effective-type: text/plain
Body-file: NONE
Subject: Security update 

我真的希望能够修改我现有的脚本(如前一篇stackexchange帖子所示),以便能够打印这样没有任何边界的电子邮件。

这是糟糕的格式吗?我一直无法找到任何库的例子,这些库可以用来可靠地打印电子邮件的正文、主题和其他基本标题,而不需要复杂的步骤来逐部分分析整个邮件。

我知道mimeexplode可以做到,但我不知道怎么做。我需要将邮件正文存储在一个缓冲区中进行操作,因此使用像mimeexplode这样的命令行程序将是一种迂回的方式。

共有1个答案

刘博文
2023-03-14

我还不完全清楚你想要实现什么,因为你只发布代码,但没有足够详细的意图。但您使用的是部分来检查消息,该消息有明确的文档记录,以返回多部分/*或类似部分(即消息/rfc822),并且不处理单个消息:

... 返回所有子部分的数组,如果没有子部分,则返回空数组(例如,如果这是单部分消息,或退化的多部分消息)。在标量上下文中,这将返回零件的数量。

如果你只想得到所有的部分,包括独立的部分(即一个不属于任何部分的单一实体),只需使用parts_DFS,如下例所示,它为所有具有非零主体的实体打印主体:

use MIME::Parser;
my $parser = MIME::Parser->new;
my $entity = $parser->parse(\*STDIN);
for my $part ($entity->parts_DFS) {
    defined(my $body = $part->bodyhandle) or next; # has no body, likely multipart or similar
    print "body: ".$body->as_string."\n";
}

编辑:鉴于你已经更新了问题,你不是在寻找所有部分,而是在寻找正文部分。确定实际的主要部分并不容易,但您可以尝试使用第一个内联的text/*部分。这可能看起来像这样:

use MIME::Parser;
my $parser = MIME::Parser->new;
my $entity = $parser->parse(\*STDIN);
for my $part ($entity->parts_DFS) {
    defined(my $body = $part->bodyhandle) or next; # has no body, likely multipart or similar
    if (my $disp = $part->head->get('content-disposition')) {
        next if $disp !~ m{inline}i;
    }
    print "body: ".$body->as_string."\n";
    last;
}
 类似资料:
  • 我正在寻找一种方法来解析多部分/可选电子邮件的正文部分。目前,我有一个使用Email::Mime模块的perl脚本,它可以正确解析text/plain和text/html。尽管我的问题是,当我解析一个多部分/可选电子邮件时,$part- PERL代码 来源

  • 问题内容: 是否有人熟悉Java库,该库有助于解析以下电子邮件的字段(日期,主题,从,到)? 问题答案: JavaMail是一个Oracle库,它在javax.mail软件包中提供邮件服务和与邮件相关的服务(例如解析常规邮件和MIME邮件)。另外,Apache有一个用于处理邮件的Commons Email 库。 在JavaMail API中,解析包含电子邮件消息的字符串(可能是或可能不是明确的MI

  • 问题内容: 我正在编写一个Python脚本来处理Procmail返回的电子邮件。如该问题中所建议,我正在使用以下Procmail配置: 我的process_mail.py脚本正在通过stdin接收电子邮件,如下所示: 我正在尝试以这种方式解析消息: 我想获取诸如“发件人”,“收件人”和“主题”之类的消息字段。但是,消息对象不包含任何这些字段。 我究竟做错了什么? 问题答案: 您必须确保这些行不会意

  • 我已经尝试了整整一周使用antlr构建一个语法,允许我解析电子邮件消息。 我的目标不是将整个电子邮件彻底解析为令牌,而是将其分解为相关部分。 这是我必须处理的文档格式。描述不属于消息一部分的内联注释: 我面临的问题如下: 我没有想出一个好方法来跳过消息开头的文本,并在找到标记后才开始应用解析规则。截面类型1 捕获节开始和句子标记之间节内的所有文本 在SECTION\u结束标记之后,忽略后面的所有文

  • Im正在尝试分析outlook中的.msg文件以获取MIME内容,以便将该文件另存为EML。我正在使用Exchange Web服务在EML通过Exchange服务器上的日志收件箱时保存EML,但有些电子邮件需要在事后通过outlook add in保存,不过将它们变成EML/MIME格式似乎比较困难。 任何洞察力都是非常有用的。

  • 我已经实现了一个读取电子邮件文件的功能。如果文件有附件,则返回附件名称。现在我使用Javamail库来解析电子邮件文件。这是我的代码。 它工作得很好,但是当电子邮件文件具有7bit Content-Transfer-Encoding时,BodyPart.getFileName()会产生NullPointerException。当电子邮件是7bit内容传输编码时,有没有办法获得附件名称?对不起,我的