1<?php 2 3/** 4 * Swift Mailer Message Component 5 * Composes MIME 1.0 messages meeting various RFC standards 6 * Deals with attachments, embedded images, multipart bodies, forwarded messages... 7 * Please read the LICENSE file 8 * @copyright Chris Corbyn <chris@w3style.co.uk> 9 * @author Chris Corbyn <chris@w3style.co.uk> 10 * @package Swift_Message 11 * @license GNU Lesser General Public License 12 */ 13 14require_once dirname(__FILE__) . "/ClassLoader.php"; 15Swift_ClassLoader::load("Swift_Address"); 16Swift_ClassLoader::load("Swift_Message_Mime"); 17Swift_ClassLoader::load("Swift_Message_Image"); 18Swift_ClassLoader::load("Swift_Message_Part"); 19 20 21/** 22 * Swift Message class 23 * @package Swift_Message 24 * @author Chris Corbyn <chris@w3style.co.uk> 25 */ 26class Swift_Message extends Swift_Message_Mime 27{ 28 /** 29 * Constant from a high priority message (pretty meaningless) 30 */ 31 const PRIORITY_HIGH = 1; 32 /** 33 * Constant for a low priority message 34 */ 35 const PRIORITY_LOW = 5; 36 /** 37 * Constant for a normal priority message 38 */ 39 const PRIORITY_NORMAL = 3; 40 /** 41 * The MIME warning for client not supporting multipart content 42 * @var string 43 */ 44 protected $mimeWarning = null; 45 /** 46 * The version of the library (Swift) if known. 47 * @var string 48 */ 49 protected $libVersion = ""; 50 /** 51 * A container for references to other objects. 52 * This is used in some very complex logic when sub-parts get shifted around. 53 * @var array 54 */ 55 protected $references = array( 56 "parent" => array("alternative" => null, "mixed" => null, "related" => null), 57 "alternative" => array(), 58 "mixed" => array(), 59 "related" => array() 60 ); 61 62 /** 63 * Ctor. 64 * @param string Message subject 65 * @param string Body 66 * @param string Content-type 67 * @param string Encoding 68 * @param string Charset 69 */ 70 public function __construct($subject="", $body=null, $type="text/plain", $encoding=null, $charset=null) 71 { 72 parent::__construct(); 73 if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) 74 { 75 date_default_timezone_set(@date_default_timezone_get()); 76 } 77 $this->setReturnPath(null); 78 $this->setTo(""); 79 $this->setFrom(""); 80 $this->setCc(null); 81 $this->setBcc(null); 82 $this->setReplyTo(null); 83 $this->setSubject($subject); 84 $this->setDate(time()); 85 if (defined("Swift::VERSION")) 86 { 87 $this->libVersion = Swift::VERSION; 88 $this->headers->set("X-LibVersion", $this->libVersion); 89 } 90 $this->headers->set("MIME-Version", "1.0"); 91 $this->setContentType($type); 92 $this->setCharset($charset); 93 $this->setFlowed(true); 94 $this->setEncoding($encoding); 95 96 foreach (array_keys($this->references["parent"]) as $key) 97 { 98 $this->setReference("parent", $key, $this); 99 } 100 101 $this->setMimeWarning( 102 "This is a message in multipart MIME format. Your mail client should not be displaying this. " . 103 "Consider upgrading your mail client to view this message correctly." 104 ); 105 106 if ($body !== null) 107 { 108 $this->setData($body); 109 if ($charset === null) 110 { 111 Swift_ClassLoader::load("Swift_Message_Encoder"); 112 if (Swift_Message_Encoder::instance()->isUTF8($body)) $this->setCharset("utf-8"); 113 else $this->setCharset("iso-8859-1"); 114 } 115 } 116 } 117 /** 118 * Sets a reference so when nodes are nested, operations can be redirected. 119 * This really should be refactored to use just one array rather than dynamic variables. 120 * @param string Key 1 121 * @param string Key 2 122 * @param Object Reference 123 */ 124 protected function setReference($where, $key, $ref) 125 { 126 if ($ref === $this) $this->references[$where][$key] = false; 127 else $this->references[$where][$key] = $ref; 128 } 129 /** 130 * Get a reference to an object (for complex reasons). 131 * @param string Key 1 132 * @param string Key 2 133 * @return Object 134 */ 135 protected function getReference($where, $key) 136 { 137 if (!$this->references[$where][$key]) return $this; 138 else return $this->references[$where][$key]; 139 } 140 /** 141 * Get the level in the MIME hierarchy at which this section should appear. 142 * @return string 143 */ 144 public function getLevel() 145 { 146 return Swift_Message_Mime::LEVEL_TOP; 147 } 148 /** 149 * Set the message id literally. 150 * Unless you know what you are doing you should be using generateId() rather than this method, 151 * otherwise you may break compliancy with RFC 2822. 152 * @param string The message ID string. 153 */ 154 public function setId($id) 155 { 156 $this->headers->set("Message-ID", $id); 157 } 158 /** 159 * Create a RFC 2822 compliant message id, optionally based upon $idstring. 160 * The message ID includes information about the current time, the server and some random characters. 161 * @param string An optional string the base the ID on 162 * @return string The generated message ID, including the <> quotes. 163 * @author Cristian Rodriguez <judas.iscariote@flyspray.org> 164 */ 165 public function generateId($idstring=null) 166 { 167 $midparams = array( 168 "utctime" => gmstrftime("%Y%m%d%H%M%S"), 169 "pid" => getmypid(), 170 "randint" => mt_rand(), 171 "customstr" => (preg_match("/^(?<!\\.)[a-z0-9\\.]+(?!\\.)\$/iD", $idstring) ? $idstring : "swift") , 172 "hostname" => (isset($_SERVER["SERVER_NAME"]) ? $_SERVER["SERVER_NAME"] : php_uname("n")), 173 ); 174 $this->setId(vsprintf("<%s.%d.%d.%s@%s>", $midparams)); 175 return $this->getId(); 176 } 177 /** 178 * Get the generated message ID for this message, including the <> quotes. 179 * If generated automatically, or using generateId() this method returns a RFC2822 compliant Message-ID. 180 * @return string 181 * @author Cristian Rodriguez <judas.iscariote@flyspray.org> 182 */ 183 public function getId() 184 { 185 return $this->headers->has("Message-ID") ? $this->headers->get("Message-ID") : null; 186 } 187 /** 188 * Set the address in the Return-Path: header 189 * @param string The bounce-detect address 190 */ 191 public function setReturnPath($address) 192 { 193 if ($address instanceof Swift_Address) $address = $address->build(true); 194 $this->headers->set("Return-Path", $address); 195 } 196 /** 197 * Return the address used in the Return-Path: header 198 * @return string 199 * @param boolean Return the address for SMTP command 200 */ 201 public function getReturnPath($smtp=false) 202 { 203 if ($this->headers->has("Return-Path")) 204 { 205 if (!$smtp) return $this->headers->get("Return-Path"); 206 else 207 { 208 $path = $this->headers->get("Return-Path"); 209 if (strpos($path, ">") > strpos($path, "<")) return substr($path, ($start = strpos($path, "<")), ($start + strrpos($path, ">") + 1)); 210 else return "<" . $path . ">"; 211 } 212 } 213 } 214 /** 215 * Set the address in the From: header 216 * @param string The address to set as From 217 */ 218 public function setFrom($from) 219 { 220 if ($from instanceof Swift_Address) $from = $from->build(); 221 $this->headers->set("From", $from); 222 } 223 /** 224 * Get the address used in the From: header 225 * @return string 226 */ 227 public function getFrom() 228 { 229 if ($this->headers->has("From")) return $this->headers->get("From"); 230 } 231 /** 232 * Set the list of recipients in the To: header 233 * @param mixed An array or a string 234 */ 235 public function setTo($to) 236 { 237 if ($to) 238 { 239 if (!is_array($to)) $to = array($to); 240 foreach ($to as $key => $value) 241 { 242 if ($value instanceof Swift_Address) $to[$key] = $value->build(); 243 } 244 } 245 $this->headers->set("To", $to); 246 } 247 /** 248 * Return the list of recipients in the To: header 249 * @return array 250 */ 251 public function getTo() 252 { 253 if ($this->headers->has("To")) 254 { 255 $to = $this->headers->get("To"); 256 if ($to == "") return array(); 257 else return (array) $to; 258 } 259 } 260 /** 261 * Set the list of recipients in the Reply-To: header 262 * @param mixed An array or a string 263 */ 264 public function setReplyTo($replyto) 265 { 266 if ($replyto) 267 { 268 if (!is_array($replyto)) $replyto = array($replyto); 269 foreach ($replyto as $key => $value) 270 { 271 if ($value instanceof Swift_Address) $replyto[$key] = $value->build(); 272 } 273 } 274 $this->headers->set("Reply-To", $replyto); 275 } 276 /** 277 * Return the list of recipients in the Reply-To: header 278 * @return array 279 */ 280 public function getReplyTo() 281 { 282 if ($this->headers->has("Reply-To")) 283 { 284 $reply_to = $this->headers->get("Reply-To"); 285 if ($reply_to == "") return array(); 286 else return (array) $reply_to; 287 } 288 } 289 /** 290 * Set the list of recipients in the Cc: header 291 * @param mixed An array or a string 292 */ 293 public function setCc($cc) 294 { 295 if ($cc) 296 { 297 if (!is_array($cc)) $cc = array($cc); 298 foreach ($cc as $key => $value) 299 { 300 if ($value instanceof Swift_Address) $cc[$key] = $value->build(); 301 } 302 } 303 $this->headers->set("Cc", $cc); 304 } 305 /** 306 * Return the list of recipients in the Cc: header 307 * @return array 308 */ 309 public function getCc() 310 { 311 if ($this->headers->has("Cc")) 312 { 313 $cc = $this->headers->get("Cc"); 314 if ($cc == "") return array(); 315 else return (array) $cc; 316 } 317 } 318 /** 319 * Set the list of recipients in the Bcc: header 320 * @param mixed An array or a string 321 */ 322 public function setBcc($bcc) 323 { 324 if ($bcc) 325 { 326 if (!is_array($bcc)) $bcc = array($bcc); 327 foreach ($bcc as $key => $value) 328 { 329 if ($value instanceof Swift_Address) $bcc[$key] = $value->build(); 330 } 331 } 332 $this->headers->set("Bcc", $bcc); 333 } 334 /** 335 * Return the list of recipients in the Bcc: header 336 * @return array 337 */ 338 public function getBcc() 339 { 340 if ($this->headers->has("Bcc")) 341 { 342 $bcc = $this->headers->get("Bcc"); 343 if ($bcc == "") return array(); 344 else return (array) $bcc; 345 } 346 } 347 /** 348 * Set the subject in the headers 349 * @param string The subject of the email 350 */ 351 public function setSubject($subject) 352 { 353 $this->headers->set("Subject", $subject); 354 } 355 /** 356 * Get the current subject used in the headers 357 * @return string 358 */ 359 public function getSubject() 360 { 361 return $this->headers->get("Subject"); 362 } 363 /** 364 * Set the date in the headers in RFC 2822 format 365 * @param int The time as a UNIX timestamp 366 */ 367 public function setDate($date) 368 { 369 $this->headers->set("Date", date("r", $date)); 370 } 371 /** 372 * Get the date as it looks in the headers 373 * @return string 374 */ 375 public function getDate() 376 { 377 return strtotime($this->headers->get("Date")); 378 } 379 /** 380 * Set the charset of the document 381 * @param string The charset used 382 */ 383 public function setCharset($charset) 384 { 385 $this->headers->setAttribute("Content-Type", "charset", $charset); 386 if (($this->getEncoding() == "7bit") && (strtolower($charset) == "utf-8" || strtolower($charset) == "utf8")) $this->setEncoding("8bit"); 387 } 388 /** 389 * Get the charset used in the document 390 * Returns null if none is set 391 * @return string 392 */ 393 public function getCharset() 394 { 395 if ($this->headers->hasAttribute("Content-Type", "charset")) 396 { 397 return $this->headers->getAttribute("Content-Type", "charset"); 398 } 399 else 400 { 401 return null; 402 } 403 } 404 /** 405 * Set the "format" attribute to flowed 406 * @param boolean On or Off 407 */ 408 public function setFlowed($flowed=true) 409 { 410 $value = null; 411 if ($flowed) $value = "flowed"; 412 $this->headers->setAttribute("Content-Type", "format", $value); 413 } 414 /** 415 * Check if the message format is set as flowed 416 * @return boolean 417 */ 418 public function isFlowed() 419 { 420 if ($this->headers->hasAttribute("Content-Type", "format") 421 && $this->headers->getAttribute("Content-Type", "format") == "flowed") 422 { 423 return true; 424 } 425 else return false; 426 } 427 /** 428 * Set the message prioirty in the mail client (don't rely on this) 429 * @param int The priority as a value between 1 (high) and 5 (low) 430 */ 431 public function setPriority($priority) 432 { 433 $priority = (int) $priority; 434 if ($priority > self::PRIORITY_LOW) $priority = self::PRIORITY_LOW; 435 if ($priority < self::PRIORITY_HIGH) $priority = self::PRIORITY_HIGH; 436 $label = array(1 => "High", 2 => "High", 3 => "Normal", 4 => "Low", 5 => "Low"); 437 $this->headers->set("X-Priority", $priority); 438 $this->headers->set("X-MSMail-Priority", $label[$priority]); 439 $this->headers->set("X-MimeOLE", "Produced by SwiftMailer " . $this->libVersion); 440 } 441 /** 442 * Request that the client send back a read-receipt (don't rely on this!) 443 * @param string Request address 444 */ 445 public function requestReadReceipt($request) 446 { 447 if ($request instanceof Swift_Address) $request = $request->build(); 448 if (!$request) 449 { 450 $this->headers->set("Disposition-Notification-To", null); 451 $this->headers->set("X-Confirm-Reading-To", null); 452 $this->headers->set("Return-Receipt-To", null); 453 } 454 else 455 { 456 $this->headers->set("Disposition-Notification-To", $request); 457 $this->headers->set("X-Confirm-Reading-To", $request); 458 $this->headers->set("Return-Receipt-To", $request); 459 } 460 } 461 /** 462 * Check if a read receipt has been requested for this message 463 * @return boolean 464 */ 465 public function wantsReadReceipt() 466 { 467 return $this->headers->has("Disposition-Notification-To"); 468 } 469 /** 470 * Get the current message priority 471 * Returns NULL if none set 472 * @return int 473 */ 474 public function getPriority() 475 { 476 if ($this->headers->has("X-Priority")) return $this->headers->get("X-Priority"); 477 else return null; 478 } 479 /** 480 * Alias for setData() 481 * @param mixed Body 482 */ 483 public function setBody($body) 484 { 485 $this->setData($body); 486 } 487 /** 488 * Alias for getData() 489 * @return mixed The document body 490 */ 491 public function getBody() 492 { 493 return $this->getData(); 494 } 495 /** 496 * Set the MIME warning message which is displayed to old clients 497 * @var string The full warning message (in 7bit ascii) 498 */ 499 public function setMimeWarning($text) 500 { 501 $this->mimeWarning = (string) $text; 502 } 503 /** 504 * Get the MIME warning which is displayed to old clients 505 * @return string 506 */ 507 public function getMimeWarning() 508 { 509 return $this->mimeWarning; 510 } 511 /** 512 * Attach a mime part or an attachment of some sort 513 * Any descendant of Swift_Message_Mime can be added safely (including other Swift_Message objects for mail forwarding!!) 514 * @param Swift_Message_Mime The document to attach 515 * @param string An identifier to use (one is returned otherwise) 516 * @return string The identifier for the part 517 */ 518 public function attach(Swift_Message_Mime $child, $id=null) 519 { 520 try { 521 switch ($child->getLevel()) 522 { 523 case Swift_Message_Mime::LEVEL_ALTERNATIVE: 524 $sign = (strtolower($child->getContentType()) == "text/plain") ? -1 : 1; 525 $id = $this->getReference("parent", "alternative")->addChild($child, $id, $sign); 526 $this->setReference("alternative", $id, $child); 527 break; 528 case Swift_Message_Mime::LEVEL_RELATED: 529 $id = "cid:" . $child->getContentId(); 530 $id = $this->getReference("parent", "related")->addChild($child, $id, 1); 531 $this->setReference("related", $id, $child); 532 break; 533 case Swift_Message_Mime::LEVEL_MIXED: default: 534 $id = $this->getReference("parent", "mixed")->addChild($child, $id, 1); 535 $this->setReference("mixed", $id, $child); 536 break; 537 } 538 $this->postAttachFixStructure(); 539 $this->fixContentType(); 540 return $id; 541 } catch (Swift_Message_MimeException $e) { 542 throw new Swift_Message_MimeException("Something went wrong whilst trying to move some MIME parts during an attach(). " . 543 "The MIME component threw an exception:<br />" . $e->getMessage()); 544 } 545 } 546 /** 547 * Remove a nested MIME part 548 * @param string The ID of the attached part 549 * @throws Swift_Message_MimeException If no such part exists 550 */ 551 public function detach($id) 552 { 553 try { 554 switch (true) 555 { 556 case array_key_exists($id, $this->references["alternative"]): 557 $this->getReference("parent", "alternative")->removeChild($id); 558 unset($this->references["alternative"][$id]); 559 break; 560 case array_key_exists($id, $this->references["related"]): 561 $this->getReference("parent", "related")->removeChild($id); 562 unset($this->references["related"][$id]); 563 break; 564 case array_key_exists($id, $this->references["mixed"]): 565 $this->getReference("parent", "mixed")->removeChild($id); 566 unset($this->references["mixed"][$id]); 567 break; 568 default: 569 throw new Swift_Message_MimeException("Unable to detach part identified by ID '" . $id . "' since it's not registered."); 570 break; 571 } 572 $this->postDetachFixStructure(); 573 $this->fixContentType(); 574 } catch (Swift_Message_MimeException $e) { 575 throw new Swift_Message_MimeException("Something went wrong whilst trying to move some MIME parts during a detach(). " . 576 "The MIME component threw an exception:<br />" . $e->getMessage()); 577 } 578 } 579 /** 580 * Sets the correct content type header by looking at what types of data we have set 581 */ 582 protected function fixContentType() 583 { 584 if (!empty($this->references["mixed"])) $this->setContentType("multipart/mixed"); 585 elseif (!empty($this->references["related"])) $this->setContentType("multipart/related"); 586 elseif (!empty($this->references["alternative"])) $this->setContentType("multipart/alternative"); 587 } 588 /** 589 * Move a branch of the tree, containing all it's MIME parts onto another branch 590 * @param string The content type on the branch itself 591 * @param string The content type which may exist in the branch's parent 592 * @param array The array containing all the nodes presently 593 * @param string The location of the branch now 594 * @param string The location of the branch after moving 595 * @param string The key to identify the branch by in it's new location 596 */ 597 protected function moveBranchIn($type, $nested_type, $from, $old_branch, $new_branch, $tag) 598 { 599 $new = new Swift_Message_Part(); 600 $new->setContentType($type); 601 $this->getReference("parent", $new_branch)->addChild($new, $tag, -1); 602 603 switch ($new_branch) 604 { 605 case "related": $this->setReference("related", $tag, $new);//relatedRefs[$tag] = $new; 606 break; 607 case "mixed": $this->setReference("mixed", $tag, $new);//mixedRefs[$tag] = $new; 608 break; 609 } 610 611 foreach ($from as $id => $ref) 612 { 613 if (!$ref) $ref = $this; 614 $sign = (strtolower($ref->getContentType()) == "text/plain" 615 || strtolower($ref->getContentType()) == $nested_type) ? -1 : 1; 616 switch ($new_branch) 617 { 618 case "related": $this->getReference("related", $tag)->addChild($ref, $id, $sign); 619 break; 620 case "mixed": $this->getReference("mixed", $tag)->addChild($ref, $id, $sign); 621 break; 622 } 623 $this->getReference("parent", $old_branch)->removeChild($id); 624 } 625 $this->setReference("parent", $old_branch, $new); //parentRefs[$old_branch] = $new; 626 } 627 /** 628 * Analyzes the mixing of MIME types in a mulitpart message an re-arranges if needed 629 * It looks complicated and long winded but the concept is pretty simple, even if putting it 630 * in code does me make want to cry! 631 */ 632 protected function postAttachFixStructure() 633 { 634 switch (true) 635 { 636 case (!empty($this->references["mixed"]) && !empty($this->references["related"]) && !empty($this->references["alternative"])): 637 if (!isset($this->references["related"]["_alternative"])) 638 { 639 $this->moveBranchIn( 640 "multipart/alternative", "multipart/alternative", $this->references["alternative"], "alternative", "related", "_alternative"); 641 } 642 if (!isset($this->references["mixed"]["_related"])) 643 { 644 $this->moveBranchIn( 645 "multipart/related", "multipart/alternative", $this->references["related"], "related", "mixed", "_related"); 646 } 647 break; 648 case (!empty($this->references["mixed"]) && !empty($this->references["related"])): 649 if (!isset($this->references["mixed"]["_related"])) 650 { 651 $this->moveBranchIn( 652 "multipart/related", "multipart/related", $this->references["related"], "related", "mixed", "_related"); 653 } 654 break; 655 case (!empty($this->references["mixed"]) && !empty($this->references["alternative"])): 656 if (!isset($this->references["mixed"]["_alternative"])) 657 { 658 $this->moveBranchIn( 659 "multipart/alternative", null, $this->references["alternative"], "alternative", "mixed", "_alternative"); 660 } 661 break; 662 case (!empty($this->references["related"]) && !empty($this->references["alternative"])): 663 if (!isset($this->references["related"]["_alternative"])) 664 { 665 $this->moveBranchIn( 666 "multipart/alternative", "multipart/alternative", $this->references["alternative"], "alternative", "related", "_alternative"); 667 } 668 break; 669 } 670 } 671 /** 672 * Move a branch further toward the top of the tree 673 * @param array The array containing MIME parts from the old branch 674 * @param string The name of the old branch 675 * @param string The name of the new branch 676 * @param string The key of the branch being moved 677 */ 678 protected function moveBranchOut($from, $old_branch, $new_branch, $tag) 679 { 680 foreach ($from as $id => $ref) 681 { 682 if (!$ref) $ref = $this; 683 $sign = (strtolower($ref->getContentType()) == "text/html" 684 || strtolower($ref->getContentType()) == "multipart/alternative") ? -1 : 1; 685 $this->getReference("parent", $new_branch)->addChild($ref, $id, $sign); 686 switch ($new_branch) 687 { 688 case "related": $this->getReference("related", $tag)->removeChild($id); 689 break; 690 case "mixed": $this->getReference("parent", $old_branch)->removeChild($id); 691 break; 692 } 693 } 694 $this->getReference("parent", $new_branch)->removeChild($tag); 695 $mixed = $this->getReference("parent", $new_branch);//parentRefs[$new_branch]; 696 $this->setReference("parent", $old_branch, $mixed);//parentRefs[$old_branch] = $mixed; 697 switch ($new_branch) 698 { 699 case "related": unset($this->references["related"][$tag]); 700 break; 701 case "mixed": unset($this->references["mixed"][$tag]); 702 break; 703 } 704 } 705 /** 706 * Analyzes the mixing of MIME types in a mulitpart message an re-arranges if needed 707 * It looks complicated and long winded but the concept is pretty simple, even if putting it 708 * in code does me make want to cry! 709 */ 710 protected function postDetachFixStructure() 711 { 712 switch (true) 713 { 714 case (!empty($this->references["mixed"]) && !empty($this->references["related"]) && !empty($this->references["alternative"])): 715 if (array_keys($this->references["related"]) == array("_alternative")) 716 { 717 $alt = $this->getReference("parent", "related")->getChild("_alternative"); 718 $this->getReference("parent", "mixed")->addChild($alt, "_alternative", -1); 719 $this->setReference("mixed", "_alternative", $alt);//mixedRefs["_alternative"] = $alt; 720 $this->getReference("parent", "related")->removeChild("_alternative"); 721 unset($this->references["related"]["_alternative"]); 722 $this->getReference("parent", "mixed")->removeChild("_related"); 723 unset($this->references["mixed"]["_related"]); 724 } 725 if (array_keys($this->references["mixed"]) == array("_related")) 726 { 727 $this->moveBranchOut($this->references["related"], "related", "mixed", "_related"); 728 } 729 break; 730 case (!empty($this->references["mixed"]) && !empty($this->references["related"])): 731 if (array_keys($this->references["mixed"]) == array("_related")) 732 { 733 $this->moveBranchOut($this->references["related"], "related", "mixed", "_related"); 734 } 735 if (isset($this->references["related"]["_alternative"])) 736 { 737 $this->detach("_alternative"); 738 } 739 break; 740 case (!empty($this->references["mixed"]) && !empty($this->references["alternative"])): 741 if (array_keys($this->references["mixed"]) == array("_alternative")) 742 { 743 $this->moveBranchOut($this->references["alternative"], "alternative", "mixed", "_alternative"); 744 } 745 break; 746 case (!empty($this->references["related"]) && !empty($this->references["alternative"])): 747 if (array_keys($this->references["related"]) == array("_alternative")) 748 { 749 $this->moveBranchOut($this->references["alternative"], "alternative", "related", "_alternative"); 750 } 751 break; 752 case (!empty($this->references["mixed"])): 753 if (isset($this->references["mixed"]["_related"])) $this->detach("_related"); 754 case (!empty($this->references["related"])): 755 if (isset($this->references["related"]["_alternative"]) || isset($this->references["mixed"]["_alternative"])) 756 $this->detach("_alternative"); 757 break; 758 } 759 } 760 /** 761 * Execute needed logic prior to compilation 762 */ 763 public function preBuild() 764 { 765 $data = $this->getData(); 766 if (!($enc = $this->getEncoding())) 767 { 768 $this->setEncoding("8bit"); 769 } 770 if ($this->getCharset() === null && !$this->numChildren()) 771 { 772 Swift_ClassLoader::load("Swift_Message_Encoder"); 773 if (is_string($data) && Swift_Message_Encoder::instance()->isUTF8($data)) 774 { 775 $this->setCharset("utf-8"); 776 } 777 elseif(is_string($data) && Swift_Message_Encoder::instance()->is7BitAscii($data)) 778 { 779 $this->setCharset("us-ascii"); 780 if (!$enc) $this->setEncoding("7bit"); 781 } 782 else $this->setCharset("iso-8859-1"); 783 } 784 elseif ($this->numChildren()) 785 { 786 if (!$this->getData()) 787 { 788 $this->setData($this->getMimeWarning()); 789 $this->setLineWrap(76); 790 } 791 792 if ($this->getCharset() !== null) $this->setCharset(null); 793 if ($this->isFlowed()) $this->setFlowed(false); 794 $this->setEncoding("7bit"); 795 } 796 } 797} 798