1<?php 2 3/** 4 * Swift Mailer mail() sending plugin 5 * Please read the LICENSE file 6 * @author Chris Corbyn <chris@w3style.co.uk> 7 * @package Swift_Connection 8 * @license GNU Lesser General Public License 9 */ 10 11require_once dirname(__FILE__) . "/../ClassLoader.php"; 12Swift_ClassLoader::load("Swift_Events_SendListener"); 13Swift_ClassLoader::load("Swift_Events_BeforeSendListener"); 14 15/** 16 * Swift mail() send plugin 17 * Sends the message using mail() when a SendEvent is fired. Using the NativeMail connection provides stub responses to allow this to happen cleanly. 18 * @package Swift_Connection 19 * @author Chris Corbyn <chris@w3style.co.uk> 20 */ 21class Swift_Plugin_MailSend implements Swift_Events_SendListener, Swift_Events_BeforeSendListener 22{ 23 /** 24 * The operating system of the server 25 * @var string 26 */ 27 protected $OS = null; 28 /** 29 * The return path in use here 30 * @var string 31 */ 32 protected $returnPath = null; 33 /** 34 * The line ending before we intrusively change it 35 * @var string 36 */ 37 protected $oldLE = "\r\n"; 38 /** 39 * 5th parameter in mail(). 40 * @var string 41 */ 42 protected $additionalParams; 43 44 /** 45 * Constructor. 46 * @param string 5th mail() function parameter as a sprintf() formatted string where %s is the sender. 47 */ 48 public function __construct($params="-oi -f %s") 49 { 50 $this->setAdditionalParams($params); 51 $this->setOS(PHP_OS); 52 } 53 /** 54 * Set the 5th mail() function parameter as a sprintf() formatted string where %s is the sender. 55 * @param string 56 */ 57 public function setAdditionalParams($params) 58 { 59 $this->additionalParams = $params; 60 } 61 /** 62 * Get the 5th mail() function parameter as a sprintf() string. 63 * @return string 64 */ 65 public function getAdditionalParams() 66 { 67 return $this->additionalParams; 68 } 69 /** 70 * Set the operating system string (changes behaviour with LE) 71 * @param string The operating system 72 */ 73 public function setOS($os) 74 { 75 $this->OS = $os; 76 } 77 /** 78 * Get the operating system string 79 * @return string 80 */ 81 public function getOS() 82 { 83 return $this->OS; 84 } 85 /** 86 * Check if this is windows or not 87 * @return boolean 88 */ 89 public function isWindows() 90 { 91 return (substr($this->getOS(), 0, 3) == "WIN"); 92 } 93 /** 94 * Swift's BeforeSendEvent listener. 95 * Invoked just before Swift sends a message 96 * @param Swift_Events_SendEvent The event information 97 */ 98 public function beforeSendPerformed(Swift_Events_SendEvent $e) 99 { 100 $message = $e->getMessage(); 101 $message->uncacheAll(); 102 $this->oldLE = $message->getLE(); 103 if (!$this->isWindows() && $this->oldLE != "\n") $message->setLE("\n"); 104 } 105 /** 106 * Swift's SendEvent listener. 107 * Invoked when Swift sends a message 108 * @param Swift_Events_SendEvent The event information 109 * @throws Swift_ConnectionException If mail() returns false 110 */ 111 public function sendPerformed(Swift_Events_SendEvent $e) 112 { 113 $message = $e->getMessage(); 114 $recipients = $e->getRecipients(); 115 116 $to = array(); 117 foreach ($recipients->getTo() as $addr) 118 { 119 if ($this->isWindows()) $to[] = substr($addr->build(true), 1, -1); 120 else $to[] = $addr->build(); 121 } 122 $to = implode(", ", $to); 123 124 $bcc_orig = $message->headers->has("Bcc") ? $message->headers->get("Bcc") : null; 125 $subject_orig = $message->headers->has("Subject") ? $message->headers->get("Subject") : null; 126 $to_orig = $message->headers->has("To") ? $message->headers->get("To") : null; 127 128 $bcc = array(); 129 foreach ($recipients->getBcc() as $addr) $bcc[] = $addr->build(); 130 if (!empty($bcc)) $message->headers->set("Bcc", $bcc); 131 $bcc = null; 132 133 $body_data = $message->buildData(); 134 $message_body = $body_data->readFull(); 135 136 $subject_enc = $message->headers->has("Subject") ? $message->headers->getEncoded("Subject") : ""; 137 138 $message->headers->set("To", null); 139 $message->headers->set("Subject", null); 140 141 $sender = $e->getSender(); 142 $this->returnPath = $sender->build(); 143 if ($message->headers->has("Return-Path")) $this->returnPath = $message->headers->get("Return-Path"); 144 if (preg_match("~<([^>]+)>[^>]*\$~", $this->returnPath, $matches)) $this->returnPath = $matches[1]; 145 146 $this->doMail($to, $subject_enc, $message_body, $message->headers, sprintf($this->getAdditionalParams(), $this->returnPath)); 147 $message->setLE($this->oldLE); 148 $message->headers->set("To", $to_orig); 149 $message->headers->set("Subject", $subject_orig); 150 $message->headers->set("Bcc", $bcc_orig); 151 } 152 153 public function doMail($to, $subject, $message, $headers, $params) 154 { 155 $original_from = @ini_get("sendmail_from"); 156 @ini_set("sendmail_from", $this->returnPath); 157 158 $headers = $headers->build(); 159 160 if (!ini_get("safe_mode")) $success = mail($to, $subject, $message, $headers, $params); 161 else $success = mail($to, $subject, $message, $headers); 162 163 if (!$success) 164 { 165 @ini_set("sendmail_from", $original_from); 166 throw new Swift_ConnectionException("Sending failed using mail() as PHP's default mail() function returned boolean FALSE."); 167 } 168 @ini_set("sendmail_from", $original_from); 169 } 170} 171