Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9e5be30

Browse filesBrowse files
committed
[Mime] added classes for generating MIME messages
1 parent 91c5b14 commit 9e5be30
Copy full SHA for 9e5be30

File tree

100 files changed

+8203
-17
lines changed
Filter options

Some content is hidden

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

100 files changed

+8203
-17
lines changed

‎composer.json

Copy file name to clipboardExpand all lines: composer.json
+1Lines 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"
+100Lines 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+
}
+87Lines 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+
}
+199Lines 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->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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.