- <?php
- /**
- * Zend Framework (http://framework.zend.com/)
- *
- * @link http://github.com/zendframework/zf2 for the canonical source repository
- * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-
- namespace Zend\Mail;
-
- use Traversable;
- use Zend\Mime;
-
- class Message
- {
- /**
- * Content of the message
- *
- * @var string|object
- */
- protected $body;
-
- /**
- * @var Headers
- */
- protected $headers;
-
- /**
- * Message encoding
- *
- * Used to determine whether or not to encode headers; defaults to ASCII.
- *
- * @var string
- */
- protected $encoding = 'ASCII';
-
- /**
- * Is the message valid?
- *
- * If we don't any From addresses, we're invalid, according to RFC2822.
- *
- * @return bool
- */
- public function isValid()
- {
- $from = $this->getFrom();
- if (!$from instanceof AddressList) {
- return false;
- }
- return (bool) count($from);
- }
-
- /**
- * Set the message encoding
- *
- * @param string $encoding
- * @return Message
- */
- public function setEncoding($encoding)
- {
- $this->encoding = $encoding;
- $this->getHeaders()->setEncoding($encoding);
- return $this;
- }
-
- /**
- * Get the message encoding
- *
- * @return string
- */
- public function getEncoding()
- {
- return $this->encoding;
- }
-
- /**
- * Compose headers
- *
- * @param Headers $headers
- * @return Message
- */
- public function setHeaders(Headers $headers)
- {
- $this->headers = $headers;
- $headers->setEncoding($this->getEncoding());
- return $this;
- }
-
- /**
- * Access headers collection
- *
- * Lazy-loads if not already attached.
- *
- * @return Headers
- */
- public function getHeaders()
- {
- if (null === $this->headers) {
- $this->setHeaders(new Headers());
- $date = Header\Date::fromString('Date: ' . date('r'));
- $this->headers->addHeader($date);
- }
- return $this->headers;
- }
-
- /**
- * Set (overwrite) From addresses
- *
- * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
- * @param string|null $name
- * @return Message
- */
- public function setFrom($emailOrAddressList, $name = null)
- {
- $this->clearHeaderByName('from');
- return $this->addFrom($emailOrAddressList, $name);
- }
-
- /**
- * Add a "From" address
- *
- * @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
- * @param string|null $name
- * @return Message
- */
- public function addFrom($emailOrAddressOrList, $name = null)
- {
- $addressList = $this->getFrom();
- $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
- return $this;
- }
-
- /**
- * Retrieve list of From senders
- *
- * @return AddressList
- */
- public function getFrom()
- {
- return $this->getAddressListFromHeader('from', __NAMESPACE__ . '\Header\From');
- }
-
- /**
- * Overwrite the address list in the To recipients
- *
- * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
- * @param null|string $name
- * @return Message
- */
- public function setTo($emailOrAddressList, $name = null)
- {
- $this->clearHeaderByName('to');
- return $this->addTo($emailOrAddressList, $name);
- }
-
- /**
- * Add one or more addresses to the To recipients
- *
- * Appends to the list.
- *
- * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
- * @param null|string $name
- * @return Message
- */
- public function addTo($emailOrAddressOrList, $name = null)
- {
- $addressList = $this->getTo();
- $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
- return $this;
- }
-
- /**
- * Access the address list of the To header
- *
- * @return AddressList
- */
- public function getTo()
- {
- return $this->getAddressListFromHeader('to', __NAMESPACE__ . '\Header\To');
- }
-
- /**
- * Set (overwrite) CC addresses
- *
- * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
- * @param string|null $name
- * @return Message
- */
- public function setCc($emailOrAddressList, $name = null)
- {
- $this->clearHeaderByName('cc');
- return $this->addCc($emailOrAddressList, $name);
- }
-
- /**
- * Add a "Cc" address
- *
- * @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
- * @param string|null $name
- * @return Message
- */
- public function addCc($emailOrAddressOrList, $name = null)
- {
- $addressList = $this->getCc();
- $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
- return $this;
- }
-
- /**
- * Retrieve list of CC recipients
- *
- * @return AddressList
- */
- public function getCc()
- {
- return $this->getAddressListFromHeader('cc', __NAMESPACE__ . '\Header\Cc');
- }
-
- /**
- * Set (overwrite) BCC addresses
- *
- * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
- * @param string|null $name
- * @return Message
- */
- public function setBcc($emailOrAddressList, $name = null)
- {
- $this->clearHeaderByName('bcc');
- return $this->addBcc($emailOrAddressList, $name);
- }
-
- /**
- * Add a "Bcc" address
- *
- * @param string|Address|array|AddressList|Traversable $emailOrAddressOrList
- * @param string|null $name
- * @return Message
- */
- public function addBcc($emailOrAddressOrList, $name = null)
- {
- $addressList = $this->getBcc();
- $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
- return $this;
- }
-
- /**
- * Retrieve list of BCC recipients
- *
- * @return AddressList
- */
- public function getBcc()
- {
- return $this->getAddressListFromHeader('bcc', __NAMESPACE__ . '\Header\Bcc');
- }
-
- /**
- * Overwrite the address list in the Reply-To recipients
- *
- * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList
- * @param null|string $name
- * @return Message
- */
- public function setReplyTo($emailOrAddressList, $name = null)
- {
- $this->clearHeaderByName('reply-to');
- return $this->addReplyTo($emailOrAddressList, $name);
- }
-
- /**
- * Add one or more addresses to the Reply-To recipients
- *
- * Appends to the list.
- *
- * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
- * @param null|string $name
- * @return Message
- */
- public function addReplyTo($emailOrAddressOrList, $name = null)
- {
- $addressList = $this->getReplyTo();
- $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__);
- return $this;
- }
-
- /**
- * Access the address list of the Reply-To header
- *
- * @return AddressList
- */
- public function getReplyTo()
- {
- return $this->getAddressListFromHeader('reply-to', __NAMESPACE__ . '\Header\ReplyTo');
- }
-
- /**
- * setSender
- *
- * @param mixed $emailOrAddress
- * @param mixed $name
- * @return Message
- */
- public function setSender($emailOrAddress, $name = null)
- {
- $header = $this->getHeaderByName('sender', __NAMESPACE__ . '\Header\Sender');
- $header->setAddress($emailOrAddress, $name);
- return $this;
- }
-
- /**
- * Retrieve the sender address, if any
- *
- * @return null|Address\AddressInterface
- */
- public function getSender()
- {
- $header = $this->getHeaderByName('sender', __NAMESPACE__ . '\Header\Sender');
- return $header->getAddress();
- }
-
- /**
- * Set the message subject header value
- *
- * @param string $subject
- * @return Message
- */
- public function setSubject($subject)
- {
- $headers = $this->getHeaders();
- if (!$headers->has('subject')) {
- $header = new Header\Subject();
- $headers->addHeader($header);
- } else {
- $header = $headers->get('subject');
- }
- $header->setSubject($subject);
- return $this;
- }
-
- /**
- * Get the message subject header value
- *
- * @return null|string
- */
- public function getSubject()
- {
- $headers = $this->getHeaders();
- if (!$headers->has('subject')) {
- return null;
- }
- $header = $headers->get('subject');
- return $header->getFieldValue();
- }
-
- /**
- * Set the message body
- *
- * @param null|string|\Zend\Mime\Message|object $body
- * @throws Exception\InvalidArgumentException
- * @return Message
- */
- public function setBody($body)
- {
- if (!is_string($body) && $body !== null) {
- if (!is_object($body)) {
- throw new Exception\InvalidArgumentException(sprintf(
- '%s expects a string or object argument; received "%s"',
- __METHOD__,
- gettype($body)
- ));
- }
- if (!$body instanceof Mime\Message) {
- if (!method_exists($body, '__toString')) {
- throw new Exception\InvalidArgumentException(sprintf(
- '%s expects object arguments of type Zend\Mime\Message or implementing __toString(); object of type "%s" received',
- __METHOD__,
- get_class($body)
- ));
- }
- }
- }
- $this->body = $body;
-
- if (!$this->body instanceof Mime\Message) {
- return $this;
- }
-
- // Get headers, and set Mime-Version header
- $headers = $this->getHeaders();
- $this->getHeaderByName('mime-version', __NAMESPACE__ . '\Header\MimeVersion');
-
- // Multipart content headers
- if ($this->body->isMultiPart()) {
- $mime = $this->body->getMime();
- $header = $this->getHeaderByName('content-type', __NAMESPACE__ . '\Header\ContentType');
- $header->setType('multipart/mixed');
- $header->addParameter('boundary', $mime->boundary());
- return $this;
- }
-
- // MIME single part headers
- $parts = $this->body->getParts();
- if (!empty($parts)) {
- $part = array_shift($parts);
- $headers->addHeaders($part->getHeadersArray());
- }
- return $this;
- }
-
- /**
- * Return the currently set message body
- *
- * @return object
- */
- public function getBody()
- {
- return $this->body;
- }
-
- /**
- * Get the string-serialized message body text
- *
- * @return string
- */
- public function getBodyText()
- {
- if ($this->body instanceof Mime\Message) {
- return $this->body->generateMessage(Headers::EOL);
- }
-
- return (string) $this->body;
- }
-
- /**
- * Retrieve a header by name
- *
- * If not found, instantiates one based on $headerClass.
- *
- * @param string $headerName
- * @param string $headerClass
- * @return \Zend\Mail\Header\HeaderInterface
- */
- protected function getHeaderByName($headerName, $headerClass)
- {
- $headers = $this->getHeaders();
- if ($headers->has($headerName)) {
- $header = $headers->get($headerName);
- } else {
- $header = new $headerClass();
- $headers->addHeader($header);
- }
- return $header;
- }
-
- /**
- * Clear a header by name
- *
- * @param string $headerName
- */
- protected function clearHeaderByName($headerName)
- {
- $this->getHeaders()->removeHeader($headerName);
- }
-
- /**
- * Retrieve the AddressList from a named header
- *
- * Used with To, From, Cc, Bcc, and ReplyTo headers. If the header does not
- * exist, instantiates it.
- *
- * @param string $headerName
- * @param string $headerClass
- * @throws Exception\DomainException
- * @return AddressList
- */
- protected function getAddressListFromHeader($headerName, $headerClass)
- {
- $header = $this->getHeaderByName($headerName, $headerClass);
- if (!$header instanceof Header\AbstractAddressList) {
- throw new Exception\DomainException(sprintf(
- 'Cannot grab address list from header of type "%s"; not an AbstractAddressList implementation',
- get_class($header)
- ));
- }
- return $header->getAddressList();
- }
-
- /**
- * Update an address list
- *
- * Proxied to this from addFrom, addTo, addCc, addBcc, and addReplyTo.
- *
- * @param AddressList $addressList
- * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList
- * @param null|string $name
- * @param string $callingMethod
- * @throws Exception\InvalidArgumentException
- */
- protected function updateAddressList(AddressList $addressList, $emailOrAddressOrList, $name, $callingMethod)
- {
- if ($emailOrAddressOrList instanceof Traversable) {
- foreach ($emailOrAddressOrList as $address) {
- $addressList->add($address);
- }
- return;
- }
- if (is_array($emailOrAddressOrList)) {
- $addressList->addMany($emailOrAddressOrList);
- return;
- }
- if (!is_string($emailOrAddressOrList) && !$emailOrAddressOrList instanceof Address\AddressInterface) {
- throw new Exception\InvalidArgumentException(sprintf(
- '%s expects a string, AddressInterface, array, AddressList, or Traversable as its first argument; received "%s"',
- $callingMethod,
- (is_object($emailOrAddressOrList) ? get_class($emailOrAddressOrList) : gettype($emailOrAddressOrList))
- ));
- }
- $addressList->add($emailOrAddressOrList, $name);
- }
-
- /**
- * Serialize to string
- *
- * @return string
- */
- public function toString()
- {
- $headers = $this->getHeaders();
- return $headers->toString()
- . Headers::EOL
- . $this->getBodyText();
- }
-
- /**
- * Instantiate from raw message string
- *
- * @todo Restore body to Mime\Message
- * @param string $rawMessage
- * @return Message
- */
- public static function fromString($rawMessage)
- {
- $message = new static();
- $headers = null;
- $content = null;
- Mime\Decode::splitMessage($rawMessage, $headers, $content);
- if ($headers->has('mime-version')) {
- // todo - restore body to mime\message
- }
- $message->setHeaders($headers);
- $message->setBody($content);
- return $message;
- }
- }