SendGrid邮件发送失败,前端却收到200响应?
2024-07-12 17:18:22
如何从 Sendgrid.php 文件中获取正确的响应/错误日志?
你是否遇到过使用 SendGrid 发送邮件时,即使发送失败, 前端依然收到 200
响应的情况?本文将为你揭开谜底,并提供解决方案,帮助你准确获取 Sendgrid.php 文件的响应和错误日志。
深入问题:Fetch API 与 HTTP 状态码
问题的根源在于 JavaScript 的 fetch
API 处理 HTTP 响应的机制。fetch
API 旨在处理网络请求,它关注的是请求是否成功抵达服务器并得到响应,而非响应内容本身是否代表成功。
具体来说,当 fetch
发出请求后:
- 如果网络连接正常,服务器返回了响应(无论状态码是什么),
fetch
都认为请求成功,返回一个resolved
状态的 Promise。 - 只有当网络连接中断,例如服务器无法访问,
fetch
才会返回一个rejected
状态的 Promise,表示请求本身失败。
这意味着,即使 SendGrid 服务器返回了 500 Internal Server Error
等错误状态码,fetch
依然会返回一个 resolved
的 Promise,让你误以为邮件发送成功。
解决方案:解析响应状态码
为了获取 SendGrid 发送邮件的真实结果,我们需要检查 fetch
返回的响应对象(Response
对象)中的状态码,而非仅仅依靠 Promise 的状态。
以下是改进后的 JavaScript 代码:
<script>
const remindMeForm = document.getElementById('remindMe');
remindMeForm.addEventListener('submit', function(e) {
e.preventDefault();
// ... 获取表单数据 ...
fetch('/sendgrid.php', {
method: 'POST',
body: formData
})
.then(response => {
// 检查 HTTP 状态码
if (response.ok) {
// 状态码在 200-299 之间,表示成功
return response.json(); // 假设 sendgrid.php 返回 JSON 格式数据
} else {
// 状态码不在 200-299 之间,表示出错
// 解析错误信息,并抛出 Error 对象,以便在 catch 中处理
return response.text().then(text => {
throw new Error(text);
});
}
})
.then(data => {
// 请求成功,处理响应数据
console.log('Success:', data);
jobReminder__message.innerHTML = 'Thank you for your interest in ' + jobTitle + '. A reminder has been scheduled 24 hours from now.';
})
.catch(error => {
// 处理错误
console.error('Error:', error);
// ... 根据错误信息展示相应的提示 ...
});
} );
</script>
代码解析:
response.ok
属性:Response
对象拥有一个ok
属性,它是一个布尔值,表示 HTTP 状态码是否在200
到299
之间。我们可以利用这个属性判断请求是否真正成功。- 解析错误信息: 如果
response.ok
为false
,我们需要从响应中解析出错误信息。这里我们使用response.text()
方法获取响应的文本内容,然后将其包装在一个新的Error
对象中抛出。 - 错误处理: 最后,我们在
catch
块中捕获并处理错误,可以根据错误信息展示相应的提示给用户,或者记录日志供后续分析。
完善后端代码:返回有意义的错误信息
为了让前端能够更好地处理错误,sendgrid.php
也需要做出相应的修改,返回更详细、结构化的错误信息。
<?php
// ... (其他代码)
try {
$response = $sg->client->mail()->send()->post($request_body);
// 发送成功
http_response_code(200);
echo json_encode(['message' => 'Email sent successfully']);
} catch (Exception $ex) {
// 发送失败
http_response_code(500); // 设置为 500 Internal Server Error
// 返回 JSON 格式的错误信息
echo json_encode([
'error' => true, // 标记这是一个错误响应
'message' => 'Failed to send email',
'details' => $ex->getMessage() // 包含更详细的错误信息
]);
}
代码解析:
- HTTP 状态码: 使用
http_response_code()
函数设置合适的 HTTP 状态码。发送成功时使用200
,失败时使用500
或其他合适的错误状态码。 - JSON 格式错误信息: 使用
json_encode()
函数将错误信息转换为 JSON 格式,方便前端解析。错误信息中包含error
字段标记这是一个错误响应,message
字段提供简短的错误,details
字段可以包含更详细的错误信息,例如异常信息。
总结
通过以上修改,你的前端代码将能够正确识别 SendGrid 发送邮件的成功与失败,并根据后端返回的错误信息进行相应的处理。
常见问题解答:
-
问:为什么不能直接在第一个
then
中判断状态码?答:在第一个
then
中,我们还无法确定响应内容的类型。如果状态码不是200
,我们需要先使用response.text()
获取错误信息,然后再抛出错误。 -
问:
response.json()
和response.text()
有什么区别?答:
response.json()
用于解析 JSON 格式的响应,response.text()
用于获取响应的文本内容。你需要根据sendgrid.php
返回的数据类型选择合适的方法。 -
问:如何记录错误日志?
答:你可以在
catch
块中使用console.error()
将错误信息打印到控制台,或者使用第三方日志库将错误信息记录到文件或数据库中。 -
问:如何自定义错误提示信息?
答:你可以根据后端返回的错误信息,在
catch
块中使用 JavaScript 代码动态生成相应的错误提示信息,例如使用innerHTML
更新页面元素的内容。 -
问:除了
500
,还有哪些 HTTP 状态码可以用于表示 SendGrid 发送邮件失败?答:除了
500
,还有很多 HTTP 状态码可以用于表示 SendGrid 发送邮件失败,例如400 Bad Request
表示请求参数错误,401 Unauthorized
表示认证失败,429 Too Many Requests
表示请求过于频繁。你需要根据具体情况选择合适的错误状态码。