You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
5.3 KiB

3 years ago
  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\Mime;
  11. use Symfony\Component\Mime\Exception\RuntimeException;
  12. use Symfony\Component\Mime\Part\DataPart;
  13. use Symfony\Component\Mime\Part\Multipart\AlternativePart;
  14. use Symfony\Component\Mime\Part\Multipart\MixedPart;
  15. use Symfony\Component\Mime\Part\Multipart\RelatedPart;
  16. use Symfony\Component\Mime\Part\TextPart;
  17. /**
  18. * @author Fabien Potencier <fabien@symfony.com>
  19. */
  20. final class MessageConverter
  21. {
  22. /**
  23. * @throws RuntimeException when unable to convert the message to an email
  24. */
  25. public static function toEmail(Message $message): Email
  26. {
  27. if ($message instanceof Email) {
  28. return $message;
  29. }
  30. // try to convert to a "simple" Email instance
  31. $body = $message->getBody();
  32. if ($body instanceof TextPart) {
  33. return self::createEmailFromTextPart($message, $body);
  34. }
  35. if ($body instanceof AlternativePart) {
  36. return self::createEmailFromAlternativePart($message, $body);
  37. }
  38. if ($body instanceof RelatedPart) {
  39. return self::createEmailFromRelatedPart($message, $body);
  40. }
  41. if ($body instanceof MixedPart) {
  42. $parts = $body->getParts();
  43. if ($parts[0] instanceof RelatedPart) {
  44. $email = self::createEmailFromRelatedPart($message, $parts[0]);
  45. } elseif ($parts[0] instanceof AlternativePart) {
  46. $email = self::createEmailFromAlternativePart($message, $parts[0]);
  47. } elseif ($parts[0] instanceof TextPart) {
  48. $email = self::createEmailFromTextPart($message, $parts[0]);
  49. } else {
  50. throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
  51. }
  52. return self::attachParts($email, \array_slice($parts, 1));
  53. }
  54. throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
  55. }
  56. private static function createEmailFromTextPart(Message $message, TextPart $part): Email
  57. {
  58. if ('text' === $part->getMediaType() && 'plain' === $part->getMediaSubtype()) {
  59. return (new Email(clone $message->getHeaders()))->text($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8');
  60. }
  61. if ('text' === $part->getMediaType() && 'html' === $part->getMediaSubtype()) {
  62. return (new Email(clone $message->getHeaders()))->html($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8');
  63. }
  64. throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
  65. }
  66. private static function createEmailFromAlternativePart(Message $message, AlternativePart $part): Email
  67. {
  68. $parts = $part->getParts();
  69. if (
  70. 2 === \count($parts) &&
  71. $parts[0] instanceof TextPart && 'text' === $parts[0]->getMediaType() && 'plain' === $parts[0]->getMediaSubtype() &&
  72. $parts[1] instanceof TextPart && 'text' === $parts[1]->getMediaType() && 'html' === $parts[1]->getMediaSubtype()
  73. ) {
  74. return (new Email(clone $message->getHeaders()))
  75. ->text($parts[0]->getBody(), $parts[0]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8')
  76. ->html($parts[1]->getBody(), $parts[1]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8')
  77. ;
  78. }
  79. throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
  80. }
  81. private static function createEmailFromRelatedPart(Message $message, RelatedPart $part): Email
  82. {
  83. $parts = $part->getParts();
  84. if ($parts[0] instanceof AlternativePart) {
  85. $email = self::createEmailFromAlternativePart($message, $parts[0]);
  86. } elseif ($parts[0] instanceof TextPart) {
  87. $email = self::createEmailFromTextPart($message, $parts[0]);
  88. } else {
  89. throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
  90. }
  91. return self::attachParts($email, \array_slice($parts, 1));
  92. }
  93. private static function attachParts(Email $email, array $parts): Email
  94. {
  95. foreach ($parts as $part) {
  96. if (!$part instanceof DataPart) {
  97. throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($email)));
  98. }
  99. $headers = $part->getPreparedHeaders();
  100. $method = 'inline' === $headers->getHeaderBody('Content-Disposition') ? 'embed' : 'attach';
  101. $name = $headers->getHeaderParameter('Content-Disposition', 'filename');
  102. $email->$method($part->getBody(), $name, $part->getMediaType().'/'.$part->getMediaSubtype());
  103. }
  104. return $email;
  105. }
  106. }