PHPMailer和Google SMTP中继。收件人收到其他客户电子邮件的重复电子邮件过多

时间:2019-01-19 01:22:30

标签: smtp phpmailer

我创建了一个脚本,该脚本通过电子邮件将一些跟踪详细信息发送给已发货的每个客户订单。

该脚本由PHPMailer构建,并通过Google SMTP中继服务发送电子邮件。

在测试过程中,所有操作均按预期进行。对100封电子邮件进行了负载测试,尽管它们都使用相同的电子邮件地址,但均按预期执行。没有重复或缺少电子邮件。

但是,上线不久后,我被告知几个客户收到了数十封电子邮件,其他客户也跟踪了详细信息。

对于gmail用户,他们收到了另一位客户的跟踪电子邮件,其电子邮件地址已发送给。

对于Outlook用户,他们会在发送到区域中收到其他客户的电子邮件以及许多电子邮件。

我检查了代码,测试并检查了每个函数的输出,在可能出错的地方完全丢失了。

下面是脚本的sudo进程。希望了解是否有人可以提供一些有关如何解决此问题的提示。

  1. 将电子邮件列表检索到一维数组中。
  2. 创建一个PHPMailer实例
  3. 对于数组中的每个电子邮件,发送电子邮件,等待TRUE响应,如果为FALSE,则等待5秒,如果超过CONTINUE,则重试总计3次。
  4. 完成后,脚本结束。

其他说明

该脚本由Windows任务计划程序触发。

该脚本将花费大约2-10分钟的时间运行,具体取决于重试的次数,尽管计划程序设置为每5分钟运行一次,但已将计划程序中的任务设置为不运行该任务的多个实例(如果现有程序正在运行)

任何建议都会很棒。

欢呼

代码段。希望能提供足够的想法。

一般过程是脚本从Dispatcher_cl.php调用sendTrackingEmails(),然后在脚本中使用MyCustomerMailer.php中的各种功能。 MyCustomerMailer.php或多或少是PHPMailer的抽象层。

Dispatcher_cl.php

public function sendTrackingEmails() {
    try{
        $this->processLog[] = __FUNCTION__;

        /*
        1.Get list of emails
        2.Loop and send emails
        */

        $ordersSent         = array();
        $ordersFailed       = array();
        $result             = false;
        $emailListAndInfo   = $this->getEmailListAndInfo();

        if($emailListAndInfo===false){
            //No orders to dispatch emails. So do nothing.
            $result = false;
        }else{
            $mail = new MyCustomMailer_cl();

            if($mail->setSMTPParam('default')===true){

                foreach($emailListAndInfo as $customer){

                    $sentFrom       = array();
                    $replyTo        = array();
                    $emailTo        = array($customer['email'],$customer['name']);
                    $subject        = array();
                    $body           = null;

                    /*
                        Preset email settings for each brand.
                        When adding vendors, remember to add a BODY template and VENDOR ID to the SQL in [m_getEmailListAndInfo]
                    */
                    if($customer['vendor_id']==3){  
                        //Diamondphoto
                        $sentFrom       = array('no-reply@email.com','Your order has been shipped');
                        $replyTo        = array('no-reply@email.com','Your order has been shipped');
                        $subject        = "Tracking for order {$customer['vendorOrderId']}";
                        $body           = $this->getEmailTemplateFor(3,$customer);


                    }else{
                        /*
                            If vendor_id does not match existing setup, set TRYCOUNT to 99 as indicator and skip remaining execution. 
                            Next script-run will not pick up this record due to 99 will be greater than the usual preset TRYCOUNT.
                        */
                        $this->setTryCountForOrder($customer['order_id'],99);
                        continue;
                    }

                    $emailPackage['sentFrom']   = $sentFrom;
                    $emailPackage['replyTo']    = $replyTo;
                    $emailPackage['emailTo']    = $emailTo;
                    $emailPackage['subject']    = $subject;
                    $emailPackage['body']       = $body;
                    $mail->setupEmail($emailPackage);

                    for($i=1;$i<=$this->emailTryCount;$i++){
                        // $emailSentResult = $mail->send();
                        $emailSentResult = false;

                        if($emailSentResult===true){
                            $setFlagResult = $this->setSentFlagForOrder($customer['order_id'],$i);

                            if($setFlagResult===true){
                                $ordersSent[] = $customer['order_id'];

                                break;
                            }else{
                                throw new Exception("Update sent-flag for order {$customer['order_id']} failed.");
                            }
                        }else if($emailSentResult===false AND $i<$this->emailTryCount){

                            $this->setTryCountForOrder($customer['order_id'],$i);
                            // sleep($this->emailWaitTimer);
                            continue;

                        }else if($emailSentResult===false AND $i==$this->emailTryCount){

                            $this->setTryCountForOrder($customer['order_id'],$i);
                            $ordersFailed[] = $customer['order_id'];

                        }
                    }//End sending/attempting to send tracking email.

                }//End of looping through the emailing list.


            }//End of validation SMTP parameters.

            $result = array('sent'  =>$ordersSent
                            ,'failed'=>$ordersFailed);

        }//End of section for EMAIL-LIST exist



        return $result;

    }catch(Exception $e){
        $this->processLog[] = __FUNCTION__.$e->getMessage();
        throw $e;
    }
}

MyCustomerMailer.php

    <?PHP

require 'class/PHPMailer5.2/PHPMailerAutoload.php';

