Email:MIME,分批发送附件?
Email:MIME, sending in multipart with attachment?
这让我抓狂。我一定是错过了一些愚蠢的东西。我有以下子项:
sub send_email {
use MIME::Lite;
use MIME::Base64;
use Encode;
my $to = 'support@foobar.co.uk'; #$rec{'Email'};
my $from = $admin_email;
my $subject = "webform $html_title";
my $html = "some test <b>message</b> foo bar test";
my $text = "some test message some plain version";
# $html = decode( 'utf-8', $html );
# $text = decode( 'utf-8', $text );
my ($status,$attach,$newfile);
use Email::MIME;
use Email::Address::XS;
use Email::Sender::Simple qw(sendmail);
use IO::All;
use GT::MIMETypes;
# multipart message
my @alternative_parts = (
Email::MIME->create(
body_str => $text,
attributes => {
encoding => 'quoted-printable',
content_type => "text/plain",
disposition => "inline",
charset => "UTF-8",
}
),
Email::MIME->create(
body_str => $html,
attributes => {
encoding => 'quoted-printable',
charset => "UTF-8",
content_type => "text/html",
disposition => "inline",
}
)
);
my @attachment_parts;
my $attach = "/path/to/file/tables.cgi";
if ($attach) {
my $filename = (reverse split /\//, $attach)[0]; # also change
+d in body => below
my $content;
my $mime = GT::MIMETypes::guess_type($filename);
push @parts, Email::MIME->create(
attributes => {
filename => $filename,
content_type => $mime,
encoding => "base64",
name => $filename,
attachment => "attachment"
},
body => io( $attach )->binary->all,
)
}
my $email = Email::MIME->create(
header_str => [
From => $from,
To => [ $to ],
Subject => $subject
],
parts => \@parts,
attributes => {
encoding => 'base64',
charset => "UTF-8",
content_type => "multipart/multipart",
#disposition => "inline",
}
);
sendmail($email->as_string);
print "EMAIL: " . $email->as_string. "\n\n"; # print for andy
}
它需要做的是包含纯文本和 HTML 电子邮件正文。然后,还附加了一个文件(一个.cgi 只是为了测试:))。
虽然电子邮件在 Gmail 上可以正常发送,但在 Outlook/Thunderbird 上却出现问题。我有一种感觉,这是我打破 "parts" 的方式。根据我的理解,您需要一个 "main" 正文部分,它可以分为纯文本和 HTML 版本 - 然后附件作为主体 "part" 的另一部分。不过我不太确定如何实现这一点?
这就是 "debug_structure" 的结果:
Structure: + multipart/multipart; boundary="15846317930.c94ff7.26547"
+ text/plain; charset="UTF-8"
+ text/html; charset="UTF-8"
+ text/plain; attachment="attachment"; name="tables.cgi"
更新: 按照建议,我现在正在尝试嵌套部分:
# multipart message
my @message_parts = (
Email::MIME->create(
body_str => $text,
attributes => {
encoding => 'quoted-printable',
content_type => "text/plain",
disposition => "inline",
charset => "UTF-8",
}
),
Email::MIME->create(
body_str => $html,
attributes => {
encoding => 'quoted-printable',
charset => "UTF-8",
content_type => "text/html",
disposition => "inline",
}
)
);
my @all_parts;
push @all_parts, Email::MIME->create(
parts => [\@message_parts], # add all the message parts into here...
attributes => {
content_type => "multipart/alternative"
}
);
my $attach = "/home/user/web/public_html/cgi-bin/admin/tables.cgi";
if ($attach) {
my $filename = (reverse split /\//, $attach)[0]; # also changed in body => below
# better to use GT::MIMETypes if you have it with Fileman (pretty sure you do?)
my $mime = GT::MIMETypes::guess_type($filename);
push @all_parts, Email::MIME->create(
attributes => {
filename => $filename,
content_type => $mime,
encoding => "base64",
name => $filename
},
body => io( $attach )->binary->all,
)
}
my $email = Email::MIME->create(
header_str => [
From => $from,
To => [ $to ],
Subject => $subject
],
parts => [\@all_parts],
attributes => {
encoding => 'base64',
content_type => "multipart/mixed"
}
);
print qq|Structure: | . $email->debug_structure. "\n\n";
但是我得到一个错误:
Can't call method "as_string" on unblessed reference at
/usr/local/share/perl/5.22.1/Email/MIME.pm line 771.
第 771 行在 Email::MIME 中的 parts_set
- 所以我一定是做错了什么设置?
更新 2: 感谢 Steffen 的帮助!所以这是最终的工作代码,具有正确的结构:
use Email::MIME;
use Email::Address::XS;
use Email::Sender::Simple qw(sendmail);
use IO::All;
use GT::MIMETypes;
my $to = 'support@foo.co.uk'; #$rec{'Email'};
my $from = $admin_email;
my $subject = "some title";
my $html = "some test <b>message</b> foo bar test";
my $text = "some test message some plain version";
$html = decode( 'utf-8', $html );
$text = decode( 'utf-8', $text );
# multipart message
my @message_parts = (
Email::MIME->create(
body_str => $text,
attributes => {
encoding => 'quoted-printable',
content_type => "text/plain",
disposition => "inline",
charset => "UTF-8",
}
),
Email::MIME->create(
body_str => $html,
attributes => {
encoding => 'quoted-printable',
charset => "UTF-8",
content_type => "text/html",
disposition => "inline",
}
)
);
my @all_parts;
push @all_parts, Email::MIME->create(
parts => \@message_parts, # add all the message parts into here...
attributes => {
content_type => "multipart/alternative"
}
);
my $attach = "/home/user/web/foo.co.uk/public_html/cgi-bin/admin/tables.cgi";
if ($attach) {
my $filename = (reverse split /\//, $attach)[0]; # also changed in body => below
# better to use GT::MIMETypes if you have it with Fileman (pretty sure you do?)
my $mime = "plain/text"; # hard coded in this example, but you want to set the correct type for the attachment type
push @all_parts, Email::MIME->create(
attributes => {
filename => $filename,
content_type => $mime,
encoding => "base64",
name => $filename
},
body => io( $attach )->binary->all,
)
}
my $email = Email::MIME->create(
header_str => [
From => $from,
To => [ $to ],
Subject => $subject
],
parts => \@all_parts,
attributes => {
encoding => 'base64',
content_type => "multipart/mixed"
}
);
print qq|Structure: | . $email->debug_structure. "\n\n";
sendmail($email->as_string);
结构现在正确显示为:
Structure: + multipart/mixed; boundary="15846944601.d6aF.12245"
+ multipart/alternative; boundary="15846944600.d79D2A2.12245"
+ text/plain; charset="UTF-8"
+ text/html; charset="UTF-8"
+ text/plain; name="tables.cgi"
没有您使用的 multipart/multipart
这样的东西。您的邮件应该具有以下结构:
multipart/mixed
|- multipart/alternative << mail client will choose which of the parts to display
| | text/plain << the mail as plain text
| | text/html << the mail as HTML
|- text/plain << the attachment
至于附件,选择更符合附件类型的 content-type
可能会有用。如果附件实际上是纯文本,那么 text/plain
可能没问题,但如果它是图像、办公文档、存档……则应使用不同的 content-type
。
除此之外,encoding
、charset
和 disposition
在多部分定义中都没有任何意义。这些仅与最终部件(text/plain
等)相关,与容器部件无关(multipart/whatever
)
attributes => {
encoding => 'base64',
charset => "UTF-8",
content_type => "multipart/multipart",
#disposition => "inline",
}
这让我抓狂。我一定是错过了一些愚蠢的东西。我有以下子项:
sub send_email {
use MIME::Lite;
use MIME::Base64;
use Encode;
my $to = 'support@foobar.co.uk'; #$rec{'Email'};
my $from = $admin_email;
my $subject = "webform $html_title";
my $html = "some test <b>message</b> foo bar test";
my $text = "some test message some plain version";
# $html = decode( 'utf-8', $html );
# $text = decode( 'utf-8', $text );
my ($status,$attach,$newfile);
use Email::MIME;
use Email::Address::XS;
use Email::Sender::Simple qw(sendmail);
use IO::All;
use GT::MIMETypes;
# multipart message
my @alternative_parts = (
Email::MIME->create(
body_str => $text,
attributes => {
encoding => 'quoted-printable',
content_type => "text/plain",
disposition => "inline",
charset => "UTF-8",
}
),
Email::MIME->create(
body_str => $html,
attributes => {
encoding => 'quoted-printable',
charset => "UTF-8",
content_type => "text/html",
disposition => "inline",
}
)
);
my @attachment_parts;
my $attach = "/path/to/file/tables.cgi";
if ($attach) {
my $filename = (reverse split /\//, $attach)[0]; # also change
+d in body => below
my $content;
my $mime = GT::MIMETypes::guess_type($filename);
push @parts, Email::MIME->create(
attributes => {
filename => $filename,
content_type => $mime,
encoding => "base64",
name => $filename,
attachment => "attachment"
},
body => io( $attach )->binary->all,
)
}
my $email = Email::MIME->create(
header_str => [
From => $from,
To => [ $to ],
Subject => $subject
],
parts => \@parts,
attributes => {
encoding => 'base64',
charset => "UTF-8",
content_type => "multipart/multipart",
#disposition => "inline",
}
);
sendmail($email->as_string);
print "EMAIL: " . $email->as_string. "\n\n"; # print for andy
}
它需要做的是包含纯文本和 HTML 电子邮件正文。然后,还附加了一个文件(一个.cgi 只是为了测试:))。
虽然电子邮件在 Gmail 上可以正常发送,但在 Outlook/Thunderbird 上却出现问题。我有一种感觉,这是我打破 "parts" 的方式。根据我的理解,您需要一个 "main" 正文部分,它可以分为纯文本和 HTML 版本 - 然后附件作为主体 "part" 的另一部分。不过我不太确定如何实现这一点?
这就是 "debug_structure" 的结果:
Structure: + multipart/multipart; boundary="15846317930.c94ff7.26547"
+ text/plain; charset="UTF-8"
+ text/html; charset="UTF-8"
+ text/plain; attachment="attachment"; name="tables.cgi"
更新: 按照建议,我现在正在尝试嵌套部分:
# multipart message
my @message_parts = (
Email::MIME->create(
body_str => $text,
attributes => {
encoding => 'quoted-printable',
content_type => "text/plain",
disposition => "inline",
charset => "UTF-8",
}
),
Email::MIME->create(
body_str => $html,
attributes => {
encoding => 'quoted-printable',
charset => "UTF-8",
content_type => "text/html",
disposition => "inline",
}
)
);
my @all_parts;
push @all_parts, Email::MIME->create(
parts => [\@message_parts], # add all the message parts into here...
attributes => {
content_type => "multipart/alternative"
}
);
my $attach = "/home/user/web/public_html/cgi-bin/admin/tables.cgi";
if ($attach) {
my $filename = (reverse split /\//, $attach)[0]; # also changed in body => below
# better to use GT::MIMETypes if you have it with Fileman (pretty sure you do?)
my $mime = GT::MIMETypes::guess_type($filename);
push @all_parts, Email::MIME->create(
attributes => {
filename => $filename,
content_type => $mime,
encoding => "base64",
name => $filename
},
body => io( $attach )->binary->all,
)
}
my $email = Email::MIME->create(
header_str => [
From => $from,
To => [ $to ],
Subject => $subject
],
parts => [\@all_parts],
attributes => {
encoding => 'base64',
content_type => "multipart/mixed"
}
);
print qq|Structure: | . $email->debug_structure. "\n\n";
但是我得到一个错误:
Can't call method "as_string" on unblessed reference at /usr/local/share/perl/5.22.1/Email/MIME.pm line 771.
第 771 行在 Email::MIME 中的 parts_set
- 所以我一定是做错了什么设置?
更新 2: 感谢 Steffen 的帮助!所以这是最终的工作代码,具有正确的结构:
use Email::MIME;
use Email::Address::XS;
use Email::Sender::Simple qw(sendmail);
use IO::All;
use GT::MIMETypes;
my $to = 'support@foo.co.uk'; #$rec{'Email'};
my $from = $admin_email;
my $subject = "some title";
my $html = "some test <b>message</b> foo bar test";
my $text = "some test message some plain version";
$html = decode( 'utf-8', $html );
$text = decode( 'utf-8', $text );
# multipart message
my @message_parts = (
Email::MIME->create(
body_str => $text,
attributes => {
encoding => 'quoted-printable',
content_type => "text/plain",
disposition => "inline",
charset => "UTF-8",
}
),
Email::MIME->create(
body_str => $html,
attributes => {
encoding => 'quoted-printable',
charset => "UTF-8",
content_type => "text/html",
disposition => "inline",
}
)
);
my @all_parts;
push @all_parts, Email::MIME->create(
parts => \@message_parts, # add all the message parts into here...
attributes => {
content_type => "multipart/alternative"
}
);
my $attach = "/home/user/web/foo.co.uk/public_html/cgi-bin/admin/tables.cgi";
if ($attach) {
my $filename = (reverse split /\//, $attach)[0]; # also changed in body => below
# better to use GT::MIMETypes if you have it with Fileman (pretty sure you do?)
my $mime = "plain/text"; # hard coded in this example, but you want to set the correct type for the attachment type
push @all_parts, Email::MIME->create(
attributes => {
filename => $filename,
content_type => $mime,
encoding => "base64",
name => $filename
},
body => io( $attach )->binary->all,
)
}
my $email = Email::MIME->create(
header_str => [
From => $from,
To => [ $to ],
Subject => $subject
],
parts => \@all_parts,
attributes => {
encoding => 'base64',
content_type => "multipart/mixed"
}
);
print qq|Structure: | . $email->debug_structure. "\n\n";
sendmail($email->as_string);
结构现在正确显示为:
Structure: + multipart/mixed; boundary="15846944601.d6aF.12245"
+ multipart/alternative; boundary="15846944600.d79D2A2.12245"
+ text/plain; charset="UTF-8"
+ text/html; charset="UTF-8"
+ text/plain; name="tables.cgi"
没有您使用的 multipart/multipart
这样的东西。您的邮件应该具有以下结构:
multipart/mixed
|- multipart/alternative << mail client will choose which of the parts to display
| | text/plain << the mail as plain text
| | text/html << the mail as HTML
|- text/plain << the attachment
至于附件,选择更符合附件类型的 content-type
可能会有用。如果附件实际上是纯文本,那么 text/plain
可能没问题,但如果它是图像、办公文档、存档……则应使用不同的 content-type
。
除此之外,encoding
、charset
和 disposition
在多部分定义中都没有任何意义。这些仅与最终部件(text/plain
等)相关,与容器部件无关(multipart/whatever
)
attributes => {
encoding => 'base64',
charset => "UTF-8",
content_type => "multipart/multipart",
#disposition => "inline",
}