实现每5秒发送CSV中邮件并展示输出的技术问询
问题分析与解决方案
原代码的核心问题
- 后端PHP循环同步执行,调用
mail()时会一次性发送所有邮件,没有实现间隔5秒发送的逻辑,$wait变量仅作用于前端JS,对后端发送流程无影响。 - 前端用
document.write会覆盖页面内容,且多个setTimeout同时触发计时,并非在上一封邮件发送完成后再等待5秒,无法实现依次间隔输出。 - 将邮箱地址按空格拆分遍历的逻辑不合理,每个邮箱应对应一次独立的发送和输出操作。
方案一:后端控制间隔(适合少量邮件)
如果邮件数量不多,可直接在PHP循环中添加sleep(5)实现间隔,同时开启实时输出展示发送状态,注意调整PHP执行时间限制:
<?php ini_set('max_execution_time', 0); // 关闭执行时间限制 ob_implicit_flush(true); // 开启实时输出 ob_end_flush(); $row = 1; if (($handle = fopen("Email.csv", "r")) !== FALSE) { while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { $to = trim(implode($data)); // 清理邮箱地址多余空格 if (empty($to)) continue; // 跳过空行 $subject = 'Your subject'; $message = 'Your mail content'; $headers = "From: ar742812@gmail.com"; // 发送邮件并获取结果 $sendResult = mail($to, $subject, $message, $headers); // 实时输出发送状态 echo ($row) . ": 发送邮件到 {$to} " . ($sendResult ? "成功" : "失败") . "<br>"; $row++; // 最后一封邮件无需等待 if (!feof($handle)) { sleep(5); } } fclose($handle); } ?>
方案二:前端控制+后端接口(适合大量邮件)
拆分发送逻辑为后端接口和前端控制,前端每隔5秒请求一次接口发送下一封邮件,避免后端长时间执行超时:
1. 后端接口(send_email.php)
<?php session_start(); // 用会话存储已发送的行数 $currentRow = isset($_SESSION['current_row']) ? $_SESSION['current_row'] : 1; $handle = fopen("Email.csv", "r"); if ($handle === FALSE) { echo json_encode(['success' => false, 'msg' => '无法打开CSV文件']); exit; } // 跳转到当前待发送的行 for ($i=1; $i<$currentRow; $i++) { fgetcsv($handle, 1000, ","); } $data = fgetcsv($handle, 1000, ","); fclose($handle); // 所有邮件已发送完成 if ($data === FALSE) { unset($_SESSION['current_row']); echo json_encode(['success' => false, 'msg' => '所有邮件已发送完成']); exit; } $to = trim(implode($data)); if (empty($to)) { $_SESSION['current_row'] = $currentRow + 1; echo json_encode(['success' => false, 'msg' => '跳过空邮箱']); exit; } $subject = 'Your subject'; $message = 'Your mail content'; $headers = "From: ar742812@gmail.com"; $sendResult = mail($to, $subject, $message, $headers); $_SESSION['current_row'] = $currentRow + 1; echo json_encode([ 'success' => $sendResult, 'row' => $currentRow, 'email' => $to, 'msg' => $sendResult ? '发送成功' : '发送失败' ]); ?>
2. 前端页面(index.html)
<!DOCTYPE html> <html> <head> <title>邮件发送进度</title> </head> <body> <div id="progress"></div> <script> const progressDiv = document.getElementById('progress'); let isSending = false; function sendNextEmail() { if (isSending) return; isSending = true; fetch('send_email.php') .then(response => response.json()) .then(data => { // 追加发送状态到页面 const statusItem = document.createElement('div'); statusItem.textContent = `${data.row}: 发送邮件到 ${data.email} - ${data.msg}`; progressDiv.appendChild(statusItem); // 未发送完则间隔5秒继续 if (data.msg !== '所有邮件已发送完成') { setTimeout(() => { isSending = false; sendNextEmail(); }, 5000); } else { const finishItem = document.createElement('div'); finishItem.textContent = '=== 所有邮件发送完成 ==='; progressDiv.appendChild(finishItem); } }) .catch(error => { const errorItem = document.createElement('div'); errorItem.textContent = `请求错误: ${error.message}`; progressDiv.appendChild(errorItem); isSending = false; setTimeout(sendNextEmail, 5000); }); } // 启动发送流程 sendNextEmail(); </script> </body> </html>
关键说明
- 方案一适合邮件数量少的场景,后端直接控制间隔,无需前端交互。
- 方案二更适合大量邮件,通过前端控制请求间隔,避免后端超时,同时实时展示进度。
- 两种方案都需确保服务器上
mail()函数配置正确(如sendmail或SMTP设置),否则邮件无法正常发送。
内容的提问来源于stack exchange,提问作者Ali Raza
相关产品推荐
相关产品推荐

