Address.php 4.32 KB
Newer Older
Ketan's avatar
Ketan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
<?php
/**
 * @see       https://github.com/zendframework/zend-mail for the canonical source repository
 * @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
 * @license   https://github.com/zendframework/zend-mail/blob/master/LICENSE.md New BSD License
 */

namespace Zend\Mail;

use Zend\Validator\EmailAddress as EmailAddressValidator;
use Zend\Validator\Hostname;

class Address implements Address\AddressInterface
{
    protected $comment;
    protected $email;
    protected $name;

    /**
     * Create an instance from a string value.
     *
     * Parses a string representing a single address. If it is a valid format,
     * it then creates and returns an instance of itself using the name and
     * email it has parsed from the value.
     *
     * @param string $address
     * @param null|string $comment Comment associated with the address, if any.
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public static function fromString($address, $comment = null)
    {
        if (! preg_match('/^((?P<name>.*)<(?P<namedEmail>[^>]+)>|(?P<email>.+))$/', $address, $matches)) {
            throw new Exception\InvalidArgumentException('Invalid address format');
        }

        $name = null;
        if (isset($matches['name'])) {
            $name = trim($matches['name']);
        }
        if (empty($name)) {
            $name = null;
        }

        if (isset($matches['namedEmail'])) {
            $email = $matches['namedEmail'];
        }
        if (isset($matches['email'])) {
            $email = $matches['email'];
        }
        $email = trim($email);

        return new static($email, $name, $comment);
    }

    /**
     * Constructor
     *
     * @param  string $email
     * @param  null|string $name
     * @param  null|string $comment
     * @throws Exception\InvalidArgumentException
     */
    public function __construct($email, $name = null, $comment = null)
    {
        $emailAddressValidator = new EmailAddressValidator(Hostname::ALLOW_DNS | Hostname::ALLOW_LOCAL);
        if (! is_string($email) || empty($email)) {
            throw new Exception\InvalidArgumentException('Email must be a valid email address');
        }

        if (preg_match("/[\r\n]/", $email)) {
            throw new Exception\InvalidArgumentException('CRLF injection detected');
        }

        if (! $emailAddressValidator->isValid($email)) {
            $invalidMessages = $emailAddressValidator->getMessages();
            throw new Exception\InvalidArgumentException(array_shift($invalidMessages));
        }

        if (null !== $name) {
            if (! is_string($name)) {
                throw new Exception\InvalidArgumentException('Name must be a string');
            }

            if (preg_match("/[\r\n]/", $name)) {
                throw new Exception\InvalidArgumentException('CRLF injection detected');
            }

            $this->name = $name;
        }

        $this->email = $email;

        if (null !== $comment) {
            $this->comment = $comment;
        }
    }

    /**
     * Retrieve email
     *
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Retrieve name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Retrieve comment, if any
     *
     * @return null|string
     */
    public function getComment()
    {
        return $this->comment;
    }

    /**
     * String representation of address
     *
     * @return string
     */
    public function toString()
    {
        $string = sprintf('<%s>', $this->getEmail());
        $name   = $this->constructName();
        if (null === $name) {
            return $string;
        }

        return sprintf('%s %s', $name, $string);
    }

    /**
     * Constructs the name string
     *
     * If a comment is present, appends the comment (commented using parens) to
     * the name before returning it; otherwise, returns just the name.
     *
     * @return null|string
     */
    private function constructName()
    {
        $name = $this->getName();
        $comment = $this->getComment();

        if ($comment === null || $comment === '') {
            return $name;
        }

        $string = sprintf('%s (%s)', $name, $comment);
        return trim($string);
    }
}