PHPMailer и Google SMTP-реле. Избыток дубликатов электронной почты с получателем, получающим почту другого клиента - PullRequest
0 голосов
/ 19 января 2019

Я создал скрипт, который отправляет по электронной почте некоторые данные отслеживания для каждого отправленного заказа клиента.

Скрипт построен с помощью PHPMailer и отправляет электронные письма через Google SMTP-Relay Service.

Во время тестирования все работало как положено. Загрузка протестирована с 100 электронными письмами, хотя и на один и тот же адрес электронной почты, все выполнено, как и ожидалось. Нет дубликатов или пропущенных писем.

Однако вскоре после выхода в эфир мне сказали, что несколько клиентов получили десятки электронных писем с подробностями отслеживания других клиентов.

С пользователями gmail они получили отслеживающее электронное письмо другого клиента со своим адресом электронной почты как отправленное.

Пользователи Outlook получают электронное письмо другого клиента со многими электронными письмами в зоне отправления.

Я просмотрел код, протестировал и проверил вывод каждой функции, полностью потерянный там, где он мог пойти не так.

Ниже приведен процесс sudo сценария. Посмотрим, не мог бы кто-нибудь дать несколько советов о том, как можно решить эту проблему.

  1. Получить список электронных писем в одномерный массив.
  2. Создание экземпляра PHPMailer
  3. Для каждого электронного письма в массиве отправьте электронное письмо, дождитесь ИСТИННОГО ответа, если ЛОЖЬ, ПОДОЖДИТЕ 5 с, повторите попытку 3 раза, если превышаете ПРОДОЛЖИТЬ.
  4. После завершения сценарий завершается.

Другие заметки

Сценарий запускается планировщиком задач Windows.

Выполнение сценария займет около 2-10 минут в зависимости от того, сколько попыток выполнено, хотя планировщик настроен на запуск каждые 5 минут, но задание в планировщике настроено так, чтобы не запускать несколько экземпляров задачи, если запущено существующее .

Любые предложения будут великолепны.

Приветствия

Фрагмент кода. Надеюсь, предоставит достаточную идею.

Общий процесс - вызов скрипта sendTrackingEmails () из Dispatcher_cl.php, где он затем использует различные функции из 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 голосов
/ 19 января 2019

Я не уверен, как вы ожидаете, что кто-нибудь сможет отлаживать ваш код, если вы его не показываете, но я думаю, вы не знаете, что делает addAddress (это не называется setAddress для причина), и вы, вероятно, не вызываете clearAddresses в цикле отправки.

Ваша скорость отправки также очень низкая; Я ожидаю, что отправка 100 сообщений займет не более нескольких секунд.

Взгляните на пример списка рассылки, предоставляемый PHPMailer, в котором рассматриваются все эти вещи. Рекомендации по производительности также можно найти в вики проекта PHPMailer.

...