POST 使用特殊字符时联系表单丢失数据
POST contact form missing data when special character is used
我正在使用一个简单的联系表:http://luiszuno.com/previews/formy/
问题是,每当在表单上键入字符“&”时,电子邮件中都不会收到“&”之后的其余消息。编辑:添加了代码,表单除了丢失数据问题外工作正常。是什么导致了这个问题?
jQuery(document).ready(function($) {
$("#formy").on( "submit", function( event ) {
$(this).serialize();
});
// Hide messages
$("#formy-success").hide();
$("#formy-error").hide();
$("input,textarea").blur(function(){
$(this).css("border-color","#596a87");
});
// on submit...
$("#formy #submit").click(function() {
$(this).serialize();
// Required fields:
//name
var name = $("#name").val();
if(name == "" || name == "Name *"){
$("#name").focus();
$("#formy-error").fadeIn().text("Name required");
$("#name").css("border-color","#a22528");
return false;
}
else {$("#name").css("border-color","#596a87");}
// email
var email = $("#email").val();
if(email == "" || email == "Email *"){
$("#email").focus();
$("#formy-error").fadeIn().text("Email required");
$("#email").css("border-color","#a22528");
return false;
}
else {$("#email").css("border-color","#596a87");}
// email validation
function validateEmail(email) {
var filter = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
return filter.test(email);
}
if (!validateEmail(email)) {
$("#formy-error").fadeIn().text("Invalid email address");
$("#email").css("border-color","#a22528");
return false;
}
//budget
var budget = $("#budget").val();
if(budget == "" || budget == "Budget"){
return false;
}
// comments
var comments = $("#comments").val();
if(comments == "" || comments == "Message *"){
$("#comments").focus();
$("#formy-error").fadeIn().text("Message required");
$("#comments").css("border-color","#a22528");
return false;
}
else {$("#comments").css("border-color","#596a87");}
// send mail php
var sendMailUrl = $("#sendMailUrl").val();
// Retrieve values for to, from & subject at the form
var to = $("#to").val();
var from = $("#from").val();
var subject = $("#subject").val();
// Create the data string
var dataString = 'name=' + name
+ '&email=' + email
+ '&comments=' + comments
+ '&to=' + to
+ '&from=' + from
+ '&budget=' + budget
+ '&subject=' + subject;
// ajax
$.ajax({
type:"POST",
url: sendMailUrl,
data: dataString,
success: success()
});
});
// On success...
function success(){
$("#formy-success").fadeIn(250).text("Thanks, I will contact you soon!");
$("#formy-error").hide();
$("#formy fieldset").slideUp(250);
}
return false;
});
发送-mail.php
<?php header("Content-Type: text/html; charset=utf-8");
//vars
$subject = $_POST['subject'];
$to = explode(',', $_POST['to'] );
$from = $_POST['email'];
//data
$msg = "NAME: " .$_POST['name'] ."<br>\n";
$msg .= "EMAIL: " .$_POST['email'] ."<br>\n";
$msg .= "BUDGET: " .$_POST['budget'] ."<br>\n";
$msg .= "COMMENTS: " .$_POST['comments'] ."<br>\n";
//Headers
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=UTF-8\r\n";
$headers .= "From: <".$from. ">" ;
//send for each mail
foreach($to as $mail){
mail($mail, $subject, $msg, $headers);
}
?>
按照@ADyson 的建议使用 encodeURIComponent() 修复了使用联系表单时收到的电子邮件中丢失的 data/urls。
var comments = $("#comments").val();
var e_comments = encodeURIComponent(comments);
您的问题是您是手动构建数据字符串,而不是对插入到字符串中的数据值进行 URI 编码。因此,文本中的任何原始 &
字符都将被假定为 URI 的一部分,而不是数据的一部分,这意味着它将被解释为指示下一个参数的开始,而不仅仅是文本中的一个字符。 URI 编码此数据会将此和其他特殊字符转换为它们的编码等价物,因此它们不会被误解。
现在,您当然可以通过用 encodeURIComponent()
包装每个字段变量来解决这个问题,但这是冗长乏味的:
var dataString = 'name=' + encodeURIComponent(name)
+ '&email=' + encodeURIComponent(email)
+ '&comments=' + encodeURIComponent(comments)
+ '&to=' + encodeURIComponent(to)
+ '&from=' + encodeURIComponent(from)
+ '&budget=' + encodeURIComponent(budget)
+ '&subject=' + encodeURIComponent(subject);
有更好的方法:
目前,您的 $(this).serialize();
将不起作用,因为 this
代表单击的按钮,而不是表单。但是,如果您将它指向表单,您可以使用它轻松地自动序列化其中的字段,并且 jQuery 将代表您处理任何编码问题。这节省了手动编码和单独获取每个字段值的代码(尽管我注意到你目前需要这个来进行验证,尽管还有其他方法可以实现验证,这将消除这种需要,但这完全是另一个话题)。
$.ajax({
type:"POST",
url: sendMailUrl,
data: $("#formy").serialize(),
success: success //Unrelated: I also removed the brackets here, so it becomes a _reference_ to the "success" function - writing success() as you did means the function is immediately executed, and what gets passed to jQuery is the _result_ of the function, which isn't what you want in this case
});
如您所见,这样就省事多了。如果您将来向表单中添加更多字段,则根本不必更改这段代码。
另一方面 - 使用 JavaScript 验证表单输入会很麻烦。这很好而且用户友好,但它没有提供任何安全性。在服务器端,您似乎很乐意将浏览器直接发送的任何值插入到您的电子邮件中。任何具有少量知识的用户都可以使用他们的开发工具修改您的 JavaScript,或者关闭 JS,或者完全使用其他工具(例如 PostMan 或自定义应用程序)在您的服务器上触发 HTTP 请求,而无需曾经触摸过你的表格。他们可能会发送有问题的值,这可能会搞砸您的电子邮件 - 例如一个不同的 "from" 值,或者一些讨厌的 HTML,或者如果您在应用程序的任何地方与数据库交互,请执行 SQL 注入攻击来搞砸它。您应该 始终 验证 PHP 代码中的所有传入数据是否存在安全问题,并确保它符合您的业务规则,然后再将其用于其他用途。
我正在使用一个简单的联系表:http://luiszuno.com/previews/formy/ 问题是,每当在表单上键入字符“&”时,电子邮件中都不会收到“&”之后的其余消息。编辑:添加了代码,表单除了丢失数据问题外工作正常。是什么导致了这个问题?
jQuery(document).ready(function($) {
$("#formy").on( "submit", function( event ) {
$(this).serialize();
});
// Hide messages
$("#formy-success").hide();
$("#formy-error").hide();
$("input,textarea").blur(function(){
$(this).css("border-color","#596a87");
});
// on submit...
$("#formy #submit").click(function() {
$(this).serialize();
// Required fields:
//name
var name = $("#name").val();
if(name == "" || name == "Name *"){
$("#name").focus();
$("#formy-error").fadeIn().text("Name required");
$("#name").css("border-color","#a22528");
return false;
}
else {$("#name").css("border-color","#596a87");}
// email
var email = $("#email").val();
if(email == "" || email == "Email *"){
$("#email").focus();
$("#formy-error").fadeIn().text("Email required");
$("#email").css("border-color","#a22528");
return false;
}
else {$("#email").css("border-color","#596a87");}
// email validation
function validateEmail(email) {
var filter = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
return filter.test(email);
}
if (!validateEmail(email)) {
$("#formy-error").fadeIn().text("Invalid email address");
$("#email").css("border-color","#a22528");
return false;
}
//budget
var budget = $("#budget").val();
if(budget == "" || budget == "Budget"){
return false;
}
// comments
var comments = $("#comments").val();
if(comments == "" || comments == "Message *"){
$("#comments").focus();
$("#formy-error").fadeIn().text("Message required");
$("#comments").css("border-color","#a22528");
return false;
}
else {$("#comments").css("border-color","#596a87");}
// send mail php
var sendMailUrl = $("#sendMailUrl").val();
// Retrieve values for to, from & subject at the form
var to = $("#to").val();
var from = $("#from").val();
var subject = $("#subject").val();
// Create the data string
var dataString = 'name=' + name
+ '&email=' + email
+ '&comments=' + comments
+ '&to=' + to
+ '&from=' + from
+ '&budget=' + budget
+ '&subject=' + subject;
// ajax
$.ajax({
type:"POST",
url: sendMailUrl,
data: dataString,
success: success()
});
});
// On success...
function success(){
$("#formy-success").fadeIn(250).text("Thanks, I will contact you soon!");
$("#formy-error").hide();
$("#formy fieldset").slideUp(250);
}
return false;
});
发送-mail.php
<?php header("Content-Type: text/html; charset=utf-8");
//vars
$subject = $_POST['subject'];
$to = explode(',', $_POST['to'] );
$from = $_POST['email'];
//data
$msg = "NAME: " .$_POST['name'] ."<br>\n";
$msg .= "EMAIL: " .$_POST['email'] ."<br>\n";
$msg .= "BUDGET: " .$_POST['budget'] ."<br>\n";
$msg .= "COMMENTS: " .$_POST['comments'] ."<br>\n";
//Headers
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=UTF-8\r\n";
$headers .= "From: <".$from. ">" ;
//send for each mail
foreach($to as $mail){
mail($mail, $subject, $msg, $headers);
}
?>
按照@ADyson 的建议使用 encodeURIComponent() 修复了使用联系表单时收到的电子邮件中丢失的 data/urls。
var comments = $("#comments").val();
var e_comments = encodeURIComponent(comments);
您的问题是您是手动构建数据字符串,而不是对插入到字符串中的数据值进行 URI 编码。因此,文本中的任何原始 &
字符都将被假定为 URI 的一部分,而不是数据的一部分,这意味着它将被解释为指示下一个参数的开始,而不仅仅是文本中的一个字符。 URI 编码此数据会将此和其他特殊字符转换为它们的编码等价物,因此它们不会被误解。
现在,您当然可以通过用 encodeURIComponent()
包装每个字段变量来解决这个问题,但这是冗长乏味的:
var dataString = 'name=' + encodeURIComponent(name)
+ '&email=' + encodeURIComponent(email)
+ '&comments=' + encodeURIComponent(comments)
+ '&to=' + encodeURIComponent(to)
+ '&from=' + encodeURIComponent(from)
+ '&budget=' + encodeURIComponent(budget)
+ '&subject=' + encodeURIComponent(subject);
有更好的方法:
目前,您的 $(this).serialize();
将不起作用,因为 this
代表单击的按钮,而不是表单。但是,如果您将它指向表单,您可以使用它轻松地自动序列化其中的字段,并且 jQuery 将代表您处理任何编码问题。这节省了手动编码和单独获取每个字段值的代码(尽管我注意到你目前需要这个来进行验证,尽管还有其他方法可以实现验证,这将消除这种需要,但这完全是另一个话题)。
$.ajax({
type:"POST",
url: sendMailUrl,
data: $("#formy").serialize(),
success: success //Unrelated: I also removed the brackets here, so it becomes a _reference_ to the "success" function - writing success() as you did means the function is immediately executed, and what gets passed to jQuery is the _result_ of the function, which isn't what you want in this case
});
如您所见,这样就省事多了。如果您将来向表单中添加更多字段,则根本不必更改这段代码。
另一方面 - 使用 JavaScript 验证表单输入会很麻烦。这很好而且用户友好,但它没有提供任何安全性。在服务器端,您似乎很乐意将浏览器直接发送的任何值插入到您的电子邮件中。任何具有少量知识的用户都可以使用他们的开发工具修改您的 JavaScript,或者关闭 JS,或者完全使用其他工具(例如 PostMan 或自定义应用程序)在您的服务器上触发 HTTP 请求,而无需曾经触摸过你的表格。他们可能会发送有问题的值,这可能会搞砸您的电子邮件 - 例如一个不同的 "from" 值,或者一些讨厌的 HTML,或者如果您在应用程序的任何地方与数据库交互,请执行 SQL 注入攻击来搞砸它。您应该 始终 验证 PHP 代码中的所有传入数据是否存在安全问题,并确保它符合您的业务规则,然后再将其用于其他用途。