我经常听到这样一个问题:“我有一个从网站发来的合同。我如何给
通过表单发送的电子邮件增加一个附件呢?”
首先我要说的是要做到这个没有什么简单的办法。你要很好的理解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"";
# Ok, now we have all the contents of the email.
# The next thing to do is modify the body of the email.
$emailBody = "--$boundary
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
$emailBody
--$boundary
Content-type: text/html; name=attachment.html
Content-disposition: inline; filename=attachment.html
Content-transfer-encoding: 8bit
$attachment
--$boundary--";
# Now you can send the email
mail( "person@eksempel.dk", "The subject", $emailBody, $headers);
?>
3. Attach files uploaded by users as attachments
You may find the above example difficult to understand, but below... In the example below things are even harder because we are using a form to let users upload their file and attaching the file to the email we are sending. The trouble is that we don't know the MIME type of the file in advance.
In the previous example, we already know that it is an HTML file, so setting the Content-type header for this attachment is very simple. In the example below, the MIME type could be arbitrary, since the user might upload an HTML file, a PNG file, a vCard file, or something else. Let’s take a look at an example:
# Now let’s generate the form. When generating a form that can upload files,
# don’t forget to put
# If the user has pressed the "Send" button"
if ($send) {
# Define the boundary
$boundary = uniqid( "");
# Generate email headers
$headers = "From: $from
Content-type: multipart/mixed; boundary="$boundary"";
# Determine the MIME type of the uploaded file
if ($attachment_type) $mimeType = $attachment_type;
# If the browser does not specify the MIME type of the file,
# we can set it to "application /unknown".
else $mimeType = "application/unknown";
# Determine the name of the file
$fileName = $attachment_name;
# Open the file
$fp = fopen($attachment, "r");
# Read the entire file into a variable
$read = fread($fp, filesize($attachment)) ;
# Okay, now the variable $read holds the text block containing the entire file content.
# Now we need to convert this text block into a format that the mail program can read
# We use the base64 method to encode it
$read = base64_encode($read);
# Now we have a long string encoded using the base64 method.
# The next thing is to cut this long string into small chunks consisting of 76 characters per line
$read = chunk_split($read);
# Now we can create the body of the email
$body = "--$boundary
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
$body
--$boundary
Content-type: $mimeType; name=$fileName
Content-disposition: attachment; filename=$fileName
Content-transfer-encoding: base64
$read
--$boundary--";
# Send email
mail($to, $subject, $body, $headers);
}
?>
That’s all. If you don't understand the above example well, my suggestion is to send yourself a few emails with attachments and then carefully study the source code of the emails.