Advertisement
Guest User

Untitled

a guest
Feb 1st, 2018
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 16.13 KB | None | 0 0
  1. <?php
  2.  
  3. class AmazonSES
  4. {
  5.     public $Multithread = false;
  6.     public $CampaignID  = 0;
  7.     public $SubscriberID = 0;
  8.     public $Timezone = '';
  9.     public $SendRate = 0;
  10.     public $IsAutoresponder = false;
  11.    
  12.     public $amazonSES_base_url = '';
  13.     public $debug = FALSE;
  14.  
  15.     public $aws_access_key_id = "";
  16.     public $aws_secret_key = "";
  17.  
  18.     protected function
  19.     make_required_http_headers () {
  20.         $headers = array();
  21.        
  22.         if($this->Timezone=='' || $this->Timezone==0) $this->Timezone = date_default_timezone_get();
  23.         date_default_timezone_set($this->Timezone);
  24.        
  25.         $date_value = date(DATE_RFC2822);
  26.         $headers[] = "Date: {$date_value}";
  27.  
  28.         $signature = base64_encode(hash_hmac("sha1",
  29.                                              $date_value,
  30.                                              $this->aws_secret_key,
  31.                                              TRUE));
  32.  
  33.         $headers[] =
  34.             "X-Amzn-Authorization: AWS3-HTTPS "
  35.             ."AWSAccessKeyId={$this->aws_access_key_id},"
  36.             ."Algorithm=HmacSHA1,Signature={$signature}";
  37.  
  38.         $headers[] =
  39.             "Content-Type: application/x-www-form-urlencoded";
  40.  
  41.         return $headers;
  42.     }
  43.  
  44.     protected function
  45.     make_query_string
  46.     ($query) {
  47.         $query_str = "";
  48.         foreach ($query as $k => $v)
  49.             { $query_str .= urlencode($k)."=".urlencode($v).'&'; }
  50.  
  51.         return rtrim($query_str, '&');
  52.     }
  53.  
  54.     protected function
  55.     parse_amazonSES_error
  56.     ($response) {
  57.         $sxe = simplexml_load_string($response);
  58.  
  59.         // If the error response can not be parsed properly,
  60.         // then just return the original response content.
  61.         if (($sxe === FALSE) or ($sxe->getName() !== "ErrorResponse"))
  62.             { return $response; }
  63.  
  64.         return "{$sxe->Error->Code}"
  65.                .(($sxe->Error->Message)?" - {$sxe->Error->Message}":"");
  66.     }
  67.  
  68.     protected function
  69.     make_request
  70.     ($query) {
  71.         $dbHost=$dbUser=$dbPass=$dbName='';
  72.         if(file_exists('../config.php')) require '../config.php';
  73.         $server_path_array1 = explode('/', $_SERVER['SCRIPT_FILENAME']);       
  74.         $delimiter = $server_path_array1[count($server_path_array1)-1];
  75.         if($delimiter=='send-now.php') $delimiter = 'includes';
  76.         $server_path_array = explode($delimiter, $_SERVER['SCRIPT_FILENAME']);
  77.         $server_path = $server_path_array[0];
  78.         if(file_exists($server_path.'includes/config.php')) require $server_path.'includes/config.php';
  79.         if(isset($dbPort)) $mysqli = new mysqli($dbHost, $dbUser, $dbPass, $dbName, $dbPort);
  80.         else $mysqli = new mysqli($dbHost, $dbUser, $dbPass, $dbName);
  81.        
  82.         //Get SES endpoint
  83.         $q = 'SELECT ses_endpoint FROM login LIMIT 1';
  84.         $r = mysqli_query($mysqli, $q);
  85.         if ($r) while($row = mysqli_fetch_array($r)) $this->amazonSES_base_url = 'https://'.$row['ses_endpoint'];
  86.        
  87.         // Prepare headers and query string.
  88.         $request_url = $this->amazonSES_base_url;
  89.         $query_str = $this->make_query_string($query);
  90.         $http_headers = $this->make_required_http_headers();
  91.  
  92.         if ($this->debug) {
  93.             echo "[AmazonSESDebug] Query Parameters:\n\"";
  94.             print_r($query);
  95.             echo "\"\n";
  96.  
  97.             printf("[AmazonSES Debug] Http Headers:\n\"%s\"\n",
  98.                                       implode("\n", $http_headers));
  99.             printf("[AmazonSES Debug] Query String:\n\"%s\"\n", $query_str);
  100.         }
  101.        
  102.         //if multithreading is needed,
  103.         if($this->Multithread)
  104.         {
  105.             //Insert SES query into queue
  106.             $q8 = 'SELECT count(*) FROM queue WHERE campaign_id = '.$this->CampaignID.' AND subscriber_id = '.$this->SubscriberID;
  107.             $r8 = mysqli_query($mysqli, $q8);
  108.             if ($r8)
  109.             {
  110.                 while($row = mysqli_fetch_array($r8)) $no_of_matching_email_in_queue = $row['count(*)'];
  111.                
  112.                 //if email does not exist in queue
  113.                 if($no_of_matching_email_in_queue==0)
  114.                 {
  115.                     $q = 'INSERT INTO queue (query_str, campaign_id, subscriber_id) VALUES ("'.addslashes($query_str).'", '.$this->CampaignID.', '.$this->SubscriberID.')';
  116.                     $q4 = 'UPDATE subscribers SET last_campaign = '.$this->CampaignID.' WHERE id = '.$this->SubscriberID; //Update last_campaign in subscribers table
  117.                     mysqli_query($mysqli, $q);
  118.                     mysqli_query($mysqli, $q4);
  119.                 }
  120.             }
  121.            
  122.             //Check if there are more than X (where X is the send rate) emails in queue, send them in parallel to SES
  123.             $q2 = 'SELECT id, query_str, subscriber_id FROM queue WHERE campaign_id = '.$this->CampaignID.' AND sent = 0 LIMIT '.$this->SendRate;
  124.             $r2 = mysqli_query($mysqli, $q2);
  125.             if ($r2 && mysqli_num_rows($r2) >= $this->SendRate)
  126.             {
  127.                 $id_array = array();
  128.                 $time_started = microtime();
  129.                
  130.                 if (!function_exists('on_request_done'))
  131.                 {
  132.                     function on_request_done($content, $url, $ch, $callback_data)
  133.                     {                      
  134.                         $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);    
  135.                         if ($httpcode !== 200) //if fail
  136.                         {                          
  137.                             // Pause for one second then retry sending
  138.                             sleep(1);
  139.                             $cr = curl_init();
  140.                             curl_setopt($cr, CURLOPT_URL, $callback_data[2]);
  141.                             curl_setopt($cr, CURLOPT_POST, $callback_data[1]);
  142.                             curl_setopt($cr, CURLOPT_POSTFIELDS, $callback_data[1]);
  143.                             curl_setopt($cr, CURLOPT_HTTPHEADER, $callback_data[3]);
  144.                             curl_setopt($cr, CURLOPT_HEADER, TRUE);
  145.                             curl_setopt($cr, CURLOPT_RETURNTRANSFER, TRUE);
  146.                             curl_setopt($cr, CURLOPT_SSL_VERIFYHOST, 2);
  147.                             curl_setopt($cr, CURLOPT_SSL_VERIFYPEER, 1);
  148.                             curl_setopt($cr, CURLOPT_CAINFO, $server_path.'certs/cacert.pem');
  149.                             $response = curl_exec($cr);
  150.                    
  151.                             // Get http status code
  152.                             $response_http_status_code = curl_getinfo($cr, CURLINFO_HTTP_CODE);
  153.                            
  154.                             if($response_http_status_code !== 200)
  155.                             {
  156.                                 $q7 = 'SELECT errors FROM campaigns WHERE id = '.$callback_data[4];
  157.                                 $r7 = mysqli_query($mysqli, $q7);
  158.                                 if ($r7)
  159.                                 {
  160.                                     while($row = mysqli_fetch_array($r7))
  161.                                     {
  162.                                         $errors = $row['errors'];
  163.                                        
  164.                                         if($errors=='')
  165.                                             $val = $callback_data[0].':'.$response_http_status_code;
  166.                                         else
  167.                                         {
  168.                                             $errors .= ','.$callback_data[0].':'.$response_http_status_code;
  169.                                             $val = $errors;
  170.                                         }
  171.                                     }  
  172.                                 }
  173.            
  174.                                 //update campaigns' errors column
  175.                                 $q6 = 'UPDATE campaigns SET errors = "'.$val.'" WHERE id = '.$callback_data[4];
  176.                                 mysqli_query($mysqli, $q6);
  177.                             }
  178.                         }
  179.                     }
  180.                 }
  181.                
  182.                 $mh = curl_multi_init();
  183.                 $outstanding_requests = array();
  184.                
  185.                 while($row = mysqli_fetch_array($r2))
  186.                 {
  187.                     $queue_id = $row['id'];
  188.                     $queue = stripslashes($row['query_str']);  
  189.                     $subscriber_id = $row['subscriber_id'];
  190.                     array_push($id_array, $queue_id);
  191.                    
  192.                     // Prepare curl.
  193.                     $ch = curl_init();                 
  194.                     curl_setopt($ch, CURLOPT_URL, $request_url);
  195.                     curl_setopt($ch, CURLOPT_POST, $queue);
  196.                     curl_setopt($ch, CURLOPT_POSTFIELDS, $queue);
  197.                     curl_setopt($ch, CURLOPT_HTTPHEADER, $http_headers);
  198.                     curl_setopt($ch, CURLOPT_HEADER, TRUE);
  199.                     curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  200.                     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
  201.                     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
  202.                     curl_setopt($ch, CURLOPT_CAINFO, $server_path.'certs/cacert.pem');
  203.                    
  204.                     //add handle
  205.                     curl_multi_add_handle($mh, $ch);
  206.                    
  207.                     $ch_array_key = (int)$ch;
  208.  
  209.                     $outstanding_requests[$ch_array_key] = array(
  210.                         'url' => $request_url,
  211.                         'callback' => 'on_request_done',
  212.                         'user_data' => array($subscriber_id, $queue, $request_url, $http_headers, $this->CampaignID)
  213.                     );
  214.                 }
  215.                
  216.                 //Batch processing started
  217.                 $in_id = implode(',', $id_array);
  218.                 $q4 = 'UPDATE queue SET sent = 1, query_str = NULL WHERE id IN ('.$in_id.')'; //update sent status to 1
  219.                 $q5 = 'UPDATE campaigns SET recipients = recipients+'.count($id_array).', timeout_check = NULL WHERE recipients < to_send AND id = '.$this->CampaignID; //increment recipients number in campaigns table
  220.                 mysqli_query($mysqli, $q4);
  221.                 mysqli_query($mysqli, $q5);
  222.                 $id_array = array();
  223.                
  224.                 $messageID_array = array();
  225.                 $subscriberIDArray = array();
  226.                
  227.                 //execute the handles
  228.                 $active = null;
  229.                 do
  230.                 {
  231.                     $mrc = curl_multi_exec($mh, $active);
  232.                     usleep(1);
  233.                    
  234.                     while ($info=curl_multi_info_read($mh))
  235.                     {  
  236.                         $ch = $info['handle'];
  237.                         $ch_array_key = (int)$ch;
  238.                        
  239.                         $request = $outstanding_requests[$ch_array_key];
  240.            
  241.                         $url = $request['url'];
  242.                         $content = curl_multi_getcontent($ch);
  243.                         $callback = $request['callback'];
  244.                         $user_data = $request['user_data'];
  245.                        
  246.                         ////Prepare messageID & subscriberID array
  247.                         $messageIDArray = explode('<MessageId>', $content);
  248.                         $messageIDArray2 = explode('</MessageId>', $messageIDArray[1]);
  249.                         array_push($messageID_array, $messageIDArray2[0]);
  250.                         array_push($subscriberIDArray, $user_data[0]);
  251.                        
  252.                         call_user_func($callback, $content, $url, $ch, $user_data);
  253.                        
  254.                         unset($outstanding_requests[$ch_array_key]);
  255.                        
  256.                         curl_multi_remove_handle($mh, $ch);
  257.                     }
  258.                 } while ($mrc == CURLM_CALL_MULTI_PERFORM || ($active && $mrc == CURLM_OK));
  259.                
  260.                 curl_multi_close($mh);
  261.                
  262.                 //update messageID of each subscriber in one query
  263.                 $when = '';
  264.                 for($w=0;$w<count($messageID_array);$w++) $when .= 'WHEN '.$subscriberIDArray[$w].' THEN "'.$messageID_array[$w].'" ';
  265.                 $q14 = "UPDATE subscribers SET messageID = CASE id $when END WHERE id IN (".implode(',',$subscriberIDArray).")";
  266.                 mysqli_query($mysqli, $q14);
  267.                
  268.                 //throttling
  269.                 $time_taken = microtime() - $time_started;
  270.                 $usleep = ceil((1 - $time_taken) * 1000000);
  271.                 if($time_taken < 1) usleep($usleep);
  272.             }
  273.         }
  274.        
  275.         else
  276.         {
  277.             //Get server path
  278.             $server_path_array2 = explode('includes/', $_SERVER['SCRIPT_FILENAME']);
  279.             $server_path2 = $server_path_array2[0];
  280.             if(count($server_path_array2)==1) $server_path2 = $server_path;
  281.        
  282.             // Prepare curl.
  283.             $cr = curl_init();
  284.             curl_setopt($cr, CURLOPT_URL, $request_url);
  285.             curl_setopt($cr, CURLOPT_POST, $query_str);
  286.             curl_setopt($cr, CURLOPT_POSTFIELDS, $query_str);
  287.             curl_setopt($cr, CURLOPT_HTTPHEADER, $http_headers);
  288.             curl_setopt($cr, CURLOPT_HEADER, TRUE);
  289.             curl_setopt($cr, CURLOPT_RETURNTRANSFER, TRUE);
  290.             curl_setopt($cr, CURLOPT_SSL_VERIFYHOST, 2);
  291.             curl_setopt($cr, CURLOPT_SSL_VERIFYPEER, 1);
  292.             curl_setopt($cr, CURLOPT_CAINFO, $server_path2.'certs/cacert.pem');
  293.    
  294.             // Make the request and fetch response.
  295.             $response = curl_exec($cr);
  296.    
  297.             // Separate header and content.
  298.             $tmpar = explode("\r\n\r\n", $response, 2);
  299.             $response_http_headers = $tmpar[0];
  300.             $response_content = $tmpar[1];
  301.    
  302.             // Parse the http status code.
  303.             $tmpar = explode(" ", $response_http_headers, 3);
  304.             $response_http_status_code = $tmpar[1];
  305.            
  306.             // Parse the http status code from content.
  307.             $tmpar2 = explode(" ", $response_content, 3);
  308.             $response_http_status_code2 = $tmpar2[1];
  309.            
  310.             if($response_http_status_code2==400)
  311.             {
  312.                 //Response title
  313.                 $response_title_array1 = explode('<Code>', $response_content);
  314.                 $response_title_array2 = explode('</Code>', $response_title_array1[1]);
  315.                 $response_title = $response_title_array2[0];
  316.                
  317.                 //Response message
  318.                 $response_msg_array1 = explode('<Message>', $response_content);
  319.                 $response_msg_array2 = explode('</Message>', $response_msg_array1[1]);
  320.                 $response_msg = $response_msg_array2[0];
  321.                
  322.                 //Response requestID
  323.                 $response_rqid_array1 = explode('<RequestId>', $response_content);
  324.                 $response_rqid_array2 = explode('</RequestId>', $response_rqid_array1[1]);
  325.                 $response_rqid = $response_rqid_array2[0];
  326.                
  327.                 $the_error = array();
  328.                 $the_error['code'] = $response_http_status_code2;
  329.                 $the_error['full_error'] = $response_title.' (Request ID: '.$response_rqid.'): '.$response_msg;
  330.                
  331.                 //Write to error_log
  332.                 error_log($the_error['full_error']);
  333.                
  334.                 return $the_error;
  335.             }
  336.            
  337.             //Check if there's a campaign/autoresponder ID
  338.             if($this->CampaignID != '')
  339.             {
  340.                 //Get message ID from response
  341.                 $messageIDArray = explode('<MessageId>', $response);
  342.                 $messageIDArray2 = explode('</MessageId>', $messageIDArray[1]);
  343.                 $messageID = $messageIDArray2[0];
  344.                
  345.                 //Update subscriber's messageID if it's an Autoresponder
  346.                 if($this->IsAutoresponder)
  347.                 {
  348.                     $q9 = 'UPDATE subscribers SET messageID = "'.$messageID.'" WHERE id = '.$this->SubscriberID;
  349.                     mysqli_query($mysqli, $q9);
  350.                 }
  351.                 //Increment recipients number in campaigns table if it's a campaign
  352.                 else
  353.                 {
  354.                     $q5 = 'UPDATE campaigns SET recipients = recipients+1 WHERE id = '.$this->CampaignID;
  355.                     $q9 = 'UPDATE subscribers SET last_campaign = '.$this->CampaignID.', messageID = "'.$messageID.'" WHERE id = '.$this->SubscriberID;
  356.                     mysqli_query($mysqli, $q5);
  357.                     mysqli_query($mysqli, $q9);
  358.                 }
  359.             }
  360.         }
  361.     }
  362.  
  363.     //***********************************************************************
  364.     // Name: send_mail
  365.     // Description:
  366.     //    Send mail using amazonSES. Provide $header, $subject,
  367.     //    $body appropriately. The $recipients and $from are mostly expe-
  368.     //    rimental and unneccessary as documented in the SES api.
  369.     //
  370.     //    Return an array in the form -
  371.     //        array(http_status_code, response_content)
  372.     //    if the http_status_code is something other than "200", then
  373.     //    the response_content is an error message parsed from the response.
  374.     //***********************************************************************
  375.    
  376.     public function
  377.     send_mail
  378.     ($header, $subject, $body,
  379.      $recipients=FALSE, $from=FALSE) {
  380.         // Make sure that there is a blank line between header and body.
  381.         $raw_mail = rtrim($header, "\r\n")."\n\n".$body;
  382.  
  383.         // Prepare query.
  384.         //*********************************************************//
  385.         $query = array();
  386.         $query["Action"] = "SendRawEmail";
  387.  
  388.         // Add optional Destination.member.N request parameter.
  389.         if ($recipients) {
  390.             $mcnt = 1;
  391.             foreach ($recipients as $recipient) {
  392.                 $query["Destinations.member.{$mcnt}"] = $recipient;
  393.                 $mcnt += 1;
  394.             }
  395.         }
  396.  
  397.         // Add optional Source parameter.
  398.         if ($from)
  399.             { $query["Source"] = $from; }
  400.  
  401.         // Add mail data.
  402.         $query["RawMessage.Data"] = base64_encode($raw_mail);
  403.         //*********************************************************//
  404.  
  405.         // Send the mail and forward the result array to the caller.
  406.         return $this->make_request($query);
  407.     }
  408.  
  409.     public function
  410.     request_verification
  411.     ($email_address) {
  412.         $query = array();
  413.  
  414.         $query["Action"] = "VerifyEmailAddress";
  415.         $query["EmailAddress"] = $email_address;
  416.  
  417.         return $this->make_request($query);
  418.     }
  419. }
  420.  
  421. /* End of file */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement