170 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			PHP
		
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			PHP
		
	
	
<?php
 | 
						|
 | 
						|
/*
 | 
						|
 * This file is part of the Symfony package.
 | 
						|
 *
 | 
						|
 * (c) Fabien Potencier <fabien@symfony.com>
 | 
						|
 *
 | 
						|
 * For the full copyright and license information, please view the LICENSE
 | 
						|
 * file that was distributed with this source code.
 | 
						|
 */
 | 
						|
 | 
						|
namespace Symfony\Component\Mime;
 | 
						|
 | 
						|
use Symfony\Component\Mime\Exception\LogicException;
 | 
						|
use Symfony\Component\Mime\Header\Headers;
 | 
						|
use Symfony\Component\Mime\Part\AbstractPart;
 | 
						|
use Symfony\Component\Mime\Part\TextPart;
 | 
						|
 | 
						|
/**
 | 
						|
 * @author Fabien Potencier <fabien@symfony.com>
 | 
						|
 */
 | 
						|
class Message extends RawMessage
 | 
						|
{
 | 
						|
    private Headers $headers;
 | 
						|
    private ?AbstractPart $body;
 | 
						|
 | 
						|
    public function __construct(?Headers $headers = null, ?AbstractPart $body = null)
 | 
						|
    {
 | 
						|
        $this->headers = $headers ? clone $headers : new Headers();
 | 
						|
        $this->body = $body;
 | 
						|
    }
 | 
						|
 | 
						|
    public function __clone()
 | 
						|
    {
 | 
						|
        $this->headers = clone $this->headers;
 | 
						|
 | 
						|
        if (null !== $this->body) {
 | 
						|
            $this->body = clone $this->body;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function setBody(?AbstractPart $body = null): static
 | 
						|
    {
 | 
						|
        if (1 > \func_num_args()) {
 | 
						|
            trigger_deprecation('symfony/mime', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
 | 
						|
        }
 | 
						|
        $this->body = $body;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getBody(): ?AbstractPart
 | 
						|
    {
 | 
						|
        return $this->body;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function setHeaders(Headers $headers): static
 | 
						|
    {
 | 
						|
        $this->headers = $headers;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getHeaders(): Headers
 | 
						|
    {
 | 
						|
        return $this->headers;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getPreparedHeaders(): Headers
 | 
						|
    {
 | 
						|
        $headers = clone $this->headers;
 | 
						|
 | 
						|
        if (!$headers->has('From')) {
 | 
						|
            if (!$headers->has('Sender')) {
 | 
						|
                throw new LogicException('An email must have a "From" or a "Sender" header.');
 | 
						|
            }
 | 
						|
            $headers->addMailboxListHeader('From', [$headers->get('Sender')->getAddress()]);
 | 
						|
        }
 | 
						|
 | 
						|
        if (!$headers->has('MIME-Version')) {
 | 
						|
            $headers->addTextHeader('MIME-Version', '1.0');
 | 
						|
        }
 | 
						|
 | 
						|
        if (!$headers->has('Date')) {
 | 
						|
            $headers->addDateHeader('Date', new \DateTimeImmutable());
 | 
						|
        }
 | 
						|
 | 
						|
        // determine the "real" sender
 | 
						|
        if (!$headers->has('Sender') && \count($froms = $headers->get('From')->getAddresses()) > 1) {
 | 
						|
            $headers->addMailboxHeader('Sender', $froms[0]);
 | 
						|
        }
 | 
						|
 | 
						|
        if (!$headers->has('Message-ID')) {
 | 
						|
            $headers->addIdHeader('Message-ID', $this->generateMessageId());
 | 
						|
        }
 | 
						|
 | 
						|
        // remove the Bcc field which should NOT be part of the sent message
 | 
						|
        $headers->remove('Bcc');
 | 
						|
 | 
						|
        return $headers;
 | 
						|
    }
 | 
						|
 | 
						|
    public function toString(): string
 | 
						|
    {
 | 
						|
        if (null === $body = $this->getBody()) {
 | 
						|
            $body = new TextPart('');
 | 
						|
        }
 | 
						|
 | 
						|
        return $this->getPreparedHeaders()->toString().$body->toString();
 | 
						|
    }
 | 
						|
 | 
						|
    public function toIterable(): iterable
 | 
						|
    {
 | 
						|
        if (null === $body = $this->getBody()) {
 | 
						|
            $body = new TextPart('');
 | 
						|
        }
 | 
						|
 | 
						|
        yield $this->getPreparedHeaders()->toString();
 | 
						|
        yield from $body->toIterable();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function ensureValidity()
 | 
						|
    {
 | 
						|
        if (!$this->headers->get('To')?->getBody() && !$this->headers->get('Cc')?->getBody() && !$this->headers->get('Bcc')?->getBody()) {
 | 
						|
            throw new LogicException('An email must have a "To", "Cc", or "Bcc" header.');
 | 
						|
        }
 | 
						|
 | 
						|
        if (!$this->headers->get('From')?->getBody() && !$this->headers->get('Sender')?->getBody()) {
 | 
						|
            throw new LogicException('An email must have a "From" or a "Sender" header.');
 | 
						|
        }
 | 
						|
 | 
						|
        parent::ensureValidity();
 | 
						|
    }
 | 
						|
 | 
						|
    public function generateMessageId(): string
 | 
						|
    {
 | 
						|
        if ($this->headers->has('Sender')) {
 | 
						|
            $sender = $this->headers->get('Sender')->getAddress();
 | 
						|
        } elseif ($this->headers->has('From')) {
 | 
						|
            if (!$froms = $this->headers->get('From')->getAddresses()) {
 | 
						|
                throw new LogicException('A "From" header must have at least one email address.');
 | 
						|
            }
 | 
						|
            $sender = $froms[0];
 | 
						|
        } else {
 | 
						|
            throw new LogicException('An email must have a "From" or a "Sender" header.');
 | 
						|
        }
 | 
						|
 | 
						|
        return bin2hex(random_bytes(16)).strstr($sender->getAddress(), '@');
 | 
						|
    }
 | 
						|
 | 
						|
    public function __serialize(): array
 | 
						|
    {
 | 
						|
        return [$this->headers, $this->body];
 | 
						|
    }
 | 
						|
 | 
						|
    public function __unserialize(array $data): void
 | 
						|
    {
 | 
						|
        [$this->headers, $this->body] = $data;
 | 
						|
    }
 | 
						|
}
 |