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

my $message = do { local $/; ; }; my @classes = qw(Email::MIME Email::Simple MIME::Entity Mail::Internet Mail::Message); eval "require $_" or die $@ for @classes; use Benchmark; my %h; for my $class (@classes) { $h{$class} = sub { my $obj = Email::Abstract->cast($message, $class); Email::Abstract->get_header($obj, "Subject"); Email::Abstract->get_body($obj); Email::Abstract->set_header($obj, "Subject", "New Subject"); Email::Abstract->set_body($obj, "A completely new body"); Email::Abstract->as_string($obj); } } timethese(1000, \%h); __DATA__ ...
我把一封短小的邮件放到 DATA 部分中,并运行相同的操作一千次:构造一个新的消息对象,读取邮件头,
读取邮件体,并将消息内容作为字符串返回。 
    Benchmark: timing 1000 iterations of Email::MIME, Email::Simple, 
    MIME::Entity, Mail::Internet, Mail::Message...
    Email::MIME: 10 wallclock secs ( 7.97 usr +  0.24 sys =  8.21 CPU) 
        @ 121.80/s (n=1000)
    Email::Simple:  9 wallclock secs ( 7.49 usr +  0.05 sys =  7.54 CPU) 
        @ 132.63/s (n=1000)
    MIME::Entity: 33 wallclock secs (23.76 usr +  0.35 sys = 24.11 CPU) 
        @ 41.48/s (n=1000)
    Mail::Internet: 24 wallclock secs (17.34 usr +  0.30 sys = 17.64 CPU) 
        @ 56.69/s (n=1000)
    Mail::Message: 20 wallclock secs (17.12 usr +  0.27 sys = 17.39 CPU) 
        @ 57.50/s (n=1000)
Perl 电子邮件项目确实是成功的:Email::MIME 和 Email::Simple 的运行速度差不多是对手的两倍。
然而,我们要强调一点,这里所做的测试都是非常低级的,如果你要做任何比这里看到的更加复杂的操作,
你该考虑哪些老的 Mail:: 模块。 
邮箱的处理
对于单独信件的处理已经谈了很多了,让我们来看看对一组邮件或者存放邮件的文件夹该如何处理。
我们提到过 Mail::Box ,它绝对是处理邮件文件夹的老大,它支持本地和远程的文件夹处理,
可以编辑文件夹,以及作相应的排序操作等等。要使用它,我们首先需要 Mail::Box::Manager 模块,
它是用来构建 Mail::Box 对象的工厂对象。 
    use Mail::Box::Manager
    my $mgr = Mail::Box::Manager->new;
接下来,我们通过管理器来打开文件夹: 
    my $folder = $mgr->open(folder => $folder_file);
而现在,我们可以获取各个独立的邮件表达对象(Mail::Message): 
    for ($folder->messages) {
        print $_->subject,"\n";
    }
与此最为相近的,我喜欢用的邮箱管理器还是 Mail::Util 的 read_mbox 函数。把 unix
mbox 文件路径传递给它,然后返回一系列的匿名数组,每个匿名数组都表示一个邮件消息,其元素为该消息的每一行。
如此一来,它非常适合 Mail::Internet->new 或者相近的: 
    for (read_mbox($folder_file)) {
        my $obj = Mail::Internet->new($_);
        print $_->head->get("Subject"),"\n";
    }
这两种做法都非常容易,不过似乎在 Mail::Util 的简洁性和 Mail::Box 的功能上还有些简化的余地,
于是电子邮件项目再次停滞下来,这次的焦点集中在 Email::Folder 和 Email::LocalDelivery 上面。 
Email::Folder 可以处理 mbox 和 maildir 格式的邮件文件夹,以及计划中更多其他格式,并且它有非
常简洁的操作界面: 
    my $folder = Email::Folder->new($folder_file);
    for ($folder->messages) {
        print $_->header("Subject"),"\n";
    }
默认情况,它返回一系列 Email::Simple 对象用以表达每封邮件,不过这可以通过派生一个子类来改变。
例如,如果我们想要原始的 RFC2822 格式的字符串,我们可以这样做: 
    package Email::Folder::Raw; use base 'Email::Folder';
    sub bless_message { my ($self, $rfc2822) = @_; return $rfc2822; }
可能将来我们不用再派生一个子类,然后 bless_message ,而改用 Email::Abstract->cast 来更容易的
改变对邮件消息的表达方式。 
处理文件夹的另一方面就是如何写数据了。或者说如何本地投递。Email::LocalDelivery 模块的出现是为了
辅助 Email::Filter 。问题比听起来要更难些,因为它必须处理锁定,跳开邮件体,以及由 mailbox 和 
maildir 等不同格式而引发的问题。而 LocalDelivery 则通过简单的界面把所有这些都隐藏起来: 
    Email::LocalDelivery->deliver($rfc2822, @mailboxes);
Email::LocalDelivery 和 Email::Folder 都使用了 Email::FolderType 模块来帮助确定是哪种类型的
邮件文件夹(通过文件名来判断)。 
邮件地址的处理
我们再次从抽象层面回到低级的处理,有大量的模块可用于对邮件地址的处理。我很喜欢老的 Mail::Address 模块。
邮件地址可以分割为各种字段,诸如:实际的邮件地址,名称短语,注释信息。例如: 
    Example user  (Not a real user)
Mail::Address 解析这些邮件地址,并将名称短语和注释分离出来,以便获取各个独立的部分: 
    for (Mail::Address->parse($from_line)) {
        print $_->name, "\t", $_->address, "\n";
    }
不幸的是,和其他很多邮件模块一样,并不真的那么有用。 
    my ($addr) = Mail::Address->parse('"eBay, Inc." ');
    print $addr->name # Inc. eBay
得到的结果仍然难以让人接受,虽然它比之间的版本所返回的 "Inc Ebay" 要好些。于是 Casey West 加入
我们并创造了 Email::Address 模块。它和 Mail::Address 使用一致的交互界面,并且运行地更加快速,
差不多两到三倍。(译注:上面的例子中,Email::Address 返回 "eBay, Inc." 。看来在作者眼里,
Mail::Address 的作者画蛇添足了。) 
还有一件我们经常需要做的事情就是校验邮件地址是否合法。比如,某个用户在站点上注册,我们就需要对他
所提供的邮件地址是否能够接收邮件作检查。Email::Valid 模块是在我们这帮叛逆的人冲进来之前,就已有的 
Email:: 名字空间的原住民,这个模块就是用来做这件事情的。在它最简约的用法中,我们可以说: 
    if (not Email::Valid->address('test@example.com')) {
        die "Not a valid address"

								
共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