PHPMailer结合Angular发邮件提示Undefined变量无表单数据如何解决
问题原因及修复方案
核心问题梳理
- 数据格式不匹配:Angular提交的是JSON格式数据,PHP的
$_POST无法直接解析,导致参数获取失败,变量未定义 - 变量作用域错误:参数变量仅在if判断块内定义,判断不通过时外部调用直接报未定义,且发信逻辑放在判断外,无参数也会发空邮件
- PHPMailer配置错误:加密方式和端口不匹配,可能导致发信异常
修复步骤
1. PHP端修改(推荐优先调整)
修改后的完整PHP代码如下:
<?php require 'includes/PHPMailer.php'; require 'includes/SMTP.php'; require 'includes/Exception.php'; use PHPMailer\PHPMailer\Exception; use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; // 接收JSON格式的请求数据 $rawData = file_get_contents('php://input'); $postData = json_decode($rawData, true); // 初始化变量避免未定义报错 $nombre = $email = $mensaje = ''; // 校验参数 if(isset($postData['nombre']) && isset($postData['email']) && isset($postData['mensaje'])){ $nombre = trim($postData['nombre']); $email = trim($postData['email']); $mensaje = trim($postData['mensaje']); }else{ // 参数缺失直接返回错误 echo '缺少必填参数'; exit; } try { $mail = new PHPMailer(true); //Server settings $mail->SMTPDebug = 0; // 生产环境关闭调试输出 $mail->Host = 'smtp.gmail.com'; $mail->SMTPAuth = true; $mail->Username = 'kanazawa8213@gmail.com'; $mail->Password = '你的应用密码'; $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // 587端口对应STARTTLS加密 $mail->Port = 587; //Recipients $mail->setFrom('kanazawa8213@gmail.com', 'Ptree'); $mail->addAddress('kanazawa8213@gmail.com'); //Content $mail->isHTML(true); $mail->Subject = 'Nuevo mensaje desde Ptree site'; $mail->Body = "Este es un mensaje desde Ptree site:<br><br>". " Nombre: ".$nombre. "<br><br> Email: ".$email. "<br><br> Mensaje: " .$mensaje; if($mail->send()){ echo 'Message has been sent'; }else{ echo 'Message could not be sent.'; echo 'Mailer Error: ' . $mail->ErrorInfo; } } catch (Exception $e) { echo "邮件发送异常: {$e->getMessage()}"; } ?>
修改点说明:
- 用
file_get_contents('php://input')获取原始JSON请求体,解析后拿到参数 - 提前初始化变量,避免未定义报错
- 把发信逻辑放到参数校验通过的分支内,参数缺失直接返回错误不会发空邮件
- 修正加密方式和端口的匹配关系,生产环境关闭调试输出
- 外层增加异常捕获,避免未捕获异常导致接口报错
2. Angular端调整(可选,若不想改PHP可以用这个方案)
如果要保留PHP的$_POST接收逻辑,就把Angular的提交格式改成x-www-form-urlencoded或者FormData:
修改MycontactService的sendMessage方法:
sendMessage(landingForm:any): Observable<any> { // 转成FormData格式 const formData = new FormData(); Object.keys(landingForm).forEach(key => { formData.append(key, landingForm[key]); }); // 去掉自定义的Content-Type,HttpClient会自动识别FormData设置正确的请求头 return this.http.post<any>(`${this.emailUrl}`, formData).pipe( tap( message => console.log(message) ), catchError(this.handleError('Sending', [])) ); }
其他注意事项
- Gmail的SMTP现在需要开启两步验证后生成应用专用密码,不能用账号的普通登录密码,否则会发信失败
- 表单提交前可以加一步判断
landingForm.valid,只有表单校验通过才提交,避免无效请求
内容的提问来源于stack exchange,提问作者Luis Alejandro López de Anda
相关产品推荐
相关产品推荐

