1<?php 2 3/* 4 * This file is part of SwiftMailer. 5 * (c) 2004-2009 Chris Corbyn 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11//@require 'Swift/Transport.php'; 12//@require 'Swift/Transport/MailInvoker.php'; 13//@require 'Swift/Mime/Message.php'; 14//@require 'Swift/Events/EventListener.php'; 15 16/** 17 * Sends Messages using the mail() function. 18 * 19 * It is advised that users do not use this transport if at all possible 20 * since a number of plugin features cannot be used in conjunction with this 21 * transport due to the internal interface in PHP itself. 22 * 23 * The level of error reporting with this transport is incredibly weak, again 24 * due to limitations of PHP's internal mail() function. You'll get an 25 * all-or-nothing result from sending. 26 * 27 * @package Swift 28 * @subpackage Transport 29 * @author Chris Corbyn 30 */ 31class Swift_Transport_MailTransport implements Swift_Transport 32{ 33 34 /** Addtional parameters to pass to mail() */ 35 private $_extraParams = '-f%s'; 36 37 /** The event dispatcher from the plugin API */ 38 private $_eventDispatcher; 39 40 /** An invoker that calls the mail() function */ 41 private $_invoker; 42 43 /** 44 * Create a new MailTransport with the $log. 45 * @param Swift_Transport_Log $log 46 */ 47 public function __construct(Swift_Transport_MailInvoker $invoker, 48 Swift_Events_EventDispatcher $eventDispatcher) 49 { 50 $this->_invoker = $invoker; 51 $this->_eventDispatcher = $eventDispatcher; 52 } 53 54 /** 55 * Not used. 56 */ 57 public function isStarted() 58 { 59 return false; 60 } 61 62 /** 63 * Not used. 64 */ 65 public function start() 66 { 67 } 68 69 /** 70 * Not used. 71 */ 72 public function stop() 73 { 74 } 75 76 /** 77 * Set the additional parameters used on the mail() function. 78 * 79 * This string is formatted for sprintf() where %s is the sender address. 80 * 81 * @param string $params 82 */ 83 public function setExtraParams($params) 84 { 85 $this->_extraParams = $params; 86 return $this; 87 } 88 89 /** 90 * Get the additional parameters used on the mail() function. 91 * 92 * This string is formatted for sprintf() where %s is the sender address. 93 * 94 * @return string 95 */ 96 public function getExtraParams() 97 { 98 return $this->_extraParams; 99 } 100 101 /** 102 * Send the given Message. 103 * 104 * Recipient/sender data will be retreived from the Message API. 105 * The return value is the number of recipients who were accepted for delivery. 106 * 107 * @param Swift_Mime_Message $message 108 * @param string[] &$failedRecipients to collect failures by-reference 109 * @return int 110 */ 111 public function send(Swift_Mime_Message $message, &$failedRecipients = null) 112 { 113 $failedRecipients = (array) $failedRecipients; 114 115 if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) 116 { 117 $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); 118 if ($evt->bubbleCancelled()) 119 { 120 return 0; 121 } 122 } 123 124 $count = ( 125 count((array) $message->getTo()) 126 + count((array) $message->getCc()) 127 + count((array) $message->getBcc()) 128 ); 129 130 $toHeader = $message->getHeaders()->get('To'); 131 $subjectHeader = $message->getHeaders()->get('Subject'); 132 133 $to = $toHeader->getFieldBody(); 134 $subject = $subjectHeader->getFieldBody(); 135 136 $reversePath = $this->_getReversePath($message); 137 138 //Remove headers that would otherwise be duplicated 139 $message->getHeaders()->remove('To'); 140 $message->getHeaders()->remove('Subject'); 141 142 $messageStr = $message->toString(); 143 144 $message->getHeaders()->set($toHeader); 145 $message->getHeaders()->set($subjectHeader); 146 147 //Separate headers from body 148 if (false !== $endHeaders = strpos($messageStr, "\r\n\r\n")) 149 { 150 $headers = substr($messageStr, 0, $endHeaders) . "\r\n"; //Keep last EOL 151 $body = substr($messageStr, $endHeaders + 4); 152 } 153 else 154 { 155 $headers = $messageStr . "\r\n"; 156 $body = ''; 157 } 158 159 unset($messageStr); 160 161 if ("\r\n" != PHP_EOL) //Non-windows (not using SMTP) 162 { 163 $headers = str_replace("\r\n", PHP_EOL, $headers); 164 $body = str_replace("\r\n", PHP_EOL, $body); 165 } 166 else //Windows, using SMTP 167 { 168 $headers = str_replace("\r\n.", "\r\n..", $headers); 169 $body = str_replace("\r\n.", "\r\n..", $body); 170 } 171 172 if ($this->_invoker->mail($to, $subject, $body, $headers, 173 sprintf($this->_extraParams, $reversePath))) 174 { 175 if ($evt) 176 { 177 $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); 178 $evt->setFailedRecipients($failedRecipients); 179 $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); 180 } 181 } 182 else 183 { 184 $failedRecipients = array_merge( 185 $failedRecipients, 186 array_keys((array) $message->getTo()), 187 array_keys((array) $message->getCc()), 188 array_keys((array) $message->getBcc()) 189 ); 190 191 if ($evt) 192 { 193 $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED); 194 $evt->setFailedRecipients($failedRecipients); 195 $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); 196 } 197 198 $message->generateId(); 199 200 $count = 0; 201 } 202 203 return $count; 204 } 205 206 /** 207 * Register a plugin. 208 * 209 * @param Swift_Events_EventListener $plugin 210 */ 211 public function registerPlugin(Swift_Events_EventListener $plugin) 212 { 213 $this->_eventDispatcher->bindEventListener($plugin); 214 } 215 216 // -- Private methods 217 218 /** Determine the best-use reverse path for this message */ 219 private function _getReversePath(Swift_Mime_Message $message) 220 { 221 $return = $message->getReturnPath(); 222 $sender = $message->getSender(); 223 $from = $message->getFrom(); 224 $path = null; 225 if (!empty($return)) 226 { 227 $path = $return; 228 } 229 elseif (!empty($sender)) 230 { 231 $keys = array_keys($sender); 232 $path = array_shift($keys); 233 } 234 elseif (!empty($from)) 235 { 236 $keys = array_keys($from); 237 $path = array_shift($keys); 238 } 239 return $path; 240 } 241 242} 243