Envelope.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Mailer;
  11. use Symfony\Component\Mailer\Exception\InvalidArgumentException;
  12. use Symfony\Component\Mailer\Exception\LogicException;
  13. use Symfony\Component\Mime\Address;
  14. use Symfony\Component\Mime\RawMessage;
  15. /**
  16. * @author Fabien Potencier <fabien@symfony.com>
  17. */
  18. class Envelope
  19. {
  20. private Address $sender;
  21. private array $recipients = [];
  22. /**
  23. * @param Address[] $recipients
  24. */
  25. public function __construct(Address $sender, array $recipients)
  26. {
  27. $this->setSender($sender);
  28. $this->setRecipients($recipients);
  29. }
  30. public static function create(RawMessage $message): self
  31. {
  32. if (RawMessage::class === $message::class) {
  33. throw new LogicException('Cannot send a RawMessage instance without an explicit Envelope.');
  34. }
  35. return new DelayedEnvelope($message);
  36. }
  37. public function setSender(Address $sender): void
  38. {
  39. // to ensure deliverability of bounce emails independent of UTF-8 capabilities of SMTP servers
  40. if (!preg_match('/^[^@\x80-\xFF]++@/', $sender->getAddress())) {
  41. throw new InvalidArgumentException(\sprintf('Invalid sender "%s": non-ASCII characters not supported in local-part of email.', $sender->getAddress()));
  42. }
  43. $this->sender = $sender;
  44. }
  45. /**
  46. * @return Address Returns a "mailbox" as specified by RFC 2822
  47. * Must be converted to an "addr-spec" when used as a "MAIL FROM" value in SMTP (use getAddress())
  48. */
  49. public function getSender(): Address
  50. {
  51. return $this->sender;
  52. }
  53. /**
  54. * @param Address[] $recipients
  55. */
  56. public function setRecipients(array $recipients): void
  57. {
  58. if (!$recipients) {
  59. throw new InvalidArgumentException('An envelope must have at least one recipient.');
  60. }
  61. $this->recipients = [];
  62. foreach ($recipients as $recipient) {
  63. if (!$recipient instanceof Address) {
  64. throw new InvalidArgumentException(\sprintf('A recipient must be an instance of "%s" (got "%s").', Address::class, get_debug_type($recipient)));
  65. }
  66. $this->recipients[] = new Address($recipient->getAddress());
  67. }
  68. }
  69. /**
  70. * @return Address[]
  71. */
  72. public function getRecipients(): array
  73. {
  74. return $this->recipients;
  75. }
  76. /**
  77. * Returns true if any address' localpart contains at least one
  78. * non-ASCII character, and false if all addresses have all-ASCII
  79. * localparts.
  80. *
  81. * This helps to decide whether to the SMTPUTF8 extensions (RFC
  82. * 6530 and following) for any given message.
  83. *
  84. * The SMTPUTF8 extension is strictly required if any address
  85. * contains a non-ASCII character in its localpart. If non-ASCII
  86. * is only used in domains (e.g. horst@freiherr-von-mühlhausen.de)
  87. * then it is possible to send the message using IDN encoding
  88. * instead of SMTPUTF8. The most common software will display the
  89. * message as intended.
  90. */
  91. public function anyAddressHasUnicodeLocalpart(): bool
  92. {
  93. if ($this->getSender()->hasUnicodeLocalpart()) {
  94. return true;
  95. }
  96. foreach ($this->getRecipients() as $r) {
  97. if ($r->hasUnicodeLocalpart()) {
  98. return true;
  99. }
  100. }
  101. return false;
  102. }
  103. }