|
本帖最后由 hyperlau 于 2017-7-3 16:02 编辑
不管是用CI的email类还是其他类,只要在php里调用smtp发邮件都会碰到需要等待发送完成才能返回的情况,用户体验非常不好,不爽,不利索。。。。
还好会perl,改了改N年前写的发邮件脚本,在php里写一条text到一个邮件队列的文本文件,然后crontab调用perl脚本来处理邮件队列,发送完成直接删掉这行,然后写日志到一个日志文本文件,没有等待,没有延迟,多开心~~
代码如下:
PHP部分:
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部分:
PHP复制代码
#!/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[31mFAILED\033[0m]\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())[5,4,3,2,1,0];
$time_format[0] += 1900;
$time_format[1] += 1;
foreach $_(@time_format ) {
$_ = sprintf("%02d", $_);
}
my $cur_time = "$time_format[0]-$time_format[1]-$time_format[2] $time_format[3]:$time_format[4]:$time_format[5]";
return($cur_time);
}
复制代码
Perl代码可以保存在/usr/local/nginx/html/app/third_party/q_mail.pl , 要注意权限,因为大部分web服务器都运行在一个牢笼用户下,要保证脚本可读可执行运行前需要安装所需的库,在shell下执行:
PHP复制代码
cpan Tie ::File
cpan Net ::SMTP
cpan Authen ::SASL
复制代码
crontab: ( 一分钟执行一次)
PHP复制代码
* * * * * /usr/local/nginx/html/app/third_party/q_mail.pl &
复制代码
整合到自己的代码里,可以这样调用:
PHP复制代码
$this->load->library('msg');
$this->msg->send_mail_q('def@def.com','标题','内容');
复制代码
完成!
|
|