web-dev-qa-db-ja.com

送信PHP添付ファイル付きHTMLメール

問題が発生しました。今日まで、PHPを含むHTMLメールを、

Content-type: text/html;

ここで、添付ファイルを追加する機能を追加しました。このため、この行を

Content-Type: multipart/mixed;

今、multipart/mixed、残りのメール、つまり通常のテキストは、text/plainとして表示されます。添付ファイルが機能し、メールテキストがHTMLのままであることをどのようにして認識できますか?

12
Florian Müller

添付ファイル付きのメールを送信するには、混合タイプがメールに含まれることを指定するmultipart/mixed MIMEタイプを使用する必要があります。さらに、multipart/alternative MIMEタイプを使用して、プレーンテキストとHTMLバージョンの両方の電子メールを送信します。例を見てください。

<?php 
//define the receiver of the email 
$to = '[email protected]'; 
//define the subject of the email 
$subject = 'Test email with attachment'; 
//create a boundary string. It must be unique 
//so we use the MD5 algorithm to generate a random hash 
$random_hash = md5(date('r', time())); 
//define the headers we want passed. Note that they are separated with \r\n 
$headers = "From: [email protected]\r\nReply-To: [email protected]"; 
//add boundary string and mime type specification 
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\""; 
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents('attachment.Zip'))); 
//define the body of the message. 
ob_start(); //Turn on output buffering 
?> 
--PHP-mixed-<?php echo $random_hash; ?>  
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>" 

--PHP-alt-<?php echo $random_hash; ?>  
Content-Type: text/plain; charset="iso-8859-1" 
Content-Transfer-Encoding: 7bit

Hello World!!! 
This is simple text email message. 

--PHP-alt-<?php echo $random_hash; ?>  
Content-Type: text/html; charset="iso-8859-1" 
Content-Transfer-Encoding: 7bit

<h2>Hello World!</h2> 
<p>This is something with <b>HTML</b> formatting.</p> 

--PHP-alt-<?php echo $random_hash; ?>-- 

--PHP-mixed-<?php echo $random_hash; ?>  
Content-Type: application/Zip; name="attachment.Zip"  
Content-Transfer-Encoding: base64  
Content-Disposition: attachment  

<?php echo $attachment; ?> 
--PHP-mixed-<?php echo $random_hash; ?>-- 

<?php 
//copy current buffer contents into $message variable and delete current output buffer 
$message = ob_get_clean(); 
//send the email 
$mail_sent = @mail( $to, $subject, $message, $headers ); 
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed" 
echo $mail_sent ? "Mail sent" : "Mail failed"; 
?>

ご覧のとおり、添付ファイル付きのメールを送信するのは簡単です。前の例では、multipart/mixed MIMEタイプがあり、その中には、2つのバージョンの電子メールを指定するmultipart/alternative MIMEタイプがあります。メッセージに添付ファイルを含めるには、指定したファイルから文字列にデータを読み取り、base64でエンコードし、小さなチャンクに分割して、MIME仕様と一致することを確認してから、添付ファイルとして含めます。

10

回答1を数時間試してみましたが、運がありませんでした。私はここで解決策を見つけました: http://www.finalwebsites.com/forums/topic/php-e-mail-attachment-script

魅力的な作品-5分未満! (私がしたように)最初のコンテンツタイプをtext/plainからtext/htmlに変更することもできます。

これは、複数の添付ファイルを処理するように少し変更したバージョンです。

function mail_attachment($files, $path, $mailto, $from_mail, $from_name, $replyto, $subject, $message) {
$uid = md5(uniqid(time()));

$header = "From: ".$from_name." <".$from_mail.">\r\n";
$header .= "Reply-To: ".$replyto."\r\n";
$header .= "MIME-Version: 1.0\r\n";
$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
$header .= "This is a multi-part message in MIME format.\r\n";
$header .= "--".$uid."\r\n";
$header .= "Content-type:text/html; charset=iso-8859-1\r\n";
$header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$header .= $message."\r\n\r\n";

    foreach ($files as $filename) { 

        $file = $path.$filename;

        $file_size = filesize($file);
        $handle = fopen($file, "r");
        $content = fread($handle, $file_size);
        fclose($handle);
        $content = chunk_split(base64_encode($content));

        $header .= "--".$uid."\r\n";
        $header .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n"; // use different content types here
        $header .= "Content-Transfer-Encoding: base64\r\n";
        $header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
        $header .= $content."\r\n\r\n";
    }

$header .= "--".$uid."--";
return mail($mailto, $subject, "", $header);
}
26
Brian

PHPのSWIFTMAILは、メールの添付ファイルとしてgr8で機能します。

こちらからswiftmailerをダウンロード http://swiftmailer.org/

以下の簡単なコードを見てください

ファイルを含める

require_once('path/to/swiftMailer/lib/Swift_required.php');

トランスポートを作成

//FOR SMTP
// Create the Transport
$transport = Swift_SmtpTransport::newInstance('smtp.googlemail.com', 465, 'ssl')
    ->setUsername('[email protected]')
    ->setPassword('gmailpassword');

OR

//FOR NORMAL MAIL
$transport = Swift_MailTransport::newInstance();

メイラーオブジェクト

// Create the Mailer using your created Transport
$mailer = Swift_Mailer::newInstance($transport);

メッセージオブジェクトの作成

$message = Swift_Message::newInstance($subject)
    ->setFrom(array($from => $from))
    ->setTo($to)
    ->setBody($body);
$message->attach(Swift_Attachment::fromPath($filepath));

メッセージを送る

$result = $mailer->send($message);
3
Rayiez

インターネットメッセージのフォーマット方法を本当に知りたい場合は、そのRFC(別名RFC)を参照してください。 「多目的インターネットメール拡張-インターネットメッセージ本文の形式」を定義するものは、1996年11月に発行された RFC2045 です。

