参考了一下网上的文章。俗话说,天下文章一大抄,看你会抄不会抄。关键是能为我所用,这是最重要的。废话不多讲,let‘s go。
其实发mail很简单,php有现成的函数,可以参考php 的 manual,特别是第四个例子,讲的很详细。
关键是怎么把上传附件跟邮件发送结合起来。关于文件的上传,可以参考http://blog.csdn.net/slamdunk3/archive/2005/02/23/299025.aspx 这篇文章。
讲一下 文件上传的方法及其属性:
我们假设文件上传字段的名称如上例所示,为 userfile。名称可随意命名。
表单里可以这样写:
提交之后,php利用$_FILES 数组 自动获取相关参数:
$_FILES['userfile']['name']
客户端机器文件的原名称。
$_FILES['userfile']['type']
文件的 MIME 类型,需要浏览器提供该信息的支持,例如“image/gif”。
$_FILES['userfile']['size']
已上传文件的大小,单位为字节。
$_FILES['userfile']['tmp_name']
文件被上传后在服务端储存的临时文件名。
$_FILES['userfile']['error']
和该文件上传相关的错误代码。['error'] 是在 PHP 4.2.0 版本中增加的。
注: 在 PHP 4.1.0 版本以前该数组的名称为 $HTTP_POST_FILES,它并不像 $_FILES 一样是自动全局变量。PHP 3 不支持 $HTTP_POST_FILES 数组。
当 php.ini 中的 register_globals 被设置为 on 时,您可以使用更多的变量。例如,$userfile_name 等价于 $_FILES['userfile']['name'],$userfile_type 等价于 $_FILES['userfile']['type'] 等。请记住从 PHP 4.2.0 开始,register_globals 的默认值为 off,因此我们建议您不要依赖于改设置项而使用刚刚提到的那些附加变量。
文件被上传后,默认地会被储存到服务端的默认临时目录中,除非您将 php.ini 中的 upload_tmp_dir 设置为了其它的路径。服务端的默认临时目录可以通过更改 PHP 运行环境的环境变量 TMPDIR 来重新设置,但是在 PHP 脚本内部通过运行 putenv() 函数来设置是不起作用的。该环境变量也可以用来确认其它的操作也是在上传的文件上进行的。
有了这些,我们再看与邮件相关的东西。下面是一个带附件(一个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: Here's 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。
我们仿照上面的例子,自己写一个php程序,可以对提交的 收信人,发送人,信件内容,附件进行处理。
首先建立一个静态页面,代码如下:
// 開啟檔案
$fp = fopen($file, "r");
// 把整個檔案讀進變數
$read = fread($fp, filesize($file ));
//我們用base64方法把它編碼
$read = base64_encode($read);
//把這個長字串切成由每行76個字元組成的小塊
$read = chunk_split($read);
//現在我們可以建立郵件的主體
$body = "--$boundary
Content-type: text/plain; charset=iso-8859 -1
Content-transfer-encoding: 8bit
$text
--$boundary
Content-type: $mimeType; name=$fileName
Content-disposition: attachment; filename=$ fileName
Content-transfer-encoding: base64
$read
--$boundary--";
//發送郵件
if(mail($to, $subject,$body, $headers))
print "OK! the mail $from --- $to has been send
";
else
print "fail to send mail
";
? >
我看不明白沒關係,我來說明一下:
1,郵件頭的構造:一般包括
內容類型(Content-type)要發送附件,設定為multipart/mixed 意思是多個部分(郵件本身+附件)。
boundary ,就是上面提到的分界線,他的值用php自帶的 uniqid();函數取得
接受方,抄送等,在後面加上 From: Cc:。與上面的 Content-type boundary 之間用 rn 分割 。
2 郵件體
如果是純文字的郵件內容它的格式如下:
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
後面再緊接著加上郵件的文字內容。
如果是附件:
Content-type: $mimeType; name=$fileName
Content-disposition: attachment; filename=$fileName
Content-transfer-encoding: base64
後面再緊接著加上附件內容。
$mimeType 是附件的 MIME類型。 可以用 $_FILES['upload_file']['type'] 得到。
$fileName 就是附件的名字了
郵件文字內容和附件之間用 boundary 分割。
有人會問,附件內容是什麼?附件內容就是用read函數讀入所上傳的附件,然後再把它經過base64編碼之後再用chunk_split 大卸N塊,每塊大小是預設的76字元。
好了,現在再去看那段程序,應該沒什麼問題了吧?把對應的變數帶入mail函數裡面就ok了。
以上程式在 PHP Version 4.3.8 freeBSD 下測試通過。
參考文章:《php 發送附附件的郵件 作者: cn-linux》