需要明确的是,我没有写这段代码,这是以前的开发人员写的。无论如何,我的客户在通过他们的表单上传时没有收到图像,只是一个带有错误消息的红框。
根据请求,这里是完整的代码:
<?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.0n";
$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: PHP4n";
$headers .= "X-Priority: 3n"; //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_partsn";
$message .= "Content-Type: text/plain; charset="iso-8859-1"n";
$message .= "Content-Transfer-Encoding: quoted-printablen";
$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_telephonenn";
$message .= "$addressnn";
$message .= "$bodyn";
$message .= "n";
$message .= "------=MIME_BOUNDRY_message_parts--n";
$message .= "n";
$message .= "------=MIME_BOUNDRY_main_messagen";
$message .= "Content-Type: application/octet-stream;ntname="" . $attachment_name . ""n";
$message .= "Content-Transfer-Encoding: base64n";
$message .= "Content-Disposition: attachment;ntfilename="" . $attachment_name . ""nn";
$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();
}
?>
我完全被这段代码弄糊涂了,因为我没有写它,也无法解密为什么"$attachment_name"one_answers"$attachement_name"是单独的字符串,如果我把"attachmentname"改为"attachment",我的问题会得到解决吗?
您的代码似乎对我有效,但也存在一些潜在的问题。我认为最重要的一点可能是图像是使用不正确的Content-Type:
发送的,但下面还详细介绍了一些其他问题。
图像类型
$message .= "Content-Type: application/octet-stream;ntname="" . $attachment_name . ""n";
当没有合适的内容类型或内容类型未知时,application/octet-stream
被用作发送任意二进制数据的最后手段。您应该使用正确的图像类型:
$message .= "Content-Type: " . $_FILES['attachement']['type']
. ";ntname="" . $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 messagen";
exit;
}
MIME语法
$headers .= "X-Priority: 3n"; //1 = Urgent, 3 = Normal $headers .= "Return-Path: <" . $_POST['from_email'] . ">n"; $headers .= "This is a multi-part message in MIME format.n";
Return-Path:
是您的最后一个标头。下一行是消息正文的一部分。您需要一个空行来分隔邮件正文和邮件头。例如:
$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_partsn";
请注意,如果确实将上面的一些行移动到$message
,则需要在Content-Type:
标头之后插入一个额外的换行符。
$attachment = $_FILES['attachment']['tmp_name']; $attachment_name = $_FILES['attachment']['name']; ... $message .= "Content-Disposition: attachment;ntfilename="" . $attachment_name . ""nn";
$attachment_name
由浏览器发送,通常是用户上传的文件的原始名称。$attachment
是将图像存储在服务器上的临时文件的名称。两者完全不同,不能互换。
您可能希望从这些变量中去掉控制字符(如换行符)和双引号,以防止恶意用户破坏标头的语法。
行尾
根据Mail语法,行应该以CRLF
("rn"
)序列结尾,但不清楚在调用mail()
函数时应该使用哪一行结尾。PHP文档中写道:
如果未收到消息,请尝试仅使用
LF
(n
)。一些Unix邮件传输代理(最著名的是»qmail)会自动将LF
替换为CRLF
(如果使用CRLF
,则会导致CR
加倍)。这应该是最后的手段,因为它不符合»RFC 2822。
$_POST[]数据
您不应该在邮件头中使用来自$_POST[]
的原始数据。恶意用户可以很容易地插入自己的标头(如Bcc:
),将垃圾邮件发送到任意地址。您至少应该过滤掉控制字符(如换行符),还可以根据使用情况过滤或转义尖括号和双引号。