如何使用 Email::MIME 更改一个部分的正文?或者:body_set 对谁起作用?

Posted

技术标签:

【中文标题】如何使用 Email::MIME 更改一个部分的正文?或者:body_set 对谁起作用?【英文标题】:How to change the body of one part using Email::MIME? Or: Who does body_set work? 【发布时间】:2014-03-28 22:56:51 【问题描述】:

我正在尝试使用 Email::MIMEs (1.926) walk_partsbody_set 更改多部分 MIME 电子邮件中某个部分的正文。

更改存在,但是在发送邮件时,发送的是旧的/未更改的邮件文本。 问题是:我必须做什么才能“激活”我的更改?

见:

use Email::MIME;

my $raw_message_text = q!Date: Wed, 26 Feb 2014 08:02:39 +0100
From: Me <me@example.com>
To: You <you@example.com>
Subject: test
MIME-Version: 1.0
Content-Type: multipart/mixed;
 boundary="------------010309070301040606000908"

This is a multi-part message in MIME format.
--------------010309070301040606000908
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

this is a test

--------------010309070301040606000908
Content-Type: text/plain;
 name="file-to-attach.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="file-to-attach.txt"

dGV4dCBpbnNpZGUgYXR0YWNobWVudAoK
--------------010309070301040606000908--
!;


my $parsed_email = Email::MIME->new($raw_message_text);

$parsed_email->walk_parts(sub 
    my ($part) = @_;
    return if $part->subparts; # multipart
    return unless ($part->content_type =~ /text\/plain.*charset=utf-8/i);
    $part->body_set("new body text");
);

print "As you see the change is there:\n";
$parsed_email->walk_parts(sub 
    my ($part) = @_;
    return if $part->subparts; # multipart
    my $body = $part->body;
    print "Body:$body\n";
);

print "But the email object itself doesn't notice that:\n\n";

print $parsed_email->as_string;

这将首先显示更改后的正文,所以你看它就在那里!但是当显示整个邮件时,会使用旧的正文。如果我只是使用Email::Sender 发送电子邮件,也会发生同样的情况。所以我想知道body_set的正确用法是什么...

【问题讨论】:

它适用于我的 1.910 【参考方案1】:

我也偶然发现了这个问题。最终我意识到原始海报中缺少的只是以下内容:

my @new_parts = $parsed_email->parts;
$parsed_email->parts_set( \@new_parts );

在最后的 as_string 调用之前添加上述内容,你就很好了。

【讨论】:

确实!它在 Debian 的 1.910-1 版本中没有 parts_set 也可以工作,但至少在 1.926-1 (Debian Jessie) 中是必需的。【参考方案2】:

walk_parts 似乎无法正常工作我必须使用旧的经典方法,我不确定新版本是否有问题,但使用此方法可以正常工作,您只需要以某种方式替换您的代码:

这个解决方案根本没有效率,我知道它对内存很重,但我很懒,我想我应该寻找另一个有这个模型的库。

my @parts = $parsed->subparts;
my @new_parts;
if (@parts) 
  foreach (@parts)
  
    my $part = $_;
    print $part->content_type."\r\n";    
    if ($part->content_type =~ /text\/plain.*charset=utf-8/i) 
     $part->body_set("new body text");
     push @new_parts, $part;
     else 
     push @new_parts, $part;
    
   
 else 
 print 'single part';#to replace for single mime

$parsed->parts_set(\@new_parts);

【讨论】:

那就别那么懒了,快点更新答案吧:)

以上是关于如何使用 Email::MIME 更改一个部分的正文?或者:body_set 对谁起作用?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Email::MIME 和 multipart/signed 解析电子邮件

使用 Email::MIME 和 multipart/mixed with subparts 解析电子邮件

如何使用 Perl Email::Mime 内联图像?

如何使用Email :: Mime与sendmail

电子邮件:MIME,用附件多部分发送?

将 MIMEText 编码为引用的可打印文件