简体   繁体   English

未发送 PHP 邮件图像附件

[英]PHP Mail Image attachment not being sent

Just to be clear - I didn't write this code, this is from a previous developer.只是要清楚 - 我没有编写此代码,这是来自以前的开发人员。 Anyway, my client isn't receiving images when uploaded via their form, just a red box with an error message.无论如何,我的客户在通过表单上传时没有收到图像,只是一个带有错误消息的红色框。

As per request here is the whole code:根据请求,这里是整个代码:

<?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();
}

?>

I'm completely confused by this code as I didn't write it and can't decrypt why "$attachment" and "$attachment_name" are separate strings, if I change the "attachment_name" to "attachment" will my problems be fixed?我完全被这段代码弄糊涂了,因为我没有写它并且无法解密为什么“$attachment”和“$attachment_name”是单独的字符串,如果我将“attachment_name”更改为“attachment”,我的问题将得到解决?

The code that you have seems to work for me, but there are a few potential problems.您拥有的代码似乎对我有用,但存在一些潜在问题。 I think perhaps the most important one is that the image is sent using an incorrect Content-Type: , but there are also some other issues detailed below.我认为也许最重要的是图像是使用不正确的Content-Type: ,但下面还详细介绍了一些其他问题。

Image type图像类型

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

The application/octet-stream is used as a last resort for sending arbitrary binary data when there is no appropriate content type, or the content type is unknown.当没有合适的内容类型或内容类型未知时, application/octet-stream用作发送任意二进制数据的最后手段。 You should use a proper image type:您应该使用正确的图像类型:

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

If you want to prevent users from mailing arbitrary files, you can use a white-list:如果你想阻止用户邮寄任意文件,你可以使用白名单:

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 syntax 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";

The Return-Path: is the last of your headers. Return-Path:是最后一个标题。 The next line is part of the message body .下一行是消息正文的一部分。 You need a blank line to separate the message body from the headers.您需要一个空行来将邮件正文与标题分开。 Eg:例如:

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

Personally, I would add the message body to $message instead.就个人而言,我会将消息正文添加到$message The mail() function doesn't care, it just concatenates the headers and message with a line break. mail()函数并不关心,它只是用换行符连接标题和消息。 See more about line endings below.请参阅下面有关行尾的更多信息。


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

Note that if you do move some of the lines above to $message , you need to insert an extra line break after the Content-Type: header.请注意,如果您确实将上面的某些行移动到$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 is sent by the browser and is typically the original name of the file uploaded by the user. $attachment_name由浏览器发送,通常是用户上传的文件的原始名称。 $attachment is the name of the temporary file where the image is stored on the server . $attachment服务器上存储图像的临时文件的名称。 The two are entirely different and are not interchangeable.两者完全不同,不可互换。

You may want to strip control characters (such as line breaks) and double quotes from these variables to prevent malicious users from disrupting the syntax of the headers.您可能希望从这些变量中去除控制字符(例如换行符)和双引号,以防止恶意用户破坏标头的语法。

Line endings行尾

According to the Mail syntax , lines should be terminated with a CRLF ( "\\r\\n" ) sequence, but it is not clear which line ending should be used when calling the mail() function.根据Mail 语法,行应该以CRLF ( "\\r\\n" ) 序列结束,但不清楚在调用mail()函数时应该使用哪个行结尾。 The PHP documentation says: PHP 文档说:

If messages are not received, try using a LF ( \\n ) only.如果未收到消息,请尝试仅使用LF ( \\n )。 Some Unix mail transfer agents (most notably » qmail ) replace LF by CRLF automatically (which leads to doubling CR if CRLF is used).一些 Unix 邮件传输代理(最著名的是» qmail )自动用CRLF替换LF (如果使用CRLF ,这会导致CR加倍)。 This should be a last resort, as it does not comply with » RFC 2822 .这应该是最后的手段,因为它不符合» RFC 2822

$_POST[] data $_POST[] 数据

You should not use raw data from $_POST[] in your mail headers.您不应在邮件标头中使用来自$_POST[]原始数据。 A malicious user could easily insert their own headers (such as Bcc: ) to send spam to arbitrary addresses.恶意用户可以轻松插入他们自己的标头(例如Bcc: )以将垃圾邮件发送到任意地址。 You should at least filter out control characters (such as line breaks) and perhaps also filter or escape angle brackets and double quotes depending on usage.您至少应该过滤掉控制字符(例如换行符),并且可能还根据使用情况过滤或转义尖括号和双引号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM