【问题标题】:is there a way to attach a PDF FILE with Net::SMTP in Perl有没有办法在 Perl 中使用 Net::SMTP 附加 PDF 文件
【发布时间】:2016-04-21 06:16:55
【问题描述】:

我正在尝试在多部分内容电子邮件中附加一个 pdf 文件,是的,我知道我可以使用 mime lite 或十亿个 perl 模块,但我只能使用开箱即用的 perl 5.8.8 ,到目前为止我有

#!/usr/bin/perl
use Net::SMTP;
use MIME::Base64 qw( encode_base64 );
use MIME::Base64 qw( decode_base64 );
use strict;
use warnings;

my $from = 'az@xx.com';
my $to = 'raxxxfael.xx@xxx.com';
my $to2 = 'xx.xx@xxx.com';
my $boundary = 'frontier';




open my $Initial_File, '<', "summary.pdf";
binmode $Initial_File;
open my $Initial_OutFile, '>', "temp.pdf";
my $buf;
while ( read( $Initial_File, $buf, 60 * 57 ) ) {
    print $Initial_OutFile encode_base64( $buf );
}

close $Initial_OutFile;
close $Initial_File;


open INFILE, '<', "temp.pdf";
open my $final_output, '>',"summary2.pdf";
binmode $final_output;
my $buffer;
while ( $buffer = <INFILE> ) {
    print $final_output decode_base64( $buffer );
}
my @pdf = $final_output;
close $final_output;
close INFILE; 

my $smtp = Net::SMTP->new('xx.xxx.com');
$smtp->mail($from);
$smtp->recipient($to,$to2, { SkipBad => 1 });
$smtp->data();
$smtp->datasend("Subject: Test Email \n");
$smtp->datasend("MIME-Version: 1.0\n");
$smtp->datasend("Content-type: multipart/mixed;\n\tboundary=".$boundary."\n");
$smtp->datasend("\n");
$smtp->datasend("--".$boundary."\n");
$smtp->datasend("Content-type: text/plain\n");
$smtp->datasend("Content-Disposition: quoted-printable\n");
$smtp->datasend("\nTest From You \n");
$smtp->datasend("--".$boundary."\n");
$smtp->datasend("Content-Disposition: attachment; filename=summary2.pdf \n");
$smtp->datasend("Content-Type: application/pdf; name=summary2.pdf ");
$smtp->datasend("\n");
$smtp->datasend("@pdf\n");
$smtp->datasend("--".$boundary."--\n");
$smtp->dataend();
# $smtp->quit;   

exit;

电子邮件正确发送,但是(显然)在尝试打开 pdf 文件时它说它的编码不正确,有没有办法将 PDF 文件缓冲到附件中,以将其发送出去是?

【问题讨论】:

  • MIME::Lite is pure-perl,复制代码即可。
  • “我只能使用开箱即用的 perl 5.8.8” - 这可能是您应该首先解决的问题 :-) 如果您不能使用 CPAN,那么您'真的没有使用 Perl 的全部功能。
  • @DaveCross 完全同意,如果由我来决定,我已经安装了整个 CPAN,这是一个生产服务器,IT 不愿意做任何微小的改变。
  • @daxim 感谢您的提示!我这样做了,如果你想将它设置为 anser 我会接受它

标签: perl smtp attachment


【解决方案1】:

这是一个如何使用 Net::SMTP 发送多部分邮件消息的工作示例。

提供了用于发送纯文本、纯文本文件和二进制图像 (jpg) 的代码。

希望这会有所帮助!

亚历杭德罗

PS。上面提供的代码 RVS 列出了其他几种内容类型,包括 pdf。任何不是纯文本文件的文件都应被视为二进制文件,并以 base64 编码发送。您不需要对其进行解码,因为接收邮件的电子邮件客户端应该会处理它。

#!/usr/bin/perl

use Net::SMTP;
use strict;
use warnings;

use MIME::Base64 qw( encode_base64 );
#use MIME::Base64 qw( decode_base64 );

my $from = 'from@email.com';
my $to = 'to@email.com';

my $attachBinaryFile= 'test.jpg';
my $attachTextFile = 'test.txt';

my $boundary = 'frontier';

open(DAT, $attachTextFile) || die("Could not open text file!");
my @textFile = <DAT>;
close(DAT);

my $smtp = Net::SMTP->new('your.smtp.com', Timeout => 60) || die("Could not create SMTP object.");
print "Sending mail\n";
$smtp->mail($from);
$smtp->recipient($to, { SkipBad => 1 });
$smtp->data();
$smtp->datasend("To: $to\n");
$smtp->datasend("From: $from\n");
$smtp->datasend("Subject: Multi part test\n");
$smtp->datasend("MIME-Version: 1.0\n");
$smtp->datasend("Content-type: multipart/mixed;\n\tboundary=\"$boundary\"\n");
$smtp->datasend("\n");
$smtp->datasend("--$boundary\n");
$smtp->datasend("Content-type: text/plain\n");
$smtp->datasend("Content-Disposition: quoted-printable\n");
$smtp->datasend("\nToday\'s files are attached:\n");
$smtp->datasend("\nHave a nice day! :)\n");
$smtp->datasend("--$boundary\n");
$smtp->datasend("Content-Type: application/text; name=\"$attachTextFile\"\n");
$smtp->datasend("Content-Disposition: attachment; filename=\"$attachTextFile\"\n");
$smtp->datasend("\n");
$smtp->datasend("@textFile\n");
$smtp->datasend("--$boundary\n");
$smtp->datasend("Content-Type: image/jpeg; name=\"$attachBinaryFile\"\n");
$smtp->datasend("Content-Transfer-Encoding: base64\n");
$smtp->datasend("Content-Disposition: attachment; filename=\"$attachBinaryFile\"\n");
$smtp->datasend("\n");
my $buf;
open(DAT, "../uploads/$attachBinaryFile") || die("Could not open binary file!");
   binmode(DAT);
   local $/=undef;
   while (read(DAT, my $picture, 4096)) {
      $buf = &encode_base64( $picture );
      $smtp->datasend($buf);
   }
close(DAT);
$smtp->datasend("\n");
$smtp->datasend("--$boundary\n");
$smtp->dataend();
$smtp->quit;
print "Mail sent\n";
exit;

【讨论】:

  • 您好,我已经使用了此代码,并且似乎可以正常工作,但我很好奇电子邮件中还附加了未包含在代码中的附加文件。只是想知道为什么或如何发生。谢谢! :D
  • 上述解决方案几乎是正确的,除了块缓冲区大小“4096” - 这个大小不正确,将导致从 pdf 或空白 pdf 中删除所有文本。正确的大小是“4104”,因为它必须是 57 字节的倍数。我一直在努力解决这个问题,直到我在总是令人难以置信的 Perl Monks 网站上找到了正确的块大小:perlmonks.org/?node_id=1211052
【解决方案2】:

最终手动将 MIME:Lite 添加到我的用户目录

use lib '/xx/sas/xx/perl';
use MIME::Lite;
open(SMTP,'/xx/sas/xx/perl/MIME/srv.txt') || die("Could not open the file");
my $mail_host = <SMTP>;
close(SMTP);
open(DATA, $ARGV[3] ) || die("Could not open the file");
my @csv = <DATA>;
close(DATA);

foreach (@csv){
    $textStr.= $_;
}

$msg = MIME::Lite->new (
  From => $ARGV[0],
  To => $ARGV[1],
  Subject => $ARGV[2],
  Type =>'multipart/mixed'
) or die "Error creating multipart container: $!\n";

$msg->attach (
  Type => 'TEXT',
  Data => $textStr
) or die "Error adding the text message part: $!\n";

foreach my $file (split(',', $ARGV[4])) { 
        $content_type='TEXT';
        if ( $file =~ /\.gif$/i ){ $content_type ='image/gif'}
        if ( $file =~ /\.jpg$/i ){ $content_type ='image/jpeg'}
        if ( $file =~ /\.zip$/i ){ $content_type ='application/zip'}
        if ( $file =~ /\.html$/i ){ $content_type ='text/html'}
        if ( $file =~ /\.pdf$/i ){ $content_type ='application/pdf'}
        if ( $file =~ /\.xls$/i ){ $content_type ='application/vnd.ms-excel'}
        if ( $file =~ /\.log$/i ){ $content_type ='application/octet-stream'}
        $msg->attach (
           Type => $content_type,
           Path => $file,
           Filename => $file,
           Disposition => 'attachment'
        ) or die "Error adding $file: $!\n";    
}   

MIME::Lite->send('smtp', $mail_host, Timeout=>60);
$msg->send;

【讨论】:

    【解决方案3】:

    这……看起来不对:

    open FILE, "summary.pdf" or die $!;
    my @txt = <FILE>;
    close FILE;
    
    ...
    $smtp->datasend("@txt\n");
    

    我相信您所寻找的问题在于这两行代码。您正在使用字符串阅读器读取二进制格式,然后将该二进制插入字符串中。

    试试:

    ...
    open FILE, "summary.pdf" or die $!;
    binmode(FILE);
    my $data = do { local $/; <FILE> };
    close FILE;
    ...
    $smtp->datasend($data);
    

    或类似的东西。

    【讨论】:

    • 无赖!我没有尝试,只是说它可能是在正确的方向。 :)
    猜你喜欢
    • 2010-11-14
    • 1970-01-01
    • 1970-01-01
    • 2023-02-25
    • 2020-10-29
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多