headers.rst 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. Message Headers
  2. ===============
  3. Sometimes you'll want to add your own headers to a message or modify/remove
  4. headers that are already present. You work with the message's HeaderSet to do
  5. this.
  6. Header Basics
  7. -------------
  8. All MIME entities in Swift Mailer -- including the message itself --
  9. store their headers in a single object called a HeaderSet. This HeaderSet is
  10. retrieved with the ``getHeaders()`` method.
  11. As mentioned in the previous chapter, everything that forms a part of a
  12. message in Swift Mailer is a MIME entity that is represented by an instance of
  13. ``Swift_Mime_MimeEntity``. This includes -- most notably -- the
  14. message object itself, attachments, MIME parts and embedded images. Each of
  15. these MIME entities consists of a body and a set of headers that describe the
  16. body.
  17. For all of the "standard" headers in these MIME entities, such as the
  18. ``Content-Type``, there are named methods for working with them,
  19. such as ``setContentType()`` and
  20. ``getContentType()``. This is because headers are a moderately
  21. complex area of the library. Each header has a slightly different required
  22. structure that it must meet in order to comply with the standards that govern
  23. email (and that are checked by spam blockers etc).
  24. You fetch the HeaderSet from a MIME entity like so:
  25. .. code-block:: php
  26. $message = Swift_Message::newInstance();
  27. //Fetch the HeaderSet from a Message object
  28. $headers = $message->getHeaders();
  29. $attachment = Swift_Attachment::fromPath('document.pdf');
  30. //Fetch the HeaderSet from an attachment object
  31. $headers = $attachment->getHeaders();
  32. The job of the HeaderSet is to contain and manage instances of Header objects.
  33. Depending upon the MIME entity the HeaderSet came from, the contents of the
  34. HeaderSet will be different, since an attachment for example has a different
  35. set of headers to those in a message.
  36. You can find out what the HeaderSet contains with a quick loop, dumping out
  37. the names of the headers:
  38. .. code-block:: php
  39. foreach ($headers->getAll() as $header) {
  40. printf("%s<br />\n", $header->getFieldName());
  41. }
  42. /*
  43. Content-Transfer-Encoding
  44. Content-Type
  45. MIME-Version
  46. Date
  47. Message-ID
  48. From
  49. Subject
  50. To
  51. */
  52. You can also dump out the rendered HeaderSet by calling its
  53. ``toString()`` method:
  54. .. code-block:: php
  55. echo $headers->toString();
  56. /*
  57. Message-ID: <1234869991.499a9ee7f1d5e@swift.generated>
  58. Date: Tue, 17 Feb 2009 22:26:31 +1100
  59. Subject: Awesome subject!
  60. From: sender@example.org
  61. To: recipient@example.org
  62. MIME-Version: 1.0
  63. Content-Type: text/plain; charset=utf-8
  64. Content-Transfer-Encoding: quoted-printable
  65. */
  66. Where the complexity comes in is when you want to modify an existing header.
  67. This complexity comes from the fact that each header can be of a slightly
  68. different type (such as a Date header, or a header that contains email
  69. addresses, or a header that has key-value parameters on it!). Each
  70. header in the HeaderSet is an instance of ``Swift_Mime_Header``.
  71. They all have common functionality, but knowing exactly what type of header
  72. you're working with will allow you a little more control.
  73. You can determine the type of header by comparing the return value of its
  74. ``getFieldType()`` method with the constants
  75. ``TYPE_TEXT``, ``TYPE_PARAMETERIZED``,
  76. ``TYPE_DATE``, ``TYPE_MAILBOX``,
  77. ``TYPE_ID`` and ``TYPE_PATH`` which are defined in
  78. ``Swift_Mime_Header``.
  79. .. code-block:: php
  80. foreach ($headers->getAll() as $header) {
  81. switch ($header->getFieldType()) {
  82. case Swift_Mime_Header::TYPE_TEXT: $type = 'text';
  83. break;
  84. case Swift_Mime_Header::TYPE_PARAMETERIZED: $type = 'parameterized';
  85. break;
  86. case Swift_Mime_Header::TYPE_MAILBOX: $type = 'mailbox';
  87. break;
  88. case Swift_Mime_Header::TYPE_DATE: $type = 'date';
  89. break;
  90. case Swift_Mime_Header::TYPE_ID: $type = 'ID';
  91. break;
  92. case Swift_Mime_Header::TYPE_PATH: $type = 'path';
  93. break;
  94. }
  95. printf("%s: is a %s header<br />\n", $header->getFieldName(), $type);
  96. }
  97. /*
  98. Content-Transfer-Encoding: is a text header
  99. Content-Type: is a parameterized header
  100. MIME-Version: is a text header
  101. Date: is a date header
  102. Message-ID: is a ID header
  103. From: is a mailbox header
  104. Subject: is a text header
  105. To: is a mailbox header
  106. */
  107. Headers can be removed from the set, modified within the set, or added to the
  108. set.
  109. The following sections show you how to work with the HeaderSet and explain the
  110. details of each implementation of ``Swift_Mime_Header`` that may
  111. exist within the HeaderSet.
  112. Header Types
  113. ------------
  114. Because all headers are modeled on different data (dates, addresses,
  115. text!) there are different types of Header in Swift Mailer. Swift Mailer
  116. attempts to categorize all possible MIME headers into more general groups,
  117. defined by a small number of classes.
  118. Text Headers
  119. ~~~~~~~~~~~~
  120. Text headers are the simplest type of Header. They contain textual information
  121. with no special information included within it -- for example the Subject
  122. header in a message.
  123. There's nothing particularly interesting about a text header, though it is
  124. probably the one you'd opt to use if you need to add a custom header to a
  125. message. It represents text just like you'd think it does. If the text
  126. contains characters that are not permitted in a message header (such as new
  127. lines, or non-ascii characters) then the header takes care of encoding the
  128. text so that it can be used.
  129. No header -- including text headers -- in Swift Mailer is vulnerable
  130. to header-injection attacks. Swift Mailer breaks any attempt at header
  131. injection by encoding the dangerous data into a non-dangerous form.
  132. It's easy to add a new text header to a HeaderSet. You do this by calling the
  133. HeaderSet's ``addTextHeader()`` method.
  134. .. code-block:: php
  135. $message = Swift_Message::newInstance();
  136. $headers = $message->getHeaders();
  137. $headers->addTextHeader('Your-Header-Name', 'the header value');
  138. Changing the value of an existing text header is done by calling it's
  139. ``setValue()`` method.
  140. .. code-block:: php
  141. $subject = $message->getHeaders()->getHeader('Subject');
  142. $subject->setValue('new subject');
  143. When output via ``toString()``, a text header produces something
  144. like the following:
  145. .. code-block:: php
  146. $subject = $message->getHeaders()->getHeader('Subject');
  147. $subject->setValue('amazing subject line');
  148. echo $subject->toString();
  149. /*
  150. Subject: amazing subject line
  151. */
  152. If the header contains any characters that are outside of the US-ASCII range
  153. however, they will be encoded. This is nothing to be concerned about since
  154. mail clients will decode them back.
  155. .. code-block:: php
  156. $subject = $message->getHeaders()->getHeader('Subject');
  157. $subject->setValue('contains – dash');
  158. echo $subject->toString();
  159. /*
  160. Subject: contains =?utf-8?Q?=E2=80=93?= dash
  161. */
  162. Parameterized Headers
  163. ~~~~~~~~~~~~~~~~~~~~~
  164. Parameterized headers are text headers that contain key-value parameters
  165. following the textual content. The Content-Type header of a message is a
  166. parameterized header since it contains charset information after the content
  167. type.
  168. The parameterized header type is a special type of text header. It extends the
  169. text header by allowing additional information to follow it. All of the
  170. methods from text headers are available in addition to the methods described
  171. here.
  172. Adding a parameterized header to a HeaderSet is done by using the
  173. ``addParameterizedHeader()`` method which takes a text value like
  174. ``addTextHeader()`` but it also accepts an associative array of
  175. key-value parameters.
  176. .. code-block:: php
  177. $message = Swift_Message::newInstance();
  178. $headers = $message->getHeaders();
  179. $headers->addParameterizedHeader(
  180. 'Header-Name', 'header value',
  181. array('foo' => 'bar')
  182. );
  183. To change the text value of the header, call it's ``setValue()``
  184. method just as you do with text headers.
  185. To change the parameters in the header, call the header's
  186. ``setParameters()`` method or the ``setParameter()``
  187. method (note the pluralization).
  188. .. code-block:: php
  189. $type = $message->getHeaders()->getHeader('Content-Type');
  190. //setParameters() takes an associative array
  191. $type->setParameters(array(
  192. 'name' => 'file.txt',
  193. 'charset' => 'iso-8859-1'
  194. ));
  195. //setParameter() takes two args for $key and $value
  196. $type->setParameter('charset', 'iso-8859-1');
  197. When output via ``toString()``, a parameterized header produces
  198. something like the following:
  199. .. code-block:: php
  200. $type = $message->getHeaders()->getHeader('Content-Type');
  201. $type->setValue('text/html');
  202. $type->setParameter('charset', 'utf-8');
  203. echo $type->toString();
  204. /*
  205. Content-Type: text/html; charset=utf-8
  206. */
  207. If the header contains any characters that are outside of the US-ASCII range
  208. however, they will be encoded, just like they are for text headers. This is
  209. nothing to be concerned about since mail clients will decode them back.
  210. Likewise, if the parameters contain any non-ascii characters they will be
  211. encoded so that they can be transmitted safely.
  212. .. code-block:: php
  213. $attachment = Swift_Attachment::newInstance();
  214. $disp = $attachment->getHeaders()->getHeader('Content-Disposition');
  215. $disp->setValue('attachment');
  216. $disp->setParameter('filename', 'report–may.pdf');
  217. echo $disp->toString();
  218. /*
  219. Content-Disposition: attachment; filename*=utf-8''report%E2%80%93may.pdf
  220. */
  221. Date Headers
  222. ~~~~~~~~~~~~
  223. Date headers contains an RFC 2822 formatted date (i.e. what PHP's
  224. ``date('r')`` returns). They are used anywhere a date or time is
  225. needed to be presented as a message header.
  226. The data on which a date header is modeled is simply a UNIX timestamp such as that
  227. returned by ``time()`` or ``strtotime()``. The timestamp
  228. is used to create a correctly structured RFC 2822 formatted date such as
  229. ``Tue, 17 Feb 2009 22:26:31 +1100``.
  230. The obvious place this header type is used is in the ``Date:`` header
  231. of the message itself.
  232. It's easy to add a new date header to a HeaderSet. You do this by calling
  233. the HeaderSet's ``addDateHeader()`` method.
  234. .. code-block:: php
  235. $message = Swift_Message::newInstance();
  236. $headers = $message->getHeaders();
  237. $headers->addDateHeader('Your-Header-Name', strtotime('3 days ago'));
  238. Changing the value of an existing date header is done by calling it's
  239. ``setTimestamp()`` method.
  240. .. code-block:: php
  241. $date = $message->getHeaders()->getHeader('Date');
  242. $date->setTimestamp(time());
  243. When output via ``toString()``, a date header produces something
  244. like the following:
  245. .. code-block:: php
  246. $date = $message->getHeaders()->getHeader('Date');
  247. echo $date->toString();
  248. /*
  249. Date: Wed, 18 Feb 2009 13:35:02 +1100
  250. */
  251. Mailbox (e-mail address) Headers
  252. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  253. Mailbox headers contain one or more email addresses, possibly with
  254. personalized names attached to them. The data on which they are modeled is
  255. represented by an associative array of email addresses and names.
  256. Mailbox headers are probably the most complex header type to understand in
  257. Swift Mailer because they accept their input as an array which can take
  258. various forms, as described in the previous chapter.
  259. All of the headers that contain e-mail addresses in a message -- with the
  260. exception of ``Return-Path:`` which has a stricter syntax --
  261. use this header type. That is, ``To:``, ``From:``
  262. etc.
  263. You add a new mailbox header to a HeaderSet by calling the HeaderSet's
  264. ``addMailboxHeader()`` method.
  265. .. code-block:: php
  266. $message = Swift_Message::newInstance();
  267. $headers = $message->getHeaders();
  268. $headers->addMailboxHeader('Your-Header-Name', array(
  269. 'person1@example.org' => 'Person Name One',
  270. 'person2@example.org',
  271. 'person3@example.org',
  272. 'person4@example.org' => 'Another named person'
  273. ));
  274. Changing the value of an existing mailbox header is done by calling it's
  275. ``setNameAddresses()`` method.
  276. .. code-block:: php
  277. $to = $message->getHeaders()->getHeader('To');
  278. $to->setNameAddresses(array(
  279. 'joe@example.org' => 'Joe Bloggs',
  280. 'john@example.org' => 'John Doe',
  281. 'no-name@example.org'
  282. ));
  283. If you don't wish to concern yourself with the complicated accepted input
  284. formats accepted by ``setNameAddresses()`` as described in the previous chapter
  285. and you only want to set one or more addresses (not names) then you can just
  286. use the ``setAddresses()`` method instead.
  287. .. code-block:: php
  288. $to = $message->getHeaders()->getHeader('To');
  289. $to->setAddresses(array(
  290. 'joe@example.org',
  291. 'john@example.org',
  292. 'no-name@example.org'
  293. ));
  294. .. note::
  295. Both methods will accept the above input format in practice.
  296. If all you want to do is set a single address in the header, you can use a
  297. string as the input parameter to ``setAddresses()`` and/or
  298. ``setNameAddresses()``.
  299. .. code-block:: php
  300. $to = $message->getHeaders()->getHeader('To');
  301. $to->setAddresses('joe-bloggs@example.org');
  302. When output via ``toString()``, a mailbox header produces
  303. something like the following:
  304. .. code-block:: php
  305. $to = $message->getHeaders()->getHeader('To');
  306. $to->setNameAddresses(array(
  307. 'person1@example.org' => 'Name of Person',
  308. 'person2@example.org',
  309. 'person3@example.org' => 'Another Person'
  310. ));
  311. echo $to->toString();
  312. /*
  313. To: Name of Person <person1@example.org>, person2@example.org, Another Person
  314. <person3@example.org>
  315. */
  316. ID Headers
  317. ~~~~~~~~~~
  318. ID headers contain identifiers for the entity (or the message). The most
  319. notable ID header is the Message-ID header on the message itself.
  320. An ID that exists inside an ID header looks more-or-less less like an email
  321. address. For example, ``<![CDATA[<1234955437.499becad62ec2@example.org>]]>``.
  322. The part to the left of the @ sign is usually unique, based on the current time and
  323. some random factor. The part on the right is usually a domain name.
  324. Any ID passed the an ID header's ``setId()`` method absolutely
  325. MUST conform to this structure, otherwise you'll get an Exception thrown at you
  326. by Swift Mailer (a ``Swift_RfcComplianceException``). This is to
  327. ensure that the generated email complies with relevant RFC documents and therefore
  328. is less likely to be blocked as spam.
  329. It's easy to add a new ID header to a HeaderSet. You do this by calling
  330. the HeaderSet's ``addIdHeader()`` method.
  331. .. code-block:: php
  332. $message = Swift_Message::newInstance();
  333. $headers = $message->getHeaders();
  334. $headers->addIdHeader('Your-Header-Name', '123456.unqiue@example.org');
  335. Changing the value of an existing date header is done by calling its
  336. ``setId()`` method.
  337. .. code-block:: php
  338. $msgId = $message->getHeaders()->getHeader('Message-ID');
  339. $msgId->setId(time() . '.' . uniqid('thing') . '@example.org');
  340. When output via ``toString()``, an ID header produces something
  341. like the following:
  342. .. code-block:: php
  343. $msgId = $message->getHeaders()->getHeader('Message-ID');
  344. echo $msgId->toString();
  345. /*
  346. Message-ID: <1234955437.499becad62ec2@example.org>
  347. */
  348. Path Headers
  349. ~~~~~~~~~~~~
  350. Path headers are like very-restricted mailbox headers. They contain a single
  351. email address with no associated name. The Return-Path header of a message is
  352. a path header.
  353. You add a new path header to a HeaderSet by calling the HeaderSet's
  354. ``addPathHeader()`` method.
  355. .. code-block:: php
  356. $message = Swift_Message::newInstance();
  357. $headers = $message->getHeaders();
  358. $headers->addPathHeader('Your-Header-Name', 'person@example.org');
  359. Changing the value of an existing path header is done by calling its
  360. ``setAddress()`` method.
  361. .. code-block:: php
  362. $return = $message->getHeaders()->getHeader('Return-Path');
  363. $return->setAddress('my-address@example.org');
  364. When output via ``toString()``, a path header produces something
  365. like the following:
  366. .. code-block:: php
  367. $return = $message->getHeaders()->getHeader('Return-Path');
  368. $return->setAddress('person@example.org');
  369. echo $return->toString();
  370. /*
  371. Return-Path: <person@example.org>
  372. */
  373. Header Operations
  374. -----------------
  375. Working with the headers in a message involves knowing how to use the methods
  376. on the HeaderSet and on the individual Headers within the HeaderSet.
  377. Adding new Headers
  378. ~~~~~~~~~~~~~~~~~~
  379. New headers can be added to the HeaderSet by using one of the provided
  380. ``add..Header()`` methods.
  381. To add a header to a MIME entity (such as the message):
  382. Get the HeaderSet from the entity by via its ``getHeaders()``
  383. method.
  384. * Add the header to the HeaderSet by calling one of the ``add..Header()``
  385. methods.
  386. The added header will appear in the message when it is sent.
  387. .. code-block:: php
  388. //Adding a custom header to a message
  389. $message = Swift_Message::newInstance();
  390. $headers = $message->getHeaders();
  391. $headers->addTextHeader('X-Mine', 'something here');
  392. //Adding a custom header to an attachment
  393. $attachment = Swift_Attachment::fromPath('/path/to/doc.pdf');
  394. $attachment->getHeaders()->addDateHeader('X-Created-Time', time());
  395. Retrieving Headers
  396. ~~~~~~~~~~~~~~~~~~
  397. Headers are retrieved through the HeaderSet's ``get()`` and
  398. ``getAll()`` methods.
  399. To get a header, or several headers from a MIME entity:
  400. * Get the HeaderSet from the entity by via its ``getHeaders()`` method.
  401. * Get the header(s) from the HeaderSet by calling either ``get()`` or
  402. ``getAll()``.
  403. When using ``get()`` a single header is returned that matches the
  404. name (case insensitive) that is passed to it. When using
  405. ``getAll()`` with a header name, an array of headers with that
  406. name are returned. Calling ``getAll()`` with no arguments returns
  407. an array of all headers present in the entity.
  408. .. note::
  409. It's valid for some headers to appear more than once in a message (e.g.
  410. the Received header). For this reason ``getAll()`` exists to fetch all
  411. headers with a specified name. In addition, ``get()`` accepts an optional
  412. numerical index, starting from zero to specify which header you want more
  413. specifically.
  414. .. note::
  415. If you want to modify the contents of the header and you don't know for
  416. sure what type of header it is then you may need to check the type by
  417. calling its ``getFieldType()`` method.
  418. .. code-block:: php
  419. $headers = $message->getHeaders();
  420. //Get the To: header
  421. $toHeader = $headers->get('To');
  422. //Get all headers named "X-Foo"
  423. $fooHeaders = $headers->getAll('X-Foo');
  424. //Get the second header named "X-Foo"
  425. $foo = $headers->get('X-Foo', 1);
  426. //Get all headers that are present
  427. $all = $headers->getAll();
  428. Check if a Header Exists
  429. ~~~~~~~~~~~~~~~~~~~~~~~~
  430. You can check if a named header is present in a HeaderSet by calling its
  431. ``has()`` method.
  432. To check if a header exists:
  433. * Get the HeaderSet from the entity by via its ``getHeaders()`` method.
  434. * Call the HeaderSet's ``has()`` method specifying the header you're looking
  435. for.
  436. If the header exists, ``true`` will be returned or
  437. ``false`` if not.
  438. .. note::
  439. It's valid for some headers to appear more than once in a message (e.g.
  440. the Received header). For this reason ``has()`` accepts an optional
  441. numerical index, starting from zero to specify which header you want to
  442. check more specifically.
  443. .. code-block:: php
  444. $headers = $message->getHeaders();
  445. //Check if the To: header exists
  446. if ($headers->has('To')) {
  447. echo 'To: exists';
  448. }
  449. //Check if an X-Foo header exists twice (i.e. check for the 2nd one)
  450. if ($headers->has('X-Foo', 1)) {
  451. echo 'Second X-Foo header exists';
  452. }
  453. Removing Headers
  454. ~~~~~~~~~~~~~~~~
  455. Removing a Header from the HeaderSet is done by calling the HeaderSet's
  456. ``remove()`` or ``removeAll()`` methods.
  457. To remove an existing header:
  458. * Get the HeaderSet from the entity by via its ``getHeaders()`` method.
  459. * Call the HeaderSet's ``remove()`` or ``removeAll()`` methods specifying the
  460. header you want to remove.
  461. When calling ``remove()`` a single header will be removed. When
  462. calling ``removeAll()`` all headers with the given name will be
  463. removed. If no headers exist with the given name, no errors will occur.
  464. .. note::
  465. It's valid for some headers to appear more than once in a message (e.g.
  466. the Received header). For this reason ``remove()`` accepts an optional
  467. numerical index, starting from zero to specify which header you want to
  468. check more specifically. For the same reason, ``removeAll()`` exists to
  469. remove all headers that have the given name.
  470. .. code-block:: php
  471. $headers = $message->getHeaders();
  472. //Remove the Subject: header
  473. $headers->remove('Subject');
  474. //Remove all X-Foo headers
  475. $headers->removeAll('X-Foo');
  476. //Remove only the second X-Foo header
  477. $headers->remove('X-Foo', 1);
  478. Modifying a Header's Content
  479. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  480. To change a Header's content you should know what type of header it is and
  481. then call it's appropriate setter method. All headers also have a
  482. ``setFieldBodyModel()`` method that accepts a mixed parameter and
  483. delegates to the correct setter.
  484. To modify an existing header:
  485. * Get the HeaderSet from the entity by via its ``getHeaders()`` method.
  486. * Get the Header by using the HeaderSet's ``get()``.
  487. * Call the Header's appropriate setter method or call the header's
  488. ``setFieldBodyModel()`` method.
  489. The header will be updated inside the HeaderSet and the changes will be seen
  490. when the message is sent.
  491. .. code-block:: php
  492. $headers = $message->getHeaders();
  493. //Change the Subject: header
  494. $subj = $headers->get('Subject');
  495. $subj->setValue('new subject here');
  496. //Change the To: header
  497. $to = $headers->get('To');
  498. $to->setNameAddresses(array(
  499. 'person@example.org' => 'Person',
  500. 'thing@example.org'
  501. ));
  502. //Using the setFieldBodyModel() just delegates to the correct method
  503. // So here to calls setNameAddresses()
  504. $to->setFieldBodyModel(array(
  505. 'person@example.org' => 'Person',
  506. 'thing@example.org'
  507. ));