class MyCustomMailer_cl{

public $processLog      = array();
private $dbConnect      = null;

private $phpMailer      = null;
private $SMTPDebug      = null;
private $Debugoutput    = null;
private $Host           = null; //smtp.gmail.com OR smtp-relay.gmail.com
private $Port           = null; //587
private $SMTPSecure     = null; //tls or ssl
private $SMTPAuth       = null; //true or false
private $Username       = null;
private $Password       = null;


private $sentFrom       = array();  //array('example@gmail.com','Joe Doe');
private $replyTo        = array();  //array('example@gmail.com','Joe Doe');
private $emailTo        = array();  //array('example@gmail.com','Joe Doe');
private $subject        = null;     //Plain text
private $body           = null;     //Plain text


public function __construct() {
    try{
        $this->processLog[] = __FUNCTION__;


    }catch(Exception $e){
        $this->processLog[] = __FUNCTION__.$e->getMessage();
        throw $e;
    }
}


/*******************************************************************
                    SET functions
********************************************************************/   

public function setSMTPParam($param) {
    /*
        $param can be a text string 'default' or an array.

        $param = array( 'SMTPDebug'     =>null
                        ,'Debugoutput'  =>null 
                        ,'Host'         =>null 
                        ,'Port'         =>null 
                        ,'SMTPSecure'   =>null 
                        ,'SMTPAuth'     =>null 
                        ,'Username'     =>null 
                        ,'Password'     =>null                          
                        );
    */

    try{
        $this->processLog[] = __FUNCTION__;

        $paramError = 0;
        $result = false;


        if($param=='default'){
            $param = array( 'SMTPDebug'         =>0
                            ,'Debugoutput'      =>'html'
                            ,'Host'             =>'smtp-relay.gmail.com'    //smtp.gmail.com OR smtp-relay.gmail.com
                            ,'Port'             =>587
                            ,'SMTPSecure'       =>'tls'
                            ,'SMTPAuth'         =>true
                            ,'Username'         =>"myEmail@email.com"
                            ,'Password'         =>"myPassword"                          
                        );

        }else if(!is_array($param)){
            throw new Exception('ERROR1901155: SMTP parameter is not an array.');
        }

        //Validation - 2019.01.17 need more work, script randomly fails check here.
        foreach($param as $parameter){
            if($parameter===''  OR is_null($param)){
                $paramError++;
            }
        }


        if($paramError==0){
            $this->SMTPDebug        = $param['SMTPDebug'];
            $this->Debugoutput      = $param['Debugoutput'];
            $this->Host             = $param['Host'];
            $this->Port             = $param['Port'];
            $this->SMTPSecure       = $param['SMTPSecure'];
            $this->SMTPAuth         = $param['SMTPAuth'];
            $this->Username         = $param['Username'];
            $this->Password         = $param['Password'];

            $this->phpMailer = new PHPMailer;
            $this->phpMailer->isSMTP();

            $this->phpMailer->SMTPDebug     = $this->SMTPDebug;
            $this->phpMailer->Debugoutput   = $this->Debugoutput;
            $this->phpMailer->Host          = $this->Host;
            $this->phpMailer->Port          = $this->Port;
            $this->phpMailer->SMTPSecure    = $this->SMTPSecure;
            $this->phpMailer->SMTPAuth      = $this->SMTPAuth;
            $this->phpMailer->Username      = $this->Username;
            $this->phpMailer->Password      = $this->Password;

            $result = true;
        }

        return $result;

    }catch(Exception $e){
        $this->processLog[] = __FUNCTION__.$e->getMessage();
        throw $e;
    }
}   



public function setupEmail($data) {
    try{
        $this->processLog[] = __FUNCTION__;



        $this->sentFrom     = $data['sentFrom'];
        $this->phpMailer->setFrom($this->sentFrom[0],$this->sentFrom[1]);

        $this->replyTo      = $data['replyTo'];
        $this->phpMailer->addReplyTo($this->replyTo[0],$this->replyTo[1]);

        $this->emailTo      = $data['emailTo'];
        $this->phpMailer->addAddress($this->emailTo[0],$this->emailTo[1]);

        $this->subject      = $data['subject'];
        $this->phpMailer->Subject = $this->subject;

        $this->body         = $data['body'];
        $this->phpMailer->msgHTML($this->body);

    }catch(Exception $e){
        $this->processLog[] = __FUNCTION__.$e->getMessage();
        throw $e;
    }
}   

public function send() {
    try{
        $this->processLog[] = __FUNCTION__;
        $result = false;
        if (!$this->phpMailer->send()) {
            // throw new exception("error20190114: Failed to send at final stage.");
            $result = false;
        }else{
            $result = true;
        }

        return $result;


    }catch(Exception $e){
        $this->processLog[] = __FUNCTION__.$e->getMessage();
        throw $e;
    }
}   

public function sendWithRetry($attempt=3,$waitTime=5) {
    try{
        $this->processLog[] = __FUNCTION__;
        $result = false;

        for($i=1;$i<=$attempt;$i++){

            if(!$this->phpMailer->send()){
                if($i==$attempt){
                    break;
                }else{
                    continue;
                }

            }else{
                $result=true;
                break;
            }
        }

        return $result;

    }catch(Exception $e){
        $this->processLog[] = __FUNCTION__.$e->getMessage();
        throw $e;
    }
}   

}

?>

1 个答案:

答案 0 :(得分:0)

我不确定如果您不显示代码,您希望别人如何调试您的代码,但是我猜您可能不知道addAddress的作用(它不称为{{ 1}}是有原因的),并且您可能没有在发送循环中调用setAddress

您的发送速度也很差;我希望发送100条消息所花费的时间不会超过几秒钟。

看看PHPMailer提供的邮件列表示例,该示例解决了所有这些问题。性能建议也可以在PHPMailer项目Wiki上找到。