我经常听到这样一个问题:“我有一个从网站发来的合同。我如何给
通过表单发送的电子邮件增加一个附件呢?”
首先我要说的是要做到这个没有什么简单的办法。你要很好的理解PHP或其它的服务器端的脚本语言。当然你还要一个真正支持PHP的网站的账号。如果满足了这个前提,在你读完了本章后就可以用PHP发送带附件的电子邮件了。
1. 附件是如何工作的
如果你曾经在PHP的手册中搜索过“附件”函数,那么结果可能是什么都没有(至少在我写本文的时间还没有)。后来你就要花很多时间来了解这方面的知识。
你也许会想当你给某个人发送一封带附件的电子邮件时,附件是和邮件一起放到收件人的信箱里的(比如,如果你给他/她发了一个PNG的图片文件,他/她的信箱里会包含一个txt文件(电子邮件)和一个.png文件(附件)。但这不是它的工作原理。当你加入一个附件时,你的邮件程序把附件转换成纯文本文件,并在你写的内容(实际的电子邮件)后面插入这个文本块。这个,当你把所有的东西发出来后,收件人的信箱里只有一个纯文本文件——一个同时包含附件和实际电子邮件内容的文件。
下面是一个带附件(一个HTML文件)电子邮件的例子。
Return-Path:
Date: Mon, 22 May 2000 19:17:29 +0000
From: Someone
To: Person
Message-id: <83729KI93LI9214@example.com>
Content-type: multipart/mixed; boundary="396d983d6b89a"
Subject: Heres the subject
--396d983d6b89a
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
This is the body of the email.
--396d983d6b89a
Content-type: text/html; name=attachment.html
Content-disposition: inline; filename=attachment.html
Content-transfer-encoding: 8bit
This is the attached HTML file
--396d983d6b89a--
前面的7行是邮件的头,其中值得注意的是Content-type头部分。这个头告诉邮件程序电子邮件是由一个以上的部分组成的。不含附件的邮件只有一个部分:消息本身。带附件的电子通常至少由两部分组成:消息和附件。这样,带两个附件的邮件由三部分组成:消息,第一个附件和第二个附件。
带附件的电子邮件的不同部分之间用分界线来分隔。分界线在Content--type头中定义。邮件的每个新部分以两个连字号(--)和分界线开始。
最后一个分界线后也有两个连字号,表示这个邮件中没有其它的部分了。
在每个分界线后有一些行,用来告诉邮件程序这个部分的内容的类型。
比如,看看上面例子中第一个分界线后面的两行--以Content-type: text/plain开头的行。这些行说明后面的部分是ISO-8859-1字符集的纯文本。跟在第二个分界线后的行告诉邮件程序现在的部分是一个 HTML文件,它的名字是"attachment.html"。
Content-disposition这持告诉邮件程序如果可能就以内嵌的方式显示附件。现在新的邮件程序会在消息后显示HTML的内容。如果Content- disposition被设为attachment,那么邮件程序就不会显示HTML文件的内容,而是显示一个连接到文件的图标(或其它的类似的东西)。收件人要看附件的内容,必须点击这个图标。一般情况下,如果附件是一些文本(包含HTML),Content-disposition会被设为 inline,这是因为现在大部分邮件程序能够不借助其它浏览器而直接显示附件(文本)的内容。如果附件不是文本(比如图片或其它类似的内容), Content-disposition 就设为attachment。
2. 用PHP生成带附件的电子邮件
这里一个例子,告诉你如果把一个定义好的HTML文件加为邮件的附件:
# 我们首先写实际的消息内容
$emailBody = "This is text that goes into the body of the email.";
# 然后我们要作为附件的HTML文件
$attachment = "
This is the attached HTML file
";
# 建立在邮件中分隔不同部分的分界线。
# 基本上,分界线可以是任意的字符串。
# 但是重要的一点是确定一个写邮件的人
# 这会随意写出的字符串,所以我们用
# uniqid函数来产生一个随机的字符串。
$boundary = uniqid( "");
# 现在我们要建立邮件头。不要忘了插入
# Content-type头来说明这个邮件包含一个或更多的附件。
$headers = "From: someone@example.com
Content-type: multipart/mixed; boundary="$boundary"";
# さて、これでメールの内容はすべて揃いました。
# 次に、メールの本文を変更します。
$emailBody = "--$boundary
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
$メール本文
--$boundary
Content-type: text/html; name=attachment.html
Content-disposition: inline; filename=attachment.html
Content-transfer-encoding: 8bit
$添付ファイル
--$boundary--";
# これでメールを送信できるようになります
mail( "person@eksempel.dk", "The subject", $emailBody, $headers);
?>
3. ユーザーがアップロードしたファイルを添付ファイルとして添付します
上記の例はわかりにくいかもしれませんが、以下は…。以下の例では、フォームを使用してユーザーにファイルをアップロードさせ、送信する電子メールにそのファイルを添付しているため、状況はさらに困難になります。問題は、ファイルの MIME タイプが事前にわからないことです。
前の例では、それが HTML ファイルであることがすでにわかっているため、この添付ファイルの Content-type ヘッダーの設定は非常に簡単です。以下の例では、ユーザーが HTML ファイル、PNG ファイル、vCard ファイルなどをアップロードする可能性があるため、MIME タイプは任意である可能性があります。例を見てみましょう:
# 次に、フォームを生成しましょう。ファイルをアップロードできるフォームを生成するときは、
# を忘れずに入力してください
# ユーザーが「送信」ボタンを押した場合
if ($send) {
# 分割線を定義します
$boundary = uniqid( "");
# メールヘッダーを生成します
$headers = "From: $from
Content-type: multipart/mixed;boundary="$boundary"";
# アップロードされたファイルの MIME タイプを決定します
if ($attachment_type) $mimeType = $attachment_type;
# ブラウザがファイルの MIME タイプを指定しない場合は、
# 「application/unknown」に設定できます。
else $mimeType = "アプリケーション/不明";
# ファイルの名前を決定します
$fileName = $attachment_name;
# ファイルを開きます
$fp = fopen($attachment, "r");
# ファイル全体を変数に読み込みます
$read = fread($fp, filesize($attachment));
# さて、変数 $read にはファイルの内容全体を含むテキスト ブロックが保持されます。
# 次に、このテキスト ブロックを電子メール プログラムが読み取れる形式に変換する必要があります
# Base64 メソッドを使用してエンコードします
$read = Base64_encode($read);
# これで、base64 メソッドでエンコードされた長い文字列ができました。
# 次に、この長い文字列を 1 行あたり 76 文字で構成される小さなチャンクに分割します
$read = chunk_split($read);
# これでメールの本文を作成できます
$body = "--$boundary
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
$ボディ
--$boundary
コンテンツタイプ: $mimeType; name=$fileName
Content-disposition:attachment; filename=$fileName
Content-transfer-encoding:base64
$読む
--$boundary--";
# メールを送信する
mail($to, $subject, $body, $headers);
}
?>
以上です。上記の例がよく理解できない場合は、添付ファイル付きの電子メールを何通か自分に送信し、その電子メールのソース コードを注意深く調べることをお勧めします。