不规矩的异步邮件队列处理插件
本帖最后由 hyperlau 于 2017-7-3 16:02 编辑不管是用CI的email类还是其他类,只要在php里调用smtp发邮件都会碰到需要等待发送完成才能返回的情况,用户体验非常不好,不爽,不利索。。。。
还好会perl,改了改N年前写的发邮件脚本,在php里写一条text到一个邮件队列的文本文件,然后crontab调用perl脚本来处理邮件队列,发送完成直接删掉这行,然后写日志到一个日志文本文件,没有等待,没有延迟,多开心~~
代码如下:
PHP部分:
<?php
class Msg {
protected $CI;
public function __construct()
{
$this->CI =& get_instance();
}
public function send_mail_q($to,$sub,$msg) {
$this->CI->load->helper('file');
$line='to:'.$to.'<end>sub:'.$sub.'<end>msg:'.$msg.'<end>'."\n";
write_file('/tmp/mail_q', $line,"a");
}
}
?>
Perl部分:
#!/usr/bin/perl -w
use strict;
use warnings;
use Tie::File;
use File::Path qw( mkpath );
use Time::Local;
use Net::SMTP;
use Authen::SASL;
$|=1;
my $mail_q='/tmp/mail_q';
my $log='/tmp/mail_log';
our $MailDebug = 0;
our $MailTimeout = 30;
our $MailUser = 'abc@abc.com';
our $MailPass = 'passwod';
our $MailHost = 'smtp.exmail.qq.com';
our $MailFrom = 'abc@abc.com';
our @MailList = ();
$SIG{'INT'}=sub {print "Script is running!!\n"};
unless (-e $mail_q) {
dielogger($log,"can't found $_!");
}
my $result;
tie (my @lines,'Tie::File',$mail_q) || dielogger($log,"can't tie file to \@lines !SYSTEM_MSG: $!");
for (my $i=0;$i< @lines;$i++) {
if ($lines[$i]=~/to:(.*)\<end\>sub:(.*)\<end\>msg:(.*)\<end\>$/) {
$result=mail_send($2,$3,$1);
if ($result==0) {
$lines[$i].=" SEND OK\n";
logger($log,$lines[$i]);
delete $lines[$i];
}
}
}
sub mail_send {
my ($MailSubject, $MailContent,$MailTo) = @_;
my $smtp = Net::SMTP->new($MailHost, Timeout=>$MailTimeout, Debug=>$MailDebug);
if(!$smtp) {
dielogger($log,"Can not connect to the mail server!");
return 1;
} else {
my $auth_stat = $smtp->auth($MailUser, $MailPass);
if (!$auth_stat) {
dielogger($log,"Mail account authentification failed!");
return 2;
} else {
$smtp->mail($MailFrom);
$smtp->to($MailTo);
$smtp->data();
$smtp->datasend("Content-Type: text/html; charset=UTF-8\n");
$smtp->datasend("From:" . $MailFrom . "\n");
$smtp->datasend("To:" . $MailTo . "\n");
$smtp->datasend("Subject:" . $MailSubject . "\n");
$smtp->datasend("\n");
$smtp->datasend($MailContent);
$smtp->dataend();
}
$smtp->quit();
}
return 0;
}
sub logger
{
my ($f,$m)=@_;
open(LOGF,">>",$f)|| die "Failed to open $f.[\033\n";
my $msg=get_time() . " $m\n";
print $msg;
print LOGF $msg;
close LOGF;
}
sub dielogger
{
my ($f,$m)=@_;
logger($f,$m . " ##############QUIT##############\n");
exit 1
}
sub get_time {
my @time_format = (localtime());
$time_format += 1900;
$time_format += 1;
foreach $_(@time_format) {
$_ = sprintf("%02d", $_);
}
my $cur_time = "$time_format-$time_format-$time_format $time_format:$time_format:$time_format";
return($cur_time);
}
Perl代码可以保存在/usr/local/nginx/html/app/third_party/q_mail.pl , 要注意权限,因为大部分web服务器都运行在一个牢笼用户下,要保证脚本可读可执行运行前需要安装所需的库,在shell下执行:
cpan Tie::File
cpan Net::SMTP
cpan Authen::SASL
crontab: ( 一分钟执行一次)
* * * * * /usr/local/nginx/html/app/third_party/q_mail.pl &
整合到自己的代码里,可以这样调用:
$this->load->library('msg');
$this->msg->send_mail_q('def@def.com','标题','内容');
完成!
页:
[1]