51

我有一个简单的 PHP 邮件程序脚本,它从通过 POST 提交的表单中获取值并将它们邮寄给我:

<?php
$to = "me@example.com";

$name = $_POST['name'];
$message = $_POST['message'];
$email = $_POST['email'];

$body  =  "Person $name submitted a message: $message";
$subject = "A message has been submitted";

$headers = 'From: ' . $email;

mail($to, $subject, $body, $headers);

header("Location: http://example.com/thanks");
?>

如何清理输入?

4

5 回答 5

53

用 清理 post 变量filter_var()

这里的例子。像:

echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);   
于 2009-06-28T18:40:42.600 回答
13

由于您没有在此处构建 SQL 查询或任何内容,因此我可以看到的对这些输入的唯一相关验证是 $_POST["email"] 的电子邮件验证,如果您真的需要,可能在其他字段上使用字母数字过滤器限制消息可以包含的范围。

要过滤电子邮件地址,只需使用filter_var

$email = filter_var($email, FILTER_SANITIZE_EMAIL);

根据 Frank Farmer 的建议,您还可以过滤掉电子邮件主题中的换行符:

$subject = str_replace(array("\r","\n"),array(" "," "),$subject);
于 2009-06-28T18:42:46.153 回答
5

正如其他人所指出的那样,filter_var很棒。如果它不可用,请将其添加到您的工具箱中。

$headers变量在安全方面特别糟糕。它可以附加到并导致添加欺骗标题。这篇名为Email Injection的帖子很好地讨论了它。

filter_var i很棒,但另一种确保某事是电子邮件地址而不是坏事的方法是使用isMail()函数。这是一个:

function isEmail($email) {
    return preg_match('|^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]{2,})+$|i', $email);
};

所以要使用它,你可以这样做:

if (isset($_POST['email']) && isEmail($_POST['email'])) {
    $email = $_POST['email'] ;
} else {
    // you could halt execution here, set $email to a default email address
    // display an error, redirect, or some combination here,
}

在手动验证方面,使用substr()、running限制长度strip_tags()以及以其他方式限制可以放入的内容。

于 2009-06-28T19:09:20.330 回答
4

您需要从用户在 $headers 中提供的输入中删除任何换行符,这些换行符会传递给 mail()(在您的情况下为 $email)!请参阅电子邮件注入

PHP 应该负责清理 $to 和 $subject,但有些版本的 PHP 存在错误(受影响的是 PHP 4 <= 4.4.6 和 PHP 5 <= 5.2.1,请参阅MOPB-34-2007)。

于 2009-08-25T16:59:59.780 回答
1

您可以使用artlung上面答案中的代码来验证电子邮件..

我使用这种代码来防止标头注入..

// define some mail() header's parts and commonly used spam code to filter using preg_match
$match = "/(from\:|to\:|bcc\:|cc\:|content\-type\:|mime\-version\:|subject\:|x\-mailer\:|reply\-to\:|\%0a|\%0b)/i";

// check if any field's value containing the one or more of the code above
if (preg_match($match, $name) || preg_match( $match, $message) || preg_match( $match, $email)) {

// I use ajax, so I call the string below and send it to js file to check whether the email is failed to send or not
echo "failed";

// If you are not using ajax, then you can redirect it with php header function i.e: header("Location: http://example.com/anypage/");

// stop the script before it reach or executing the mail function
die();

}

上面的mail()'s header 过滤过于严格,因为某些用户可能在他们的消息中使用过滤后的字符串,而无意劫持您的电子邮件表单,因此将其重定向到一个页面,该页面解释了哪些类型的字符串不允许在表格或在您的表格页面上解释它。

于 2014-06-09T13:19:51.570 回答