请选择段落导航
1.使用Perl处理电子邮件的方法的演化(1)
2.使用Perl处理电子邮件的方法的演化(2)
3.使用Perl处理电子邮件的方法的演化(3)
4.使用Perl处理电子邮件的方法的演化(4)
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"