8000 [Mime] added classes for generating MIME messages · symfony/symfony@ee787d1 · GitHub
[go: up one dir, main page]

Skip to content

Commit ee787d1

Browse files
committed
[Mime] added classes for generating MIME messages
1 parent 91c5b14 commit ee787d1

File tree

100 files changed

+8201
-17
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+8201
-17
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"symfony/contracts": "^1.0.2",
3232
"symfony/polyfill-ctype": "~1.8",
3333
"symfony/polyfill-intl-icu": "~1.0",
34+
"symfony/polyfill-intl-idn": "^1.10",
3435
"symfony/polyfill-mbstring": "~1.0",
3536
"symfony/polyfill-php72": "~1.5",
3637
"symfony/polyfill-php73": "^1.8"
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Twig\Mime;
13+
14+
use League\HTMLToMarkdown\HtmlConverter;
15+
use Twig\Environment;
16+
17+
/**
18+
* @author Fabien Potencier <fabien@symfony.com>
19+
*
20+
* @experimental in 4.3
21+
*/
22+
final class Renderer
23+
{
24+
private $twig;
25+
private $context;
26+
private $converter;
27+
28+
public function __construct(Environment $twig, array $context = [])
29+
{
30+
$this->twig = $twig;
31+
$this->context = $context;
32+
if (class_exists(HtmlConverter::class)) {
33+
$this->converter = new HtmlConverter([
34+
'hard_break' => true,
35+
'strip_tags' => true,
36+
'remove_nodes' => 'head style',
37+
]);
38+
}
39+
}
40+
41+
public function render(TemplatedEmail $email): TemplatedEmail
42+
{
43+
$email = clone $email;
44+
45+
$vars = array_merge($this->context, $email->getContext(), [
46+
'email' => new WrappedTemplatedEmail($this->twig, $email),
47+
]);
48+
49+
if ($template = $email->getTemplate()) {
50+
$this->renderFull($email, $template, $vars);
51+
}
52+
53+
if ($template = $email->getTextTemplate()) {
54+
$email->text($this->twig->render($template, $vars));
55+
}
56+
57+
if ($template = $email->getHtmlTemplate()) {
58+
$email->html($this->twig->render($template, $vars));
59+
}
60+
61+
// if text body is empty, compute one from the HTML body
62+
if (!$email->getTextBody() && null !== $html = $email->getHtmlBody()) {
63+
$email->text($this->convertHtmlToText(\is_resource($html) ? stream_get_contents($html) : $html));
64+
}
65+
66+
return $email;
67+
}
68+
69+
private function renderFull(TemplatedEmail $email, string $template, array $vars): void
70+
{
71+
$template = $this->twig->load($template);
72+
73+
if ($template->hasBlock('subject', $vars)) {
74+
$email->subject($template->renderBlock('subject', $vars));
75+
}
76+
77+
if ($template->hasBlock('text', $vars)) {
78+
$email->text($template->renderBlock('text', $vars));
79+
}
80+
81+
if ($template->hasBlock('html', $vars)) {
82+
$email->html($template->renderBlock('html', $vars));
83+
}
84+
85+
if ($template->hasBlock('config', $vars)) {
86+
// we discard the output as we're only interested
87+
// in the side effect of calling email methods
88+
$template->renderBlock('config', $vars);
89+
}
90+
}
91+
92+
private function convertHtmlToText(string $html): string
93+
{
94+
if (null !== $this->converter) {
95+
return $this->converter->convert($html);
96+
}
97+
98+
return strip_tags($html);
99+
}
100+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Twig\Mime;
13+
14+
use Symfony\Component\Mime\Email;
15+
16+
/**
17+
* @author Fabien Potencier <fabien@symfony.com>
18+
*
19+
* @experimental in 4.3
20+
*/
21+
class TemplatedEmail extends Email
22+
{
23+
private $template;
24+
private $htmlTemplate;
25+
private $textTemplate;
26+
private $context = [];
27+
28+
/**
29+
* @return $this
30+
*/
31+
public function template(?string $template)
32+
{
33+
$this->template = $template;
34+
35+
return $this;
36+
}
37+
38+
/**
39+
* @return $this
40+
*/
41+
public function textTemplate(?string $template)
42+
{
43+
$this->textTemplate = $template;
44+
45+
return $this;
46+
}
47+
48+
/**
49+
* @return $this
50+
*/
51+
public function htmlTemplate(?string $template)
52+
{
53+
$this->htmlTemplate = $template;
54+
55+
return $this;
56+
}
57+
58+
public function getTemplate(): ?string
59+
{
60+
return $this->template;
61+
}
62+
63+
public function getTextTemplate(): ?string
64+
{
65+
return $this->textTemplate;
66+
}
67+
68+
public function getHtmlTemplate(): ?string
69+
{
70+
return $this->htmlTemplate;
71+
}
72+
73+
/**
74+
* @return $this
75+
*/
76+
public function context(array $context)
77+
{
78+
$this->context = $context;
79+
80+
return $this;
81+
}
82+
83+
public function getContext(): array
84+
{
85+
return $this->context;
86+
}
87+
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Twig\Mime;
13+
14+
use Symfony\Component\Mime\Address;
15+
use Symfony\Component\Mime\NamedAddress;
16+
use Twig\Environment;
17+
18+
/**
19+
* @internal
20+
*
21+
* @author Fabien Potencier <fabien@symfony.com>
22+
*
23+
* @experimental in 4.3
24+
*/
25+
final class WrappedTemplatedEmail
26+
{
27+
private $twig;
28+
private $message;
29+
30+
public function __construct(Environment $twig, TemplatedEmail $message)
31+
{
32+
$this->twig = $twig;
33+
$this->message = $message;
34+
}
35+
36+
public function toName(): string
37+
{
38+
$to = $this->message->getTo()[0];
39+
40+
return $to instanceof NamedAddress ? $to->getName() : '';
41+
}
42+
43+
public function image(string $image, string $contentType = null): string
44+
{
45+
$file = $this->twig->getLoader()->getSourceContext($image);
46+
if ($path = $file->getPath()) {
47+
$this->message->embedFromPath($path, $image, $contentType);
48+
} else {
49+
$this->message->embed($file->getCode(), $image, $contentType);
50+
}
51+
52+
return 'cid:'.$image;
53+
}
54+
55+
public function attach(string $file, string $name = null, string $contentType = null): void
56+
{
57+
$file = $this->twig->getLoader()->getSourceContext($file);
58+
if ($path = $file->getPath()) {
59+
$this->message->attachFromPath($path, $name, $contentType);
60+
} else {
61+
$this->message->attach($file->getCode(), $name, $contentType);
62+
}
63+
}
64+
65+
/**
66+
* @return $this
67+
*/
68+
public function setSubject(string $subject)
69+
{
70+
$this->message->subject($subject);
71+
72+
return $this;
73+
}
74+
75+
public function getSubject(): ?string
76+
{
77+
return $this->message->getSubject();
78+
}
79+
80+
/**
81+
* @return $this
82+
*/
83+
public function setReturnPath(string $address)
84+
{
85+
$this->message->returnPath($address);
86+
87+
return $this;
88+
}
89+
90+
public function getReturnPath(): string
91+
{
92+
return $this->message->getReturnPath();
93+
}
94+
95+
/**
96+
* @return $this
97+
*/
98+
public function addFrom(string $address, string $name = null)
99+
{
100+
$this->message->addFrom($name ? new NamedAddress($address, $name) : new Address($address));
101+
102+
return $this;
103+
}
104+
105+
/**
106+
* @return (Address|NamedAddress)[]
107+
*/
108+
public function getFrom(): array
109+
{
110+
return $this->message->getFrom();
111+
}
112+
113+
/**
114+
* @return $this
115+
*/
116+
public function addReplyTo(string $address)
117+
{
118+
$this->message->addReplyTo($address);
119+
120+
return $this;
121+
}
122+
123+
/**
124+
* @return Address[]
125+
*/
126+
public function getReplyTo(): array
127+
{
128+
return $this->message->getReplyTo();
129+
}
130+
131+
/**
132+
* @return $this
133+
*/
134+
public function addTo(string $address, string $name = null)
135+
{
136+
$this->message->addTo($name ? new NamedAddress($address, $name) : new Address($address));
137+
138+
return $this;
139+
}
140+
141+
/**
142+
* @return (Address|NamedAddress)[]
143+
*/
144+
public function getTo(): array
145+
{
146+
return $this->message->getTo();
147+
}
148+
149+
/**
150+
* @return $this
151+
*/
152+
public function addCc(string $address, string $name = null)
153+
{
154+
$this->message->addCc($name ? new NamedAddress($address, $name) : new Address($address));
155+
156+
return $this;
157+
}
158+
159+
/**
160+
* @return (Address|NamedAddress)[]
161+
*/
162+
public function getCc(): array
163+
{
164+
return $this->message->getCc();
165+
}
166+
167+
/**
168+
* @return $this
169+
*/
170+
public function addBcc(string $address, string $name = null)
171+
{
172+
$this->message->addBcc($name ? new NamedAddress($address, $name) : new Address($address));
173+
174+
return $this;
175+
}
176+
177+
/**
178+
* @return (Address|NamedAddress)[]
179+
*/
180+
public function getBcc(): array
181+
{
182+
return $this->message< 93AB /span>->getBcc();
183+
}
184+
185+
/**
186+
* @return $this
187+
*/
188+
public function setPriority(int $priority)
189+
{
190+
$this->message->setPriority($priority);
191+
192+
return $this;
193+
}
194+
195+
public function getPriority(): int
196+
{
197+
return $this->message->getPriority();
198+
}
199+
}

0 commit comments

Comments
 (0)
0