请注意 - 我没有编写此代码,这是来自之前的开发人员。 无论如何,我的客户通过他们的表单上传时没有收到图片,只是一个带有错误信息的红色框。
根据要求,这里是整个代码:
<?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;我的问题会解决吗?
答案 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;
}
$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";
就个人而言,我会将邮件正文添加到$message
。 mail()
函数并不关心,它只是将标题和消息与换行符连接起来。请参阅以下有关行结尾的更多信息。
$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。
您不应在邮件标题中使用CRLF
中的原始数据。恶意用户可以轻松插入自己的标头(例如$_POST[]
)以将垃圾邮件发送到任意地址。您至少应该过滤掉控制字符(例如换行符),也可以根据用途过滤或转义尖括号和双引号。