0

用PHP发送有附件的电子邮件

Posted in PHP at 十一月 10th, 2008 / No Comments »

我经常听到这样一个问题:”我有一个从网站发来之合同。我如何给通过表单发送之电子邮件增加一个附件呢?”
  
  首先我要说之是要做到这个没有什么简单之办法。你要很好之理解PHP或其它之服务器端之脚本语言。当然你还要一个真正支持PHP之网站之账号。如果满足了这个前提,在你读完了本章后就可以用PHP发送带附件之电子邮件了。
  
  1. 附件是如何工作之
  
  如果你曾经在PHP之手册中搜索过”附件”函数,那么结果可能是什么都没有(至少在我写本文之时间还没有)。后来你就要花很多时间来了解这方面之知识。
  
  你也许会想当你给某个人发送一封带附件之电子邮件时,附件是和邮件一起放到收件人之信箱里之(比如,如果你给他/她发了一个PNG之图片文件,他/她之信箱里会包含一个txt文件(电子邮件)和一个.png文件(附件))。但这不是它之工作原理。当你加入一个附件时,你之邮件程序把附件转换成纯文本文件,并在你写之内容(实际之电子邮件)后面插入这个文本块。这个,当你把所有之东西发出来后,收件人之信箱里只有一个纯文本文件–一个同时包含附件和实际电子邮件内容之文件。
  
  下面是一个带附件(一个HTML文件)电子邮件之例子。我已经标注了其中重要之几行:
  
  Return-Path: <someone@example.com>
  Date: Mon, 22 May 2000 19:17:29 +0000
  From: Someone <someone@example.com>
  To: Person <person@eksempel.dk>
  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
  
  <html>
  <head>
  <title>The attachment</title>
  </head>
  <body>
  <h2>This is the attached HTML file</h2>
  </body>
  </html>
  
  –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文件加为邮件之附件:
  
  <?php
  # 我们首先写实际之消息内容
  $emailBody = “This is text that goes into the body of the email.”;

  
  # 然后我们要作为附件之HTML文件
  $attachment = “<html>
  <head>
  <title>The attached file</title>
  </head>
  <body>
  <h2>This is the attached HTML file</h2>
  </body>
  </html>”;
  
  # 建立在邮件中分隔不同部分之分界线。
  # 基本上,分界线可以是任意之字符串。
  # 但是重要之一点是确定一个写邮件之人
  # 这会随意写出之字符串,所以我们用
  # 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
  
  $emailBody
  
  –$boundary
  Content-type: text/html; name=attachment.html
  Content-disposition: inline; filename=attachment.html
  Content-transfer-encoding: 8bit
  
  $attachment
  
  –$boundary–”;

  
  # 现在可以把邮件发出去了
  mail( “person@eksempel.dk“, “The subject”, $emailBody, $headers);
  ?>
  
  
  
  3. 把用户上传之文件作为附件
  
  你也许会觉得上面之例子难以理解,但下面…。在下面之例子中事情更难了,因为我们要用一个表单让用户上传他们之文件,并把这个文件作为我们要发之邮件之附件。麻烦之是我们不能预先知道文件之MIME类型。在前面之例子中,我们已经知道该它是一个HTML文件,所以给这个附件设置Content-type头是很简单之。在下面之例子中,MIME类型可能是任意之,因为用户可能会上传一个HTML文件,一个PNG文件,一个vCard文件,或者其它之东西。让我们来看看例子:
  
  <?php
  # 现在我们来生成表单。在产生可以上传文件之表单时,
  # 不要忘了把<form>标签之”enctype”属性设为”multipart/form-data”.
  echo “<form action=’$PHP_SELF’ enctype=’multipart/form-data’ method=’post’>\n”;
  echo “<input type=’text’ name=’from’><br>\n”;
  echo “<input type=’text’ name=’to’><br>\n”;

  echo “<input type=’text’ name=’subject’><br>\n”;
  echo “<input type=’file’ name=’attachment’><br>\n”;
  echo “<textarea name=’body’></textarea><br>\n”;
  echo “<input type=’submit’ name=’send’ value=’Send’>\n”;
  echo “</form>\n”;
  
  # 如果用户已经按了”Send”按钮”
  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 = “application/unknown”;
  
   # 确定文件之名字
   $fileName = $attachment_name;
  
   # 打开文件
   $fp = fopen($attachment, “r”);
   # 把整个文件读入一个变量
   $read = fread($fp, filesize($attachment));
  
   # 好,现在变量$read中保存之是包含整个文件内容之文本块。
  # 现在我们要把这个文本块转换成邮件程序可以读懂之格式
  # 我们用base64方法把它编码
   $read = base64_encode($read);
  
   # 现在我们有一个用base64方法编码之长字符串。
  # 下一件事是要把这个长字符串切成由每行76个字符组成之小块

   $read = chunk_split($read);
  
   # 现在我们可以建立邮件之主体
   $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–”;
  
   # 发送邮件
   mail($to, $subject, $body, $headers);
  }
  ?>
  
  
  这就是全部内容。如果你不能很好之理解上面之例子,我之建议是给你自己发送几个带附件之邮件,然后仔细研究邮件之源代码。

Published in PHP

No Responses to “用PHP发送有附件的电子邮件”

Leave a Reply

请输入算式结果(看不清请点击图片)
(必须)