vendor/swiftmailer/lib/classes/Swift/FileSpool.php
changeset 0 7f95f8617b0b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/swiftmailer/lib/classes/Swift/FileSpool.php	Sat Sep 24 15:40:41 2011 +0200
@@ -0,0 +1,208 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages on the filesystem.
+ * @package Swift
+ * @author  Fabien Potencier
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+class Swift_FileSpool extends Swift_ConfigurableSpool
+{
+  /** The spool directory */
+  private $_path;
+  
+  /**
+   * File WriteRetry Limit
+   * @var int
+   */
+  private $_retryLimit=10;
+  
+  /**
+   * Create a new FileSpool.
+   * @param string $path
+   * @throws Swift_IoException
+   */
+  public function __construct($path)
+  {
+    $this->_path = $path;
+    
+    if (!file_exists($this->_path))
+    {
+      if (!mkdir($this->_path, 0777, true))
+      {
+        throw new Swift_IoException('Unable to create Path ['.$this->_path.']');
+      }
+    }
+  }
+  
+  /**
+   * Tests if this Spool mechanism has started.
+   *
+   * @return boolean
+   */
+  public function isStarted()
+  {
+    return true;
+  }
+  
+  /**
+   * Starts this Spool mechanism.
+   */
+  public function start()
+  {
+  }
+  
+  /**
+   * Stops this Spool mechanism.
+   */
+  public function stop()
+  {
+  }
+  
+  /**
+   * Allow to manage the enqueuing retry limit.
+   * Default, is ten and allows over 64^20 different fileNames 
+   * 
+   * @param integer $limit
+   */
+  public function setRetryLimit($limit)
+  {
+    $this->_retryLimit=$limit;
+  }
+  
+  /**
+   * Queues a message.
+   * @param Swift_Mime_Message $message The message to store
+   * @return boolean
+   * @throws Swift_IoException
+   */
+  public function queueMessage(Swift_Mime_Message $message)
+  {
+    $ser = serialize($message);
+    $fileName=$this->_path.'/'.$this->getRandomString(10);
+    for ($i = 0; $i < $this->_retryLimit; ++$i) 
+    {
+      /* We try an exclusive creation of the file
+       * This is an atomic operation, it avoid locking mechanism
+       */
+      $fp=fopen($fileName.'.message', 'x');
+      if ($fp) 
+      {
+        fwrite($fp, $ser);
+        fclose($fp);
+        
+        return;
+      } 
+      else 
+      {
+        /* The file allready exists, we try a longer fileName
+         */
+        $fileName.=$this->getRandomString(1);
+      }
+    }
+    
+    throw new Swift_IoException('Unable to create a file for enqueuing Message');
+  }
+  
+  /**
+   * Execute a recovery if for anyreason a process is sending for too long
+   * 
+   * @param int $timeout in second Defaults is for very slow smtp responses
+   */
+  public function recover($timeout=900)
+  {
+    foreach (new DirectoryIterator($this->_path) as $file)
+    {
+      $file = $file->getRealPath();
+
+      if (substr($file, -16)=='.message.sending')
+      {
+        $lockedtime=filectime($file);
+        if ((time()-$lockedtime)>$timeout) 
+        {
+          rename($file, substr($file, 0, -8));
+        }
+      }
+    }    
+  }
+  
+  /**
+   * Sends messages using the given transport instance.
+   *
+   * @param Swift_Transport $transport         A transport instance
+   * @param string[]        &$failedRecipients An array of failures by-reference
+   *
+   * @return int The number of sent emails
+   */
+  public function flushQueue(Swift_Transport $transport, &$failedRecipients = null)
+  {
+    if (!$transport->isStarted())
+    {
+      $transport->start();
+    }
+
+    $failedRecipients = (array) $failedRecipients;
+    $count = 0;
+    $time = time();
+    foreach (new DirectoryIterator($this->_path) as $file)
+    {
+      $file = $file->getRealPath();
+
+      if (substr($file, -8) != '.message')
+      {
+        continue;
+      }
+
+      /* We try a rename, it's an atomic operation, and avoid locking the file */
+      if (rename($file, $file.'.sending')) 
+      {
+        $message = unserialize(file_get_contents($file.'.sending'));
+
+        $count += $transport->send($message, $failedRecipients);
+
+        unlink($file.'.sending');
+      }
+      else 
+      {
+        /* This message has just been catched by another process */
+        continue;
+      }
+
+      if ($this->getMessageLimit() && $count >= $this->getMessageLimit())
+      {
+        break;
+      }
+
+      if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit())
+      {
+        break;
+      }
+    }
+
+    return $count;
+  }
+  
+  /**
+   * Returns a random string needed to generate a fileName for the queue.
+   * @param int $count
+   */
+  protected function getRandomString($count) {
+    // This string MUST stay FS safe, avoid special chars
+    $base="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";
+    $ret='';
+    $strlen=strlen($base);
+    for ($i=0; $i<$count; ++$i) 
+    {
+      $ret.=$base[((int)rand(0,$strlen-1))];
+    }
+    return $ret;
+  }
+}