形式はどういうわけか非常に厳密であり、そのまま従う必要があります。

基本的に、メッセージにはヘッダーと本文が含まれます。ヘッダーは、メッセージのタイプ、フォーマット方法、タイプによって異なるその他のフィールドを定義します。

ボディはさまざまなエンティティによって形成されます。エンティティは、たとえば「こんにちは!」のようなプレーンテキストにすることができます。画像、添付ファイルなど、何でもかまいません。

[〜#〜] note [〜#〜]次の例では、角かっこで囲まれたすべて(例:{hello})を実際の値。すべての改行は実際にはCRLFです(つまり、ASCII 13 + ASCII 10)。2つのCRLFが表示されているところ。これは、最悪の瞬間です。あなたがどれほどクリエイティブであるかを示してください。

基本的に、添付ファイルがあるメールメッセージの場合、ヘッダーは次のようになります。

MIME-Version: 1.0
To: {email@domain}
Subject: {email-subject}
X-Priority: {2 (High)}
Content-Type: multipart/mixed; boundary="{mixed-boudary}"

上記の例では、{mixed-boudary}は、000008050800060107020705のような任意の一意のハッシュ値である場合があります。その他は一目瞭然です。

ここで、メッセージに新しいエンティティ(メッセージ本文、画像、添付ファイルなど)を追加するときはいつでも、新しいセクションが来ることをメールエージェントに通知する必要があります 、すなわち。そのエンティティの前に{mixed-boundary}値を付けます。これを「境界を開く」と呼びます。境界を開くことで、最初に定義されたようにその境界を挿入しないことに注意してください。--{mixed-boudary}のように、前にさらに2つのマイナス記号を使用します。 -{mixed-boudary}-のように、最後に他の2つのマイナス記号を使用する必要があることを除いて、境界を閉じるときも同様に進めます。

--{mixed-boudary}
the entity content
--{mixed-boudary}--

電子メールエージェントは、新しく挿入されたエンティティのコンテンツがどのタイプであるかを理解する必要があるため、境界の開始直後にそれを宣言する必要があります。宣言は、エンティティと互換性のあるパラメーター/値のみを含む単なるヘッダーです。

HTML本文コンテンツの場合、エンティティヘッダーは次のようになります。

Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

したがって、全体(境界で囲まれた)は最終的に次のようになります。

--{mixed-boudary}
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<html>
<head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head>
<body bgcolor="#FFFFFF" text="#000000">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel 
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus 
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat 
accumsan, consectetur ex et, rhoncus risus.
</body>
</html>

別のエンティティを挿入する必要がある場合は、上記とまったく同じように進めます。メッセージに追加するデータがなくなったら、混合境界を閉じます。 CRLF +-{mixed-boudary}-。

何らかの理由でエンティティを代替表現で挿入する必要がある場合(たとえば、本文メッセージをプレーンテキスト形式とHTML形式の両方として挿入する)、エンティティのコンテンツをcontent-type multipart/alternativeで宣言する必要があります。 (ただし、グローバルmultipart/mixedヘッダーはまだ残っています!)それぞれの代替表現は、この新しい境界によって囲まれます。

以下の完全な例:

MIME-Version: 1.0
To: {email@domain}
Subject: {email-subject}
X-Priority: {2 (High)}
Content-Type: multipart/mixed; boundary="{mixed-boudary}"

--{mixed-boudary}
Content-Type: multipart/alternative; boundary="{alternative-boudary}"

--{alternative-boudary}
Content-Type: text/plain; charset=utf-8;
Content-Transfer-Encoding: 7bit

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel 
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus 
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat 
accumsan, consectetur ex et, rhoncus risus.

--{alternative-boudary}
Content-Type: text/html; charset=utf-8;
Content-Transfer-Encoding: 7bit

<html>
<head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head>
<body bgcolor="#FFFFFF" text="#000000">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel 
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus 
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat 
accumsan, consectetur ex et, rhoncus risus.
</body>
</html>

--{alternative-boudary}--

--{mixed-boudary}
Content-Type: application/pdf; name="myfile.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="myfile.pdf"

JVBERi0xLjINOCAwIG9iag08PCAvTGVuZ3RoIDkgMCBSIC9GaWx0ZXIgL0ZsYXRlRGVjb2Rl
ID4+DXN0cmVhbQ1oQ51bbY/cNg7+BfsfhAUO11w3riW/B7gPaZEAAdpcm06RL8EBzoyn68uM
vZ3xZLv//khKsuUxNaMNiiabpUg+pKiHsmxJEcN/UsgiilP4ab2/+XF1I81vszSqclHIOEpj
sdrf/PC2EFVUpmK1vXkZxVKs1uJlJJVYPYrvPra7XVvvxYdIrE7rL83hhVj97+bNyjUoFam7
FnOB+tubGI3FZEkwmhpKXpVRnqJi0PCyjBJ1DjyOYqWBxxXp/1h3X+ov9abZt434pV0feoG/
ars/xU/9/qEZmm7diJ+abmgOr0TGeFNFEuXx5M4B95Idns/QAaJMI1IpKeXi9+ZhaPafm4NQ
cRwzNpK0iirlRvisRBZpVJa+PP51091kkjBWBXrJxUuZRjIXh0Z8FN3MnB5X5st5Kay9355n

--{mixed-boudary}--

[〜#〜]ヒント[〜#〜]

お好みのメールクライアント(私はThunderbirdです)を使用して、プレーンテキストのみ、HTMLのみ、1つを混合したメッセージを1つずつ送信します。メッセージを受け取ったら、そのソースを調べてください(表示->メッセージソース)。

@編集:非常によく文書化されたケーススタディ+ PHP例は here にあります

1