簡體   English   中英

電子郵件: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 上出現問題。 我有一種感覺,這是我分解“部分”的方式。 根據我的理解,您需要一個“主要”正文部分,它可以分為純文本和 HTML 版本 - 然后將附件作為主要“部分”的另一部分。 我不太確定如何實現這一目標?

這就是“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";

但我收到一個錯誤:

無法在 /usr/local/share/perl/5.22.1/Email/MIME.pm 第 771 行的無福參考上調用方法“as_string”。

第 771 parts_set 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

除此之外, encodingcharsetdisposition在多部分定義中都沒有任何意義。 這些僅與最終部分( text/plain等)相關,而不與容器部分( multipart/whatever )相關

    attributes => {
        encoding => 'base64',
        charset  => "UTF-8",
        content_type => "multipart/multipart",
        #disposition  => "inline",
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM