Projekt

Obecné

Profil

Stáhnout (5.91 KB) Statistiky
| Větev: | Tag: | Revize:
<?php

/**
* Handles batch mailing with Swift Mailer with fail-safe support.
* Restarts the connection if it dies and then continues where it left off.
* Please read the LICENSE file
* @copyright Chris Corbyn <chris@w3style.co.uk>
* @author Chris Corbyn <chris@w3style.co.uk>
* @package Swift
* @license GNU Lesser General Public License
*/
class Swift_BatchMailer
{
/**
* The current instance of Swift.
* @var Swift
*/
protected $swift;
/**
* The maximum number of times a single recipient can be attempted before giving up.
* @var int
*/
protected $maxTries = 2;
/**
* The number of seconds to sleep for if an error occurs.
* @var int
*/
protected $sleepTime = 0;
/**
* Failed recipients (undeliverable)
* @var array
*/
protected $failed = array();
/**
* The maximum number of successive failures before giving up.
* @var int
*/
protected $maxFails = 0;
/**
* A temporary copy of some message headers.
* @var array
*/
protected $headers = array();
/**
* Constructor.
* @param Swift The current instance of Swift
*/
public function __construct(Swift $swift)
{
$this->setSwift($swift);
}
/**
* Set the current Swift instance.
* @param Swift The instance
*/
public function setSwift(Swift $swift)
{
$this->swift = $swift;
}
/**
* Get the Swift instance which is running.
* @return Swift
*/
public function getSwift()
{
return $this->swift;
}
/**
* Set the maximum number of times a single address is allowed to be retried.
* @param int The maximum number of tries.
*/
public function setMaxTries($max)
{
$this->maxTries = abs($max);
}
/**
* Get the number of times a single address will be attempted in a batch.
* @return int
*/
public function getMaxTries()
{
return $this->maxTries;
}
/**
* Set the amount of time to sleep for if an error occurs.
* @param int Number of seconds
*/
public function setSleepTime($secs)
{
$this->sleepTime = abs($secs);
}
/**
* Get the amount of time to sleep for on errors.
* @return int
*/
public function getSleepTime()
{
return $this->sleepTime;
}
/**
* Log a failed recipient.
* @param string The email address.
*/
public function addFailedRecipient($address)
{
$this->failed[] = $address;
$this->failed = array_unique($this->failed);
}
/**
* Get all recipients which failed in this batch.
* @return array
*/
public function getFailedRecipients()
{
return $this->failed;
}
/**
* Clear out the list of failed recipients.
*/
public function flushFailedRecipients()
{
$this->failed = null;
$this->failed = array();
}
/**
* Set the maximum number of times an error can be thrown in succession and still be hidden.
* @param int
*/
public function setMaxSuccessiveFailures($fails)
{
$this->maxFails = abs($fails);
}
/**
* Get the maximum number of times an error can be thrown and still be hidden.
* @return int
*/
public function getMaxSuccessiveFailures()
{
return $this->maxFails;
}
/**
* Restarts Swift forcibly.
*/
protected function forceRestartSwift()
{
//Pre-empting problems trying to issue "QUIT" to a dead connection
$this->swift->connection->stop();
$this->swift->connection->start();
$this->swift->disconnect();
//Restart swift
$this->swift->connect();
}
/**
* Takes a temporary copy of original message headers in case an error occurs and they need restoring.
* @param Swift_Message The message object
*/
protected function copyMessageHeaders(&$message)
{
$this->headers["To"] = $message->headers->has("To") ?
$message->headers->get("To") : null;
$this->headers["Reply-To"] = $message->headers->has("Reply-To") ?
$message->headers->get("Reply-To") : null;
$this->headers["Return-Path"] = $message->headers->has("Return-Path") ?
$message->headers->get("Return-Path") : null;
$this->headers["From"] = $message->headers->has("From") ?
$message->headers->get("From") : null;
}
/**
* Restore message headers to original values in the event of a failure.
* @param Swift_Message The message
*/
protected function restoreMessageHeaders(&$message)
{
foreach ($this->headers as $name => $value)
{
$message->headers->set($name, $value);
}
}
/**
* Run a batch send in a fail-safe manner.
* This operates as Swift::batchSend() except it deals with errors itself.
* @param Swift_Message To send
* @param Swift_RecipientList Recipients (To: only)
* @param Swift_Address The sender's address
* @return int The number sent to
*/
public function send(Swift_Message $message, Swift_RecipientList $recipients, $sender)
{
$sent = 0;
$successive_fails = 0;
$it = $recipients->getIterator("to");
while ($it->hasNext())
{
$it->next();
$recipient = $it->getValue();
$tried = 0;
$loop = true;
while ($loop && $tried < $this->getMaxTries())
{
try {
$tried++;
$loop = false;
$this->copyMessageHeaders($message);
$sent += ($n = $this->swift->send($message, $recipient, $sender));
if (!$n) $this->addFailedRecipient($recipient->getAddress());
$successive_fails = 0;
} catch (Exception $e) {
$successive_fails++;
$this->restoreMessageHeaders($message);
if (($max = $this->getMaxSuccessiveFailures())
&& $successive_fails > $max)
{
throw new Exception(
"Too many successive failures. BatchMailer is configured to allow no more than " . $max .
" successive failures.");
}
//If an exception was thrown, give it one more go
if ($t = $this->getSleepTime()) sleep($t);
$this->forceRestartSwift();
$loop = true;
}
}
}
return $sent;
}
}
(5-5/20)