使用Perl处理电子邮件的方法的演化

每天我都要花费大量的时间在电子邮件相关的工作上,或者通过邮件来和其他工作伙伴联系,或者饶有兴致地分析,
索引,重新组织以及挖掘邮件内容。很自然的,Perl 协助我做这些事情。 
在 CPAN 上有很多现成的模块可以用来处理电子邮件,我们将介绍其中几个主要的。同时我们也将关注由我和 
Richard Clamp,Simon Wistow 以及其他伙伴所致力的 Perl 电子邮件项目(Perl Email Project),
该项目的目标是提供一系列简单的,有效的,精准的邮件处理模块。
邮件消息的处理
我们从一些比较简单的,用来描绘一封单独邮件,提供对邮件头和邮件体的访问,甚至修改它们的信息的那些模块
开始介绍。 
所有的这些模块的曾祖父都是 Mail::Internet ,由 Graham Barr 创建,目前 Mark Overmeer 在维护。
该模块提供了通过数组(元素为字符串行)或者文件句柄来读取信件内容的构造器,并通过它返回一个描述该信件的
 Mail::Internet 对象。在下面的例子中,我们使用变量 $rfc2822 来表示字符串形式的邮件信息内容。 
    my $obj = Mail::Internet->new( [ split /\n/, $rfc2822 ] );
Mail::Internet 从信件中提取构造出一个邮件头对象,并连带邮件体信息。邮件头对象的类为 Mail::Header 。
你可以通过该对象获取或者设置邮件头的信息: 
    my $subject = $obj->head->get("Subject");
    $obj->head->replace("Subject", "New subject");
而读取或者编辑邮件体内容的操作,则可以使用 body 方法: 
    my $old_body = $obj->body;
    $obj->body("Wasn't worth reading anyway.");
到现在为止我还没有提到过任何关于 MIME 的东西。对于简单的任务来说,Mail::Internet 确实非常方便,
不过它并不完全支持对 MIME 的处理。谢天谢地,MIME::Entity 作为一个为 MIME 而考虑设计的 
Mail::Internet 子类,允许你读取 MIME 消息的每一个独立的部分(part): 
    my $num_parts = $obj->parts;
    for (0..$num_parts) {
        my $part = $obj->parts($_);
        ...
    }
如果 Mail::Internet 和 MIME::Entity 都不适合你,你可以试试 Mark Overmeer 自己的 
Mail::Message 模块,该模块是令人印象深刻的 Mail::Box 模块中的一部分。Mail::Message 
是个极富特色的、功能全面的模块,但这些优点并不总意味着褒扬。 
Mail::Message 对象通常都是在 Mail::Box 读取一个电子邮件文件夹的时候,在内部构建的。
当然它也可以通过 read 方法来读取一封信件: 
    $obj = Mail::Message->read($rfc2822);
就像 Mail::Internet 一样,邮件消息被分割为邮件头和邮件体,而与 Mail::Internet 不同的是,
邮件体也是一个对象。我们如此读取邮件头: 
    $obj->head->get("Subject");
或者,如果是 Subject 头信息以及其他常见的邮件头信息,可以如此读取: 
    $obj->subject;
我找不到直接设置头信息的方法,所以最终可能需要这样做: 
    $obj->head->delete($header);
    $obj->head->add($header, $_) for @data;
读取邮件体内容作为字符串形式表达也仅有一点麻烦: 
    $obj->decoded->string
而设置邮件体内容的操作则绝对是恶梦 -- 我们不得不构建一个 Mail::Message::Body 对象来覆盖现有的。 
    $obj->body(Mail::Message::Body->new(data => [split /\n/, $body]));
Mail::Message 处理邮件的时候可能有点慢,也着实难用。它的体系也非常复杂,上面我们所看到的这些操作就
已经用到了 16 种类 (Mail::Address, Mail::Box::Parser, Mail::Box::Parser::Perl, Mail::Message,
 Mail::Message::Body, Mail::Message::Body::File, Mail::Message::Body::Lines,
 Mail::Message::Body::Multipart, Mail::Message::Body::Nested, Mail::Message::Construct, 
Mail::Message::Field, Mail::Message::Field::Fast, Mail::Message::Head, 
Mail::Message::Head::Complete, Mail::Message::Part, 以及 Mail::Reporter)和 4400 多行的代码。
尽管它确实拥有很多功能,我还是傻傻的觉得邮件的分析处理应该更为简洁。所以我坐下来决定自己着手编写尽
可能简洁的邮件处理函数库,结果就有了 Email::Simple 模块,它的交互界面如下所示: 
    my $obj = Email::Simple->new($rfc2822);
    my $subject = $obj->header("Subject");
    $obj->header_set("Subject", "A new subject");
    my $old_body = $obj->body;
    $obj->body_set("A new body\n");
    print $obj->as_string;
它做的事情并不多,但却非常简单和高效。如果你需要 MIME 处理,可以使用它的子类 Email::MIME, 
该类增加了 parts 方法。 
实际上,选择哪一种邮件处理函数库完全取决于你,最终用户,不过并不总是这样的。有许多辅助性的模块,
帮助你在更高的应用层上处理邮件信息的,可能要求你提供特定的邮件表达对象。比如最近的 Mail::ListDetector 
模块(稍后我们将解析),需要传给它的邮件为 Mail::Internet 对象,因为该对象的操作界面(API)是已知的。
而我不想用 Mail::Internet 对象,但我又需要 Mail::ListDetector 的一些功能,那我可以做些什么呢? 
为了让用户也能够有这样的选择,我写了一个用于表达上面各个模块操作界面的抽象层,叫做 Email::Abstract 。
给出上面任何一种类型的对象,我们都可以说: 
     my $subject = Email::Abstract->get_header($obj, "Subject");
     Email::Abstract->set_header($obj, "Subject", "My new subject");
     my $body = Email::Abstract->get_body($obj);
     Email::Abstract->set_body($message, "Hello\nTest message\n");
     $rfc2822 = Email::Abstract->as_string($obj);
Email::Abstract 知道如何在这些主要的邮件表达对象上作相应的操作。它也抽象了构造邮件消息的过程,
并允许你通过类方法 cast 来改变邮件消息对象的操作界面: 
    my $obj = Email::Abstract->cast($rfc2822, "Mail::Internet");
my $mm = Email::Abstract->cast($obj, "Mail::Message"); 这样使得模块的作者得以使用“接口预先未知
(interface-agnostic)”的方式来撰写邮件处理函数库。我很感谢 Michael Stevens 立即在 
Mail::ListDetector 中使用了 Email::Abstract 。现在我可以将 Email::Simple 对象传递给 
Mail::ListDetector 了,而且它工作的非常好。 
Email::Abstract 也给了我们对上面所有这些模块作基准测试(benchmarks)的机会。这里是我使用的测试代码: 
    use Email::Abstract;

								
共4页 首页 上一页 [1] [2] [3] [4下一页 尾页>
上一篇: LWP 与 WEB 的基本使用
下一篇:
字母检索 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z