Add EmailDeliveryBackgroundJob and DebugEmailTransport
authorTim Düsterhus <duesterhus@woltlab.com>
Mon, 15 Jun 2015 19:11:04 +0000 (21:11 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Tue, 23 Jun 2015 22:28:53 +0000 (00:28 +0200)
wcfsetup/install/files/lib/system/background/job/EmailDeliveryBackgroundJob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/email/Email.class.php
wcfsetup/install/files/lib/system/email/mime/AttachmentMimePart.class.php
wcfsetup/install/files/lib/system/email/transport/DebugEmailTransport.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/email/transport/EmailTransport.class.php [new file with mode: 0644]

diff --git a/wcfsetup/install/files/lib/system/background/job/EmailDeliveryBackgroundJob.class.php b/wcfsetup/install/files/lib/system/background/job/EmailDeliveryBackgroundJob.class.php
new file mode 100644 (file)
index 0000000..93d52a9
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+namespace wcf\system\background\job;
+use wcf\system\email\Email;
+use wcf\system\email\Mailbox;
+
+/**
+ * Delivers the given email to the given mailbox.
+ * 
+ * @author     Tim Duesterhus
+ * @copyright  2001-2015 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.background.job
+ * @category   Community Framework
+ */
+class EmailDeliveryBackgroundJob extends AbstractBackgroundJob {
+       /**
+        * email to send
+        * @var \wcf\system\email\Email
+        */
+       protected $email;
+       
+       /**
+        * recipient mailbox
+        * @var \wcf\system\email\Mailbox
+        */
+       protected $mailbox;
+       
+       /**
+        * instance of the default transport
+        * @var \wcf\system\email\transport\EmailTransport
+        */
+       protected static $transport = null;
+       
+       /**
+        * Creates the job using the given the email and the destination mailbox.
+        * 
+        * @param       \wcf\system\email\Email         $email
+        * @param       \wcf\system\email\Mailbox       $mailbox
+        * @see         \wcf\system\email\transport\EmailTransport
+        */
+       public function __construct(Email $email, Mailbox $mailbox) {
+               $this->email = $email;
+               $this->mailbox = $mailbox;
+       }
+       
+       /**
+        * Emails will be sent with an increasing timeout between the tries.
+        * 
+        * @return      int     5 minutes, 30 minutes, 2 hours.
+        */
+       public function retryAfter() {
+               switch ($this->getFailures()) {
+                       case 1:
+                               return 5 * 60;
+                       case 2:
+                               return 30 * 60;
+                       case 3:
+                               return 2 * 60 * 60;
+               }
+       }
+       
+       /**
+        * @see \wcf\system\background\job\AbstractJob::perform();
+        */
+       public function perform() {
+               if (self::$transport === null) {
+                       $name = '\wcf\system\email\transport\\'.ucfirst(MAIL_SEND_METHOD).'EmailTransport';
+                       self::$transport = new $name();
+               }
+               
+               self::$transport->deliver($this->email, $this->mailbox);
+       }
+}
index b79e440816f96871834164c1d3ecc6bb5b0b9516..bd1cd0f818ef5b10ea4322c01a869211f4eda1a1 100644 (file)
@@ -1,7 +1,9 @@
 <?php
 namespace wcf\system\email;
+use wcf\system\background\job\EmailDeliveryBackgroundJob;
 use wcf\system\email\mime\AbstractMimePart;
 use wcf\system\email\mime\TextMimePart;
+use wcf\system\event\EventHandler;
 use wcf\system\exception\SystemException;
 use wcf\util\DateUtil;
 use wcf\util\StringUtil;
@@ -361,7 +363,7 @@ class Email {
                        throw new SystemException("The header '".$header."' may not be set. You may only set user defined headers (starting with 'X-').");
                }
                
-               $this->extraHeaders[] = [ $header, EmailGrammar::encodeMimeHeader($value) ];
+               $this->extraHeaders[] = [ $header, EmailGrammar::encodeQuotedPrintableHeader($value) ];
        }
        
        /**
@@ -559,9 +561,41 @@ class Email {
                        $body .= $text;
                }
                
+               // TODO: Where to put the email signature?
+               
                return $body;
        }
        
+       /**
+        * Returns needed AbstractBackgroundJobs to deliver this email to every recipient.
+        * 
+        * @return      array<\wcf\system\background\job\AbstractBackgroundJob>
+        */
+       public function getJobs() {
+               $jobs = [ ];
+               
+               // ensure every header is filled in
+               $this->getHeaders();
+               
+               foreach ($this->recipients as $recipient) {
+                       $mail = clone $this;
+                       
+                       if ($recipient[1] instanceof UserMailbox) {
+                               $mail->addHeader('X-Community-Framework-Recipient', $recipient[1]->getUser()->username);
+                       }
+                       
+                       $data = [ 'mail' => $mail, 'recipient' => $recipient, 'skip' => false ];
+                       EventHandler::getInstance()->fireAction($this, 'getJobs', $data);
+                       
+                       // an event decided that this email should be skipped
+                       if ($data['skip']) continue;
+                       
+                       $jobs[] = new EmailDeliveryBackgroundJob($mail, $recipient[1]);
+               }
+               
+               return $jobs;
+       }
+       
        /**
         * Returns the email RFC 2822 representation of this email.
         * 
index ee1a16903d7941d0e0400176f39ea48f38225533..b1dcc69e884392f5fbe2d3523ce83b8ea88ab06d 100644 (file)
@@ -32,6 +32,12 @@ class AttachmentMimePart extends AbstractMimePart {
         */
        protected $mimeType;
        
+       /**
+        * the file contents
+        * @var string
+        */
+       protected $content = '';
+       
        /**
         * Creates a new Attachment.
         * 
@@ -47,6 +53,7 @@ class AttachmentMimePart extends AbstractMimePart {
                $this->mimeType = $mimeType ?: (FileUtil::getMimeType($path) ?: 'application/octet-stream');
                $this->path = $path;
                $this->filename = $filename ?: basename($path);
+               $this->content = file_get_contents($this->path);
        }
        
        /**
@@ -78,6 +85,6 @@ class AttachmentMimePart extends AbstractMimePart {
         * @see \wcf\system\email\mime\AbstractMimePart::getContent()
         */
        public function getContent() {
-               return file_get_contents($this->path);
+               return $this->content;
        }
 }
diff --git a/wcfsetup/install/files/lib/system/email/transport/DebugEmailTransport.class.php b/wcfsetup/install/files/lib/system/email/transport/DebugEmailTransport.class.php
new file mode 100644 (file)
index 0000000..5ef9660
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+namespace wcf\system\email\transport;
+use wcf\system\email\Email;
+use wcf\system\email\Mailbox;
+use wcf\system\io\File;
+use wcf\util\DateUtil;
+
+/**
+ * DebugEmailTransport is a debug implementation of an email transport which writes emails into
+ * a log file.
+ * 
+ * @author     Tim Duesterhus, Alexander Ebert
+ * @copyright  2001-2015 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.email.transport
+ * @category   Community Framework
+ */
+class DebugEmailTransport implements EmailTransport {
+       /**
+        * mbox file
+        * @var \wcf\system\io\File
+        */
+       protected $mbox = null;
+       
+       /**
+        * Creates a new DebugTransport using the given mbox as target.
+        * 
+        * @param       string  $mbox   mbox location or null for default location
+        */
+       public function __construct($mbox = null) {
+               if ($mbox === null) $mbox = WCF_DIR.'log/debug.mbox';
+               
+               $this->mbox = new File($mbox, 'ab');
+       }
+       
+       /**
+        * Writes the given $email into the mbox.
+        * 
+        * @param       \wcf\system\email\Email         $email
+        * @param       \wcf\system\email\Mailbox       $envelopeTo
+        */
+       public function deliver(Email $email, Mailbox $envelopeTo) {
+               $this->mbox->write("From ".$email->getSender()->getAddress()." ".DateUtil::getDateTimeByTimestamp(TIME_NOW)->format('D M d H:i:s Y')."\r\n");
+               $this->mbox->write("Delivered-To: ".$envelopeTo->getAddress()."\r\n");
+               $this->mbox->write($email);
+               $this->mbox->write("\r\n");
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/email/transport/EmailTransport.class.php b/wcfsetup/install/files/lib/system/email/transport/EmailTransport.class.php
new file mode 100644 (file)
index 0000000..b19b70a
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+namespace wcf\system\email\transport;
+use wcf\system\email\Email;
+use wcf\system\email\Mailbox;
+
+/**
+ * An EmailTransport sends emails.
+ * 
+ * @author     Tim Duesterhus
+ * @copyright  2001-2015 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.email.transport
+ * @category   Community Framework
+ */
+interface EmailTransport {
+       /**
+        * Delivers the given $email to the given Mailbox as the recipient.
+        * 
+        * @param       \wcf\system\email\Email         $email
+        * @param       \wcf\system\email\Mailbox       $envelopeTo
+        */
+       public function deliver(Email $email, Mailbox $envelopeTo);
+}