PHP+Curl调用MailJet发送邮件出现间歇性发送失败问题
问题原因分析
- 未捕获Curl请求级错误:你当前仅校验了接口返回的成功状态,没有判断
curl_exec的执行结果。如果因为网络波动、DNS解析失败、服务器出口带宽波动导致请求根本没有发送到MailJet服务器,curl_exec会返回false,此时你直接json_decode会得到空值,后续的状态判断逻辑直接报错终止,对应邮件不仅没发出去,你也收不到任何报错提示,MailJet端自然也没有相关记录。 - 未设置Curl超时参数:默认Curl没有配置超时时间,如果出现网络拥塞,单个请求会无限等待,一旦达到PHP脚本的最大执行时长,脚本会直接终止,后续待发送的邮件就会被跳过。
- 代码存在语法隐患:你当前每段邮件发送逻辑末尾都有一个多余的闭合大括号
},如果PHP开启了严格语法校验,偶尔会触发解析错误导致脚本终止,出现部分邮件未发的情况。 - 无错误日志记录:你当前没有将发送失败的请求信息、错误原因写入日志,无法定位具体是哪一步出现了问题。
代码精简优化方案
核心思路有两种,二选一即可:
方案1:复用MailJet批量发信能力(推荐)
MailJet v3.1的发信接口本身支持单请求传入多封邮件配置,仅需调用1次接口即可完成3封邮件的发送,无需重复调用Curl,也不需要加sleep延迟。
方案2:封装发信逻辑为公共函数
如果未来收件人配置会频繁调整,可以把重复的Curl逻辑封装为函数,传入收件人信息即可调用,减少冗余代码。
以下是优化后的完整代码示例,同时加入了错误处理逻辑:
<?php // 公共发信配置 $from = [ 'Email' => "fromemail@gmail.com", 'Name' => "IT Dept" ]; $apiKey = "gjirhhighighihihighrihihrihgirghihihihihihih"; $apiUrl = "https://api.mailjet.com/v3.1/send"; // 收件人列表,可直接扩展 $recipients = [ ['Email' => "email1@gmail.com", 'Name' => "Recipiant1"], ['Email' => "email2@gmail.com", 'Name' => "Recipiant2"], ['Email' => "email3@gmail.com", 'Name' => "Recipiant3"] ]; // 构造邮件内容 $date = date("F j, Y, g:i a"); $orderQty = $_POST['Order_Quantity'] ?? 0; $productQty = $_POST['Product_Quantity'] ?? 0; $crewCount = $_POST['Crew_Count'] ?? 0; $dailyTotal = array_sum($_SESSION); $htmlPart = "<center><h2>Your Daily Work Totals are Below:</h2></center><br /> <h2>Entry Date/Time:</h2> {$date} <h2>Order:</h2> {$orderQty} <h2>Product:</h2> {$productQty} <h2>Employee Count:</h2> {$crewCount} <h2>Daily Total:</h2> {$dailyTotal} <center><h2>Link to Report:</h2></center> <h3>google.com</h3> "; // 构造批量发信请求体 $body = [ 'Messages' => [] ]; foreach ($recipients as $recipient) { $body['Messages'][] = [ 'From' => $from, 'To' => [$recipient], 'Subject' => "Your Daily Data is Here", 'HTMLPart' => $htmlPart ]; } // 初始化Curl仅一次 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiUrl); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_USERPWD, $apiKey); // 新增超时配置,连接超时5秒,整体请求超时10秒 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 执行请求并捕获错误 $server_output = curl_exec($ch); $curlErr = curl_error($ch); curl_close($ch); if ($curlErr) { // 可自行替换为写日志逻辑 echo "Curl请求失败:" . $curlErr; } else { $response = json_decode($server_output, true); if (json_last_error() !== JSON_ERROR_NONE) { echo "接口返回格式解析失败"; } else { $allSuccess = true; foreach ($response['Messages'] as $index => $msg) { if ($msg['Status'] !== 'success') { $allSuccess = false; echo "发给{$recipients[$index]['Email']}的邮件发送失败"; } } if ($allSuccess) { echo "所有邮件发送成功"; } } } ?>
内容的提问来源于stack exchange,提问作者rhtwenty1
相关产品推荐
相关产品推荐

