如何解决CodeIgniter中SMTP批量邮件发送失败问题
批量SMTP邮件发送失败:仅部分发送后报错
问题描述
编写了sendMail函数用于批量发送邮件,目标数组含60个邮箱地址,但启动服务后仅成功发送10-15封,随后出现以下错误:
from: 遇到以下SMTP错误:
Unable to send data: QUIT
quit:
遇到以下SMTP错误:
Unable to send email using PHP SMTP. Your server might not be configured to send mail using this method.
User-Agent: CodeIgniter
函数代码
function sendMail($to,$cc="",$subject,$message,$title="",$attach="",$from="") { $CI = & get_instance(); $CI->load->library("email"); $CI->email->clear(TRUE); $CI->email->set_newline("\r\n"); if($title==""){ $title="q Group"; } if($from=="") { $from="q@q.com.tr"; } $CI->email->from($from, $title); if($cc<>"") $CI->email->cc($cc); $CI->email->subject($subject); $CI->email->message($message); if($attach<>"") { $CI->email->attach($attach); } $mailList = explode(",",$to); $sendMailList = ""; foreach ($mailList as $key=>$item) { if (filter_var($item, FILTER_VALIDATE_EMAIL)) { $sendMailList .=$item.","; } else{ MailLogModel::setLog($item,$subject,0,"Mail Adresi Hatalı"); if(count($mailList)==1) return ["status"=>false,"message"=>"Mail Adresi Hatalı"]; } } $sendMail = substr($sendMailList,0,-1); $CI->email->to($sendMail); if (! $CI->email->send()){ MailLogModel::setLog($sendMail,$subject,0,html_entity_decode(imap_utf8($CI->email->print_debugger('headers','subject')))); return ["status"=>false,"message"=>$CI->email->print_debugger(array('headers'))]; } else{ MailLogModel::setLog($sendMail,$subject,1); return ["status"=>true]; } }
配置文件
$config['protocol'] = "smtp"; $config['SMTPAuth'] = true; $config['smtp_host'] = "mail.MYSERVICE.com.tr"; $config['smtp_user'] = ""; $config['smtp_pass'] = ""; $config['smtp_port'] = "25"; $config['charset'] = "utf-8"; $config['mailtype'] = "html"; $config['newline'] = "\r\n"; $config['crlf'] = "\r\n"; $config['smtp_timeout'] = 5;
解决方案
1. 修复SMTP认证配置
配置中SMTPAuth设为true但smtp_user和smtp_pass为空,这会导致认证失败:
- 如果SMTP服务器需要认证:填写正确的用户名和密码
- 如果不需要认证:将
SMTPAuth改为false
2. 调整SMTP连接策略,避免复用单连接
多数SMTP服务器会限制单连接的发送次数(通常10-15封),超过后会主动断开连接。需每次发送后重新初始化邮件库:
- 若外部循环调用
sendMail,每次调用前销毁并重新加载库:unset($CI->email); $CI->load->library('email'); - 若函数内部批量发送,改为逐个处理邮箱,每次发送前重置邮件实例:
// 替换原合并收件人的逻辑,改为逐个发送 foreach ($mailList as $key=>$item) { if (!filter_var($item, FILTER_VALIDATE_EMAIL)) { MailLogModel::setLog($item,$subject,0,"Mail Adresi Hatalı"); continue; } // 每次发送前重置邮件配置 $CI->email->clear(TRUE); $CI->email->from($from, $title); if($cc<>"") $CI->email->cc($cc); $CI->email->subject($subject); $CI->email->message($message); if($attach<>"") $CI->email->attach($attach); $CI->email->to($item); if (!$CI->email->send()){ MailLogModel::setLog($item,$subject,0,html_entity_decode(imap_utf8($CI->email->print_debugger('headers','subject')))); } else { MailLogModel::setLog($item,$subject,1); } }
3. 更换SMTP端口与加密方式
端口25常被防火墙或ISP拦截,建议改用标准加密端口:
- 使用TLS加密(端口587):
$config['smtp_port'] = 587; $config['smtp_crypto'] = 'tls'; - 或使用SSL加密(端口465):
$config['smtp_port'] = 465; $config['smtp_crypto'] = 'ssl';
同时延长超时时间,避免网络延迟导致断开:
$config['smtp_timeout'] = 10;
4. 添加发送频率控制
部分服务器会限制短时间内的发送频率,可在逐个发送的循环中添加延迟:
sleep(2); // 每发送一封后暂停2秒,根据服务器要求调整
内容的提问来源于stack exchange,提问作者mehmet solak
相关产品推荐
相关产品推荐

