我在网站上有一个基本的联系表格。 我需要将表单结果发送到 2 个电子邮件地址...1)我,2)向提交表格的人确认。发送给提交者的表单结果中包含不同的消息。
我计划添加jQuery验证和Ajax,但首先我想让PHP工作。 所以我认为我不需要很多PHP验证,只需要一个基本的 -如果关键字段为空,则错误消息,作为后备。
我正在使用PHPMailer,但不幸的是,对于我缺乏PHP技能的人来说,他们的文档非常缺乏。 但是经过谷歌搜索,我已经能够拼凑出一些大部分有效的东西。 这是我使用小形式的代码(稍后会有更多字段)。
这确实将表单发送到两个电子邮件地址 - 太好了!
我遇到问题的部分是验证和错误/成功消息。
如果我只使用function sendemail
部分末尾的return $mail->send();
,它会发送正常。 但是,如果我尝试提交表单时字段中没有任何内容,则没有任何反应。 所以我尝试添加我在某处找到的这if(!$mail->send()) {...else...}
件,它也适用于有效的表单信息,但如果为空则不行。
那么,我应该用什么来代替这个? 或者它会与最后不同的东西 if/else 部分?
<?php
if (isset($_POST['submit'])) {
date_default_timezone_set('US/Central');
require 'PHPMailer-5.2.26/PHPMailerAutoload.php';
function sendemail(
$SK_emailTo,
$SK_emailSubject,
$SK_emailBody
) {
$mail = new PHPMailer;
$mail->setFrom('myEmail@gmail.com', 'My Name');
$mail->addReplyTo($_POST['email'], $_POST['name']);
$mail->addAddress($SK_emailTo);
$mail->Subject = $SK_emailSubject;
$mail->Body = $SK_emailBody;
$mail->isHTML(true);
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->Username = 'myEmail@gmail.com';
$mail->Password = 'myPwd';
//return $mail->send(); //this works by itself, without IF/ELSE, but doesn't return error if empty form fields
if(!$mail->send()) {
return 'There is a problem' . $mail->ErrorInfo;
}else{
return 'ok'; // this works but i don't know why
}
} //end function sendemail
// form fields to variables
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
// from function sendmail to ASSIGN VALUES to...
/* $SK_emailTo,
SK_emailSubject,
$SK_emailBody */
if (sendemail(
'myEmail@address.com',
'First email subject',
'Form results to me...
<br><br>'.$message
)) {
sendemail(
$email,
'Second email subject',
'Confirmation email to person who submitted the form...
<br><br>'.$message
);
$msg = 'Email sent!';
} else {
$msg = 'Email failed!' . $mail->ErrorInfo;
}
} //end if submit
?>
作为旁注,为什么return 'ok';
有效? "确定"部分附着在什么上?
谢谢!
///
根据下面 Mauro 的建议和编辑(以及该帖子评论),这就是我现在所处的位置......
<?php
if (isset($_POST['submit'])) {
date_default_timezone_set('US/Central');
require 'PHPMailer-5.2.26/PHPMailerAutoload.php';
function sendemail(
$SK_emailTo,
$SK_emailSubject,
$SK_emailBody
) {
$mail = new PHPMailer(true);
$mail->setFrom('myEmail@gmail.com', 'My Name');
$mail->addReplyTo($_POST['email'], $_POST['name']);
$mail->addAddress($SK_emailTo);
$mail->Subject = $SK_emailSubject;
$mail->Body = $SK_emailBody;
$mail->isHTML(true);
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->Username = 'myEmail@gmail.com';
$mail->Password = 'myPwd';
return $mail->send();
} //end function sendemail
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
try {
sendemail(
'myEmail@address.com',
'First email subject',
'Form results to me...
<br><br>'.$message
);
sendemail(
$email,
'Second email subject',
'Confirmation email to person who submitted the form...
<br><br>'.$message
);
echo 'Email sent!';
} //end try
catch (phpmailerException $e) { //catches PHPMailer errors
echo 'There is a problem; the message did NOT send. Please go back and check that you have filled in all the required fields and there are no typos in your email address.';
echo $e->errorMessage();
}
catch (Exception $e) { //catches validation errors
echo 'There is a problem; the message did NOT send. Please either go back and try again or contact us at email@address.com';
echo $e->getMessage();
}
function validateEmpty($string, $name = 'name') {
$string = trim($string);
if ($string == '') {
throw new Exception(sprintf('%s is empty.', $name));
}
}
} //end if submit
?>
还。。。
1)Mauro建议我使用use error_log()
记录错误消息。我该怎么做?这就是在FTP目录中产生错误消息的文本文件的原因吗?
2)毛罗还建议使用an $error & $success flag
。那是什么,我该怎么做?
3)如果"名称"和/或"电子邮件"字段(可能还有其他字段)只是空的,我希望在上述catch
中有自定义错误消息。Mauro 在上面编写了function validateEmpty
代码,但我无法让它工作。我是否将其放在脚本中的错误位置或对它做错了其他事情?
3b) 在我看来,这个函数仅适用于"名称"字段,我是否必须为"电子邮件"字段复制它?
请记住... 我希望能够在这里进行简单的验证作为后备,以防Javascript/Jquery由于某种原因不起作用。 另请注意,上述内容确实正确"发送"了电子邮件;所以我现在只是试图让验证和错误消息正常工作。
感谢您的时间和专业知识!
tl;DR:两种说法的计算结果都是true
。最好返回true
或false
而不是字符串,稍后再处理消息。
首先,我会处理你的问题,然后我会就良好做法提出一些建议。
当你在PHP和大多数语言中使用return x;
时,你正在"发送"x
回到你调用函数的位置。因此,当您的代码被执行时,它将被读取为:
if('ok')
或
if ('Error info...')
PHP 通过将if
语句(这是括号之间的部分)上的条件true
或false
转换为boolean
类型来评估该条件。PHP 中的字符串到布尔值的转换基本上如下:任何非空字符串的计算结果为TRUE
(点击链接,检查第一个表,最后一列)。
因此,如果函数成功,则返回"ok","错误信息..."如果失败,这些都是非空字符串,并且评估为true
,因此无论第一次电子邮件发送尝试是否顺利,您的脚本都会尝试发送第二次,并始终$msg
设置为"电子邮件已发送!
以下是有关如何修复脚本以使其更好地工作(和外观)的一些建议:
正如@Matt所建议的那样,最好自己验证数据,而不是依赖PHPMailer来验证数据。尽管如果目标地址无效,PHPMailer 会返回错误,但如果电子邮件无效,甚至不要调用库也是一种很好的做法。所以:
- 首先,使用 javascript 验证数据,以便您的用户获得即时反馈。
- 然后,使用 PHP 验证它(也许创建一个新的
validate()
函数,可以使用filter_var()
来验证电子邮件。 - 最后,仅当前两个成功时才发送电子邮件。
为了遵循你的思维链,你应该评估
sendemail()
返回的字符串是否等于"ok":if (sendemail(...) == 'ok')
但是,与其计算两个不同的字符串('ok'或'Error info...'),不如让函数返回布尔值,并且由于PHPMailer的
send()
已经这样做了,只需保持它对它的注释:return $mail->send()
你的最后一行是使用
$mail
,一个你在函数中声明的变量,你从来没有做过global
,所以它此时将不可用,因为你试图获取一个属性(ErrorInfo
),你将触发两个 PHP 通知:Undefined variable
和Trying to get a property from a non-object
。您可以在函数顶部添加global $mail
,这将使它全局可用(超出函数的范围),但这被认为是一种不好的做法,因为在大段代码中您可能会感到困惑。相反,触发错误的更简洁方法是抛出/捕获异常:
function sendemail(...) { // ... PHPMailer config ... if ($mail->send()) { return true; } else { throw Exception('Error: ' + $mail->ErrorInfo); } } // later... try { sendemail() $msg = 'Email sent!'; } catch (Exception $e) { $msg = 'Email failed!' . $e->getMessage(); }
在这里,如果发送电子邮件出现问题,您的函数将
throw
泛型异常,catch
部分将被执行。甚至更好
如果你像这样初始化PHPMailer:
$mail = new PHPMailer(true); // note the parameter set to true.
如果它无法发送电子邮件,它将自行引发异常,您将能够捕获异常:
function sendemail(...) { $mail = PHPMailer(true); // this line // ... PHPMailer config ... return $mail->send(); // just to return something, we aren't really using this value anymore. } // later... try { sendemail(...) $msg = 'Email sent!'; } catch (phpmailerException $e) { echo $e->errorMessage(); // Catch PHPMailer exceptions (email sending failure) } catch (Exception $e) { echo $e->getMessage(); // Boring error messages from anything else! }
永远不要忘记阅读文档!