MailboxHeader.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <?php
  2. /*
  3. * This file is part of SwiftMailer.
  4. * (c) 2004-2009 Chris Corbyn
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * A Mailbox Address MIME Header for something like From or Sender.
  11. *
  12. * @author Chris Corbyn
  13. */
  14. class Swift_Mime_Headers_MailboxHeader extends Swift_Mime_Headers_AbstractHeader
  15. {
  16. /**
  17. * The mailboxes used in this Header.
  18. *
  19. * @var string[]
  20. */
  21. private $_mailboxes = array();
  22. /**
  23. * Creates a new MailboxHeader with $name.
  24. *
  25. * @param string $name of Header
  26. * @param Swift_Mime_HeaderEncoder $encoder
  27. * @param Swift_Mime_Grammar $grammar
  28. */
  29. public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Mime_Grammar $grammar)
  30. {
  31. $this->setFieldName($name);
  32. $this->setEncoder($encoder);
  33. parent::__construct($grammar);
  34. }
  35. /**
  36. * Get the type of Header that this instance represents.
  37. *
  38. * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
  39. * @see TYPE_DATE, TYPE_ID, TYPE_PATH
  40. *
  41. * @return int
  42. */
  43. public function getFieldType()
  44. {
  45. return self::TYPE_MAILBOX;
  46. }
  47. /**
  48. * Set the model for the field body.
  49. *
  50. * This method takes a string, or an array of addresses.
  51. *
  52. * @param mixed $model
  53. *
  54. * @throws Swift_RfcComplianceException
  55. */
  56. public function setFieldBodyModel($model)
  57. {
  58. $this->setNameAddresses($model);
  59. }
  60. /**
  61. * Get the model for the field body.
  62. *
  63. * This method returns an associative array like {@link getNameAddresses()}
  64. *
  65. * @return array
  66. *
  67. * @throws Swift_RfcComplianceException
  68. */
  69. public function getFieldBodyModel()
  70. {
  71. return $this->getNameAddresses();
  72. }
  73. /**
  74. * Set a list of mailboxes to be shown in this Header.
  75. *
  76. * The mailboxes can be a simple array of addresses, or an array of
  77. * key=>value pairs where (email => personalName).
  78. * Example:
  79. * <code>
  80. * <?php
  81. * //Sets two mailboxes in the Header, one with a personal name
  82. * $header->setNameAddresses(array(
  83. * 'chris@swiftmailer.org' => 'Chris Corbyn',
  84. * 'mark@swiftmailer.org' //No associated personal name
  85. * ));
  86. * ?>
  87. * </code>
  88. *
  89. * @see __construct()
  90. * @see setAddresses()
  91. * @see setValue()
  92. *
  93. * @param string|string[] $mailboxes
  94. *
  95. * @throws Swift_RfcComplianceException
  96. */
  97. public function setNameAddresses($mailboxes)
  98. {
  99. $this->_mailboxes = $this->normalizeMailboxes((array) $mailboxes);
  100. $this->setCachedValue(null); //Clear any cached value
  101. }
  102. /**
  103. * Get the full mailbox list of this Header as an array of valid RFC 2822 strings.
  104. *
  105. * Example:
  106. * <code>
  107. * <?php
  108. * $header = new Swift_Mime_Headers_MailboxHeader('From',
  109. * array('chris@swiftmailer.org' => 'Chris Corbyn',
  110. * 'mark@swiftmailer.org' => 'Mark Corbyn')
  111. * );
  112. * print_r($header->getNameAddressStrings());
  113. * // array (
  114. * // 0 => Chris Corbyn <chris@swiftmailer.org>,
  115. * // 1 => Mark Corbyn <mark@swiftmailer.org>
  116. * // )
  117. * ?>
  118. * </code>
  119. *
  120. * @see getNameAddresses()
  121. * @see toString()
  122. *
  123. * @return string[]
  124. *
  125. * @throws Swift_RfcComplianceException
  126. */
  127. public function getNameAddressStrings()
  128. {
  129. return $this->_createNameAddressStrings($this->getNameAddresses());
  130. }
  131. /**
  132. * Get all mailboxes in this Header as key=>value pairs.
  133. *
  134. * The key is the address and the value is the name (or null if none set).
  135. * Example:
  136. * <code>
  137. * <?php
  138. * $header = new Swift_Mime_Headers_MailboxHeader('From',
  139. * array('chris@swiftmailer.org' => 'Chris Corbyn',
  140. * 'mark@swiftmailer.org' => 'Mark Corbyn')
  141. * );
  142. * print_r($header->getNameAddresses());
  143. * // array (
  144. * // chris@swiftmailer.org => Chris Corbyn,
  145. * // mark@swiftmailer.org => Mark Corbyn
  146. * // )
  147. * ?>
  148. * </code>
  149. *
  150. * @see getAddresses()
  151. * @see getNameAddressStrings()
  152. *
  153. * @return string[]
  154. */
  155. public function getNameAddresses()
  156. {
  157. return $this->_mailboxes;
  158. }
  159. /**
  160. * Makes this Header represent a list of plain email addresses with no names.
  161. *
  162. * Example:
  163. * <code>
  164. * <?php
  165. * //Sets three email addresses as the Header data
  166. * $header->setAddresses(
  167. * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld')
  168. * );
  169. * ?>
  170. * </code>
  171. *
  172. * @see setNameAddresses()
  173. * @see setValue()
  174. *
  175. * @param string[] $addresses
  176. *
  177. * @throws Swift_RfcComplianceException
  178. */
  179. public function setAddresses($addresses)
  180. {
  181. $this->setNameAddresses(array_values((array) $addresses));
  182. }
  183. /**
  184. * Get all email addresses in this Header.
  185. *
  186. * @see getNameAddresses()
  187. *
  188. * @return string[]
  189. */
  190. public function getAddresses()
  191. {
  192. return array_keys($this->_mailboxes);
  193. }
  194. /**
  195. * Remove one or more addresses from this Header.
  196. *
  197. * @param string|string[] $addresses
  198. */
  199. public function removeAddresses($addresses)
  200. {
  201. $this->setCachedValue(null);
  202. foreach ((array) $addresses as $address) {
  203. unset($this->_mailboxes[$address]);
  204. }
  205. }
  206. /**
  207. * Get the string value of the body in this Header.
  208. *
  209. * This is not necessarily RFC 2822 compliant since folding white space will
  210. * not be added at this stage (see {@link toString()} for that).
  211. *
  212. * @see toString()
  213. *
  214. * @return string
  215. *
  216. * @throws Swift_RfcComplianceException
  217. */
  218. public function getFieldBody()
  219. {
  220. // Compute the string value of the header only if needed
  221. if (is_null($this->getCachedValue())) {
  222. $this->setCachedValue($this->createMailboxListString($this->_mailboxes));
  223. }
  224. return $this->getCachedValue();
  225. }
  226. // -- Points of extension
  227. /**
  228. * Normalizes a user-input list of mailboxes into consistent key=>value pairs.
  229. *
  230. * @param string[] $mailboxes
  231. *
  232. * @return string[]
  233. */
  234. protected function normalizeMailboxes(array $mailboxes)
  235. {
  236. $actualMailboxes = array();
  237. foreach ($mailboxes as $key => $value) {
  238. if (is_string($key)) { //key is email addr
  239. $address = $key;
  240. $name = $value;
  241. } else {
  242. $address = $value;
  243. $name = null;
  244. }
  245. $this->_assertValidAddress($address);
  246. $actualMailboxes[$address] = $name;
  247. }
  248. return $actualMailboxes;
  249. }
  250. /**
  251. * Produces a compliant, formatted display-name based on the string given.
  252. *
  253. * @param string $displayName as displayed
  254. * @param bool $shorten the first line to make remove for header name
  255. *
  256. * @return string
  257. */
  258. protected function createDisplayNameString($displayName, $shorten = false)
  259. {
  260. return $this->createPhrase($this, $displayName,
  261. $this->getCharset(), $this->getEncoder(), $shorten
  262. );
  263. }
  264. /**
  265. * Creates a string form of all the mailboxes in the passed array.
  266. *
  267. * @param string[] $mailboxes
  268. *
  269. * @return string
  270. *
  271. * @throws Swift_RfcComplianceException
  272. */
  273. protected function createMailboxListString(array $mailboxes)
  274. {
  275. return implode(', ', $this->_createNameAddressStrings($mailboxes));
  276. }
  277. /**
  278. * Redefine the encoding requirements for mailboxes.
  279. *
  280. * Commas and semicolons are used to separate
  281. * multiple addresses, and should therefore be encoded
  282. *
  283. * @param string $token
  284. *
  285. * @return bool
  286. */
  287. protected function tokenNeedsEncoding($token)
  288. {
  289. return preg_match('/[,;]/', $token) || parent::tokenNeedsEncoding($token);
  290. }
  291. /**
  292. * Return an array of strings conforming the the name-addr spec of RFC 2822.
  293. *
  294. * @param string[] $mailboxes
  295. *
  296. * @return string[]
  297. */
  298. private function _createNameAddressStrings(array $mailboxes)
  299. {
  300. $strings = array();
  301. foreach ($mailboxes as $email => $name) {
  302. $mailboxStr = $email;
  303. if (!is_null($name)) {
  304. $nameStr = $this->createDisplayNameString($name, empty($strings));
  305. $mailboxStr = $nameStr . ' <' . $mailboxStr . '>';
  306. }
  307. $strings[] = $mailboxStr;
  308. }
  309. return $strings;
  310. }
  311. /**
  312. * Throws an Exception if the address passed does not comply with RFC 2822.
  313. *
  314. * @param string $address
  315. *
  316. * @throws Swift_RfcComplianceException If invalid.
  317. */
  318. private function _assertValidAddress($address)
  319. {
  320. if (!preg_match('/^' . $this->getGrammar()->getDefinition('addr-spec') . '$/D',
  321. $address))
  322. {
  323. throw new Swift_RfcComplianceException(
  324. 'Address in mailbox given [' . $address .
  325. '] does not comply with RFC 2822, 3.6.2.'
  326. );
  327. }
  328. }
  329. }