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/** 12 * The Message class for building emails. 13 * 14 * @author Chris Corbyn 15 */ 16class Swift_Message extends Swift_Mime_SimpleMessage 17{ 18 /** 19 * @var Swift_Signers_HeaderSigner[] 20 */ 21 private $headerSigners = array(); 22 23 /** 24 * @var Swift_Signers_BodySigner[] 25 */ 26 private $bodySigners = array(); 27 28 /** 29 * @var array 30 */ 31 private $savedMessage = array(); 32 33 /** 34 * Create a new Message. 35 * 36 * Details may be optionally passed into the constructor. 37 * 38 * @param string $subject 39 * @param string $body 40 * @param string $contentType 41 * @param string $charset 42 */ 43 public function __construct($subject = null, $body = null, $contentType = null, $charset = null) 44 { 45 call_user_func_array( 46 array($this, 'Swift_Mime_SimpleMessage::__construct'), 47 Swift_DependencyContainer::getInstance() 48 ->createDependenciesFor('mime.message') 49 ); 50 51 if (!isset($charset)) { 52 $charset = Swift_DependencyContainer::getInstance() 53 ->lookup('properties.charset'); 54 } 55 $this->setSubject($subject); 56 $this->setBody($body); 57 $this->setCharset($charset); 58 if ($contentType) { 59 $this->setContentType($contentType); 60 } 61 } 62 63 /** 64 * Create a new Message. 65 * 66 * @param string $subject 67 * @param string $body 68 * @param string $contentType 69 * @param string $charset 70 * 71 * @return $this 72 */ 73 public static function newInstance($subject = null, $body = null, $contentType = null, $charset = null) 74 { 75 return new self($subject, $body, $contentType, $charset); 76 } 77 78 /** 79 * Add a MimePart to this Message. 80 * 81 * @param string|Swift_OutputByteStream $body 82 * @param string $contentType 83 * @param string $charset 84 * 85 * @return $this 86 */ 87 public function addPart($body, $contentType = null, $charset = null) 88 { 89 return $this->attach(Swift_MimePart::newInstance($body, $contentType, $charset)->setEncoder($this->getEncoder())); 90 } 91 92 /** 93 * Detach a signature handler from a message. 94 * 95 * @param Swift_Signer $signer 96 * 97 * @return $this 98 */ 99 public function attachSigner(Swift_Signer $signer) 100 { 101 if ($signer instanceof Swift_Signers_HeaderSigner) { 102 $this->headerSigners[] = $signer; 103 } elseif ($signer instanceof Swift_Signers_BodySigner) { 104 $this->bodySigners[] = $signer; 105 } 106 107 return $this; 108 } 109 110 /** 111 * Attach a new signature handler to the message. 112 * 113 * @param Swift_Signer $signer 114 * 115 * @return $this 116 */ 117 public function detachSigner(Swift_Signer $signer) 118 { 119 if ($signer instanceof Swift_Signers_HeaderSigner) { 120 foreach ($this->headerSigners as $k => $headerSigner) { 121 if ($headerSigner === $signer) { 122 unset($this->headerSigners[$k]); 123 124 return $this; 125 } 126 } 127 } elseif ($signer instanceof Swift_Signers_BodySigner) { 128 foreach ($this->bodySigners as $k => $bodySigner) { 129 if ($bodySigner === $signer) { 130 unset($this->bodySigners[$k]); 131 132 return $this; 133 } 134 } 135 } 136 137 return $this; 138 } 139 140 /** 141 * Get this message as a complete string. 142 * 143 * @return string 144 */ 145 public function toString() 146 { 147 if (empty($this->headerSigners) && empty($this->bodySigners)) { 148 return parent::toString(); 149 } 150 151 $this->saveMessage(); 152 153 $this->doSign(); 154 155 $string = parent::toString(); 156 157 $this->restoreMessage(); 158 159 return $string; 160 } 161 162 /** 163 * Write this message to a {@link Swift_InputByteStream}. 164 * 165 * @param Swift_InputByteStream $is 166 */ 167 public function toByteStream(Swift_InputByteStream $is) 168 { 169 if (empty($this->headerSigners) && empty($this->bodySigners)) { 170 parent::toByteStream($is); 171 172 return; 173 } 174 175 $this->saveMessage(); 176 177 $this->doSign(); 178 179 parent::toByteStream($is); 180 181 $this->restoreMessage(); 182 } 183 184 public function __wakeup() 185 { 186 Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message'); 187 } 188 189 /** 190 * loops through signers and apply the signatures. 191 */ 192 protected function doSign() 193 { 194 foreach ($this->bodySigners as $signer) { 195 $altered = $signer->getAlteredHeaders(); 196 $this->saveHeaders($altered); 197 $signer->signMessage($this); 198 } 199 200 foreach ($this->headerSigners as $signer) { 201 $altered = $signer->getAlteredHeaders(); 202 $this->saveHeaders($altered); 203 $signer->reset(); 204 205 $signer->setHeaders($this->getHeaders()); 206 207 $signer->startBody(); 208 $this->_bodyToByteStream($signer); 209 $signer->endBody(); 210 211 $signer->addSignature($this->getHeaders()); 212 } 213 } 214 215 /** 216 * save the message before any signature is applied. 217 */ 218 protected function saveMessage() 219 { 220 $this->savedMessage = array('headers' => array()); 221 $this->savedMessage['body'] = $this->getBody(); 222 $this->savedMessage['children'] = $this->getChildren(); 223 if (count($this->savedMessage['children']) > 0 && $this->getBody() != '') { 224 $this->setChildren(array_merge(array($this->_becomeMimePart()), $this->savedMessage['children'])); 225 $this->setBody(''); 226 } 227 } 228 229 /** 230 * save the original headers. 231 * 232 * @param array $altered 233 */ 234 protected function saveHeaders(array $altered) 235 { 236 foreach ($altered as $head) { 237 $lc = strtolower($head); 238 239 if (!isset($this->savedMessage['headers'][$lc])) { 240 $this->savedMessage['headers'][$lc] = $this->getHeaders()->getAll($head); 241 } 242 } 243 } 244 245 /** 246 * Remove or restore altered headers. 247 */ 248 protected function restoreHeaders() 249 { 250 foreach ($this->savedMessage['headers'] as $name => $savedValue) { 251 $headers = $this->getHeaders()->getAll($name); 252 253 foreach ($headers as $key => $value) { 254 if (!isset($savedValue[$key])) { 255 $this->getHeaders()->remove($name, $key); 256 } 257 } 258 } 259 } 260 261 /** 262 * Restore message body. 263 */ 264 protected function restoreMessage() 265 { 266 $this->setBody($this->savedMessage['body']); 267 $this->setChildren($this->savedMessage['children']); 268 269 $this->restoreHeaders(); 270 $this->savedMessage = array(); 271 } 272 273 /** 274 * Clone Message Signers. 275 * 276 * @see Swift_Mime_SimpleMimeEntity::__clone() 277 */ 278 public function __clone() 279 { 280 parent::__clone(); 281 foreach ($this->bodySigners as $key => $bodySigner) { 282 $this->bodySigners[$key] = clone $bodySigner; 283 } 284 285 foreach ($this->headerSigners as $key => $headerSigner) { 286 $this->headerSigners[$key] = clone $headerSigner; 287 } 288 } 289} 290