PHP邮件图像附件未发送

时间:2014-09-04 11:14:12

标签: php image forms email email-attachments

请注意 - 我没有编写此代码,这是来自之前的开发人员。 无论如何,我的客户通过他们的表单上传时没有收到图片,只是一个带有错误信息的红色框。

根据要求,这里是整个代码:

<?php

function sendMail() {
  if (!isset ($_POST['to_email'])) { //Oops, forgot your email addy!
    die ("<p>Oops!  You forgot to fill out the email address! Click on the back arrow to go back</p>");
  }
  else {
    $to_name = stripslashes($_POST['to_name']);
    $from_name = stripslashes($_POST['from_name']);
    $from_telephone = stripslashes($_POST['from_telephone']);
    $subject = stripslashes($_POST['subject']);
    $body = stripslashes($_POST['body']);
    $address = stripslashes($_POST['address']);
    $to_email = $_POST['to_email'];
    $attachment = $_FILES['attachment']['tmp_name'];
    $attachment_name = $_FILES['attachment']['name']; 
    if (is_uploaded_file($attachment)) { //Do we have a file uploaded?
      $fp = fopen($attachment, "rb"); //Open it
      $data = fread($fp, filesize($attachment)); //Read it
      $data = chunk_split(base64_encode($data)); //Chunk it up and encode it as base64 so it can emailed
      fclose($fp);
    }
    //Let's start our headers
    $headers = "From: $from_name<" . $_POST['from_email'] . ">\n";
    $headers .= "Reply-To: <" . $_POST['from_email'] . ">\n"; 
    $headers .= "MIME-Version: 1.0\n";
    $headers .= "Content-Type: multipart/related; type=\"multipart/alternative\"; boundary=\"----=MIME_BOUNDRY_main_message\"\n"; 
    $headers .= "X-Sender: $from_name<" . $_POST['from_email'] . ">\n";
    $headers .= "X-Mailer: PHP4\n";
    $headers .= "X-Priority: 3\n"; //1 = Urgent, 3 = Normal
    $headers .= "Return-Path: <" . $_POST['from_email'] . ">\n"; 
    $headers .= "This is a multi-part message in MIME format.\n";
    $headers .= "------=MIME_BOUNDRY_main_message \n"; 
    $headers .= "Content-Type: multipart/alternative; boundary=\"----=MIME_BOUNDRY_message_parts\"\n"; 

    $message = "------=MIME_BOUNDRY_message_parts\n";
    $message .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n"; 
    $message .= "Content-Transfer-Encoding: quoted-printable\n"; 
    $message .= "\n"; 
    /* Add our message, in this case it's plain text.  You could also add HTML by changing the Content-Type to text/html */
    $message .= "Return call on: $from_telephone\n\n";
    $message .= "$address\n\n";
    $message .= "$body\n";
    $message .= "\n"; 
    $message .= "------=MIME_BOUNDRY_message_parts--\n"; 
    $message .= "\n"; 
    $message .= "------=MIME_BOUNDRY_main_message\n"; 
    $message .= "Content-Type: application/octet-stream;\n\tname=\"" . $attachment_name . "\"\n";
    $message .= "Content-Transfer-Encoding: base64\n";
    $message .= "Content-Disposition: attachment;\n\tfilename=\"" . $attachment_name . "\"\n\n";
    $message .= $data; //The base64 encoded message
    $message .= "\n"; 
    $message .= "------=MIME_BOUNDRY_main_message--\n"; 

    // send the message
    mail("$to_name<$to_email>", $subject, $message, $headers); 
    print "<p align=\"center\">Thank you for your email.</p>";
  }
}

switch ($action) {
  case "send":
    showForm();
    sendMail();
    break;
  default:
    showForm();
}

?>

我完全被这段代码搞糊涂了,因为我没有写它,也无法解密为什么&#34; $ attachment&#34;和&#34; $ attachment_name&#34;是单独的字符串,如果我更改&#34; attachment_name&#34;到&#34;附件&#34;我的问题会解决吗?

1 个答案:

答案 0 :(得分:0)

您拥有的代码似乎对我有用,但有一些潜在的问题。我想也许最重要的一点是图像是使用不正确的Content-Type:发送的,但下面还有其他一些问题。

图像类型

$message .= "Content-Type: application/octet-stream;\n\tname=\"" . $attachment_name . "\"\n";

当没有适当的内容类型或内容类型未知时,application/octet-stream用作发送任意二进制数据的最后手段。您应该使用正确的图像类型:

$message .= "Content-Type: " . $_FILES['attachement']['type']
            . ";\n\tname=\"" . $attachment_name . "\"\n";

如果您想阻止用户邮寄任意文件,可以使用白名单:

if (is_uploaded_file($attachment) &&
    in_array ($attachment_type, array ('image/gif', 'image/png', 'image/jpg', 'image/jpeg'))) {
  $fp = fopen($attachment, "rb"); //Open it
  $data = fread($fp, filesize($attachment)); //Read it
  $data = chunk_split(base64_encode($data)); //Chunk it up and encode it as base64 so it can emailed
  fclose ($fp); 
} else {
  echo "<p>Useful error message\n";
  exit;
}

MIME语法

$headers .= "X-Priority: 3\n"; //1 = Urgent, 3 = Normal
$headers .= "Return-Path: <" . $_POST['from_email'] . ">\n"; 
$headers .= "This is a multi-part message in MIME format.\n";

Return-Path:是您的最后一个标题。下一行是消息 body 的一部分。您需要一个空行来将邮件正文与标题分开。例如:

$headers .= "Return-Path: <" . $_POST['from_email'] . ">\n"; 
$headers .= "\n";
$headers .= "This is a multi-part message in MIME format.\n";

就个人而言,我会将邮件正文添加到$messagemail()函数并不关心,它只是将标题和消息与换行符连接起来。请参阅以下有关行结尾的更多信息。


$headers .= "------=MIME_BOUNDRY_main_message \n"; 
$headers .= "Content-Type: multipart/alternative; boundary=\"----=MIME_BOUNDRY_message_parts\"\n"; 
$message = "------=MIME_BOUNDRY_message_parts\n";

请注意,如果您确实将上面的某些行移至$message,则需要在Content-Type:标题后插入额外的换行符。


$attachment = $_FILES['attachment']['tmp_name'];
$attachment_name = $_FILES['attachment']['name']; 

...

$message .= "Content-Disposition: attachment;\n\tfilename=\"" . $attachment_name . "\"\n\n";

$attachment_name由浏览器发送,通常是用户上传的文件的原始名称。 $attachment是在服务器上存储图像的临时文件的名称。两者完全不同,不可互换。

您可能希望从这些变量中删除控制字符(例如换行符)和双引号,以防止恶意用户破坏标题的语法。

行结尾

根据Mail syntax,行应以CRLF"\r\n")序列终止,但在调用{{1}时不清楚应该使用哪一行结尾功能。 PHP documentation说:

  

如果未收到消息,请尝试仅使用mail()LF)。一些Unix邮件传输代理(最值得注意的是» qmail)会自动将\n替换为LF(如果使用CRLF,则会导致CR加倍。这应该是最后的手段,因为它不符合» RFC 2822

$ _ POST []数据

您不应在邮件标题中使用CRLF中的原始数据。恶意用户可以轻松插入自己的标头(例如$_POST[])以将垃圾邮件发送到任意地址。您至少应该过滤掉控制字符(例如换行符),也可以根据用途过滤或转义尖括号和双引号。