Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f143ee4

Browse files
committed
[Mailer] added support for the profiler
1 parent 5d5e04b commit f143ee4

File tree

8 files changed

+369
-1
lines changed

8 files changed

+369
-1
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,10 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $
553553
$loader->load('messenger_debug.xml');
554554
}
555555

556+
if (class_exists(Mailer::class)) {
557+
$loader->load('mailer_debug.xml');
558+
}
559+
556560
$container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']);
557561
$container->setParameter('profiler_listener.only_master_requests', $config['only_master_requests']);
558562

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<services>
8+
<service id="mailer.logger_message_listener" class="Symfony\Component\Mailer\EventListener\MessageLoggerListener">
9+
<tag name="kernel.event_subscriber"/>
10+
</service>
11+
12+
<service id="mailer.data_collector" class="Symfony\Component\Mailer\DataCollector\MessageDataCollector">
13+
<argument type="service" id="mailer.logger_message_listener" />
14+
<tag name="data_collector" template="@WebProfiler/Collector/mailer.html.twig" id="mailer" />
15+
</service>
16+
</services>
17+
</container>
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
2+
3+
{% block toolbar %}
4+
{% if collector.messages|length %}
5+
{% set icon %}
6+
{% include('@WebProfiler/Icon/mailer.svg') %}
7+
<span class="sf-toolbar-value">{{ collector.messages|length }}</span>
8+
{% endset %}
9+
10+
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': profiler_url }) }}
11+
{% endif %}
12+
{% endblock %}
13+
14+
{% block head %}
15+
{{ parent() }}
16+
<style type="text/css">
17+
/* utility classes */
18+
.m-t-0 { margin-top: 0 !important; }
19+
.m-t-10 { margin-top: 10px !important; }
20+
21+
/* basic grid */
22+
.row {
23+
display: flex;
24+
flex-wrap: wrap;
25+
margin-right: -15px;
26+
margin-left: -15px;
27+
}
28+
.col {
29+
flex-basis: 0;
30+
flex-grow: 1;
31+
max-width: 100%;
32+
position: relative;
33+
width: 100%;
34+
min-height: 1px;
35+
padding-right: 15px;
36+
padding-left: 15px;
37+
}
38+
.col-4 {
39+
flex: 0 0 33.333333%;
40+
max-width: 33.333333%;
41+
}
42+
43+
/* small tabs */
44+
.sf-tabs-sm .tab-navigation li {
45+
font-size: 14px;
46+
padding: .3em .5em;
47+
}
48+
</style>
49+
{% endblock %}
50+
51+
{% block menu %}
52+
<span class="label {{ collector.messages|length ? '' : 'disabled' }}">
53+
<span class="icon">{{ include('@WebProfiler/Icon/mailer.svg') }}</span>
54+
55+
<strong>Emails</strong>
56+
{% if collector.messages|length > 0 %}
57+
<span class="count">
58+
<span>{{ collector.messages|length }}</span>
59+
</span>
60+
{% endif %}
61+
</span>
62+
{% endblock %}
63+
64+
{% block panel %}
65+
<h2>Emails</h2>
66+
67+
{% if not collector.messages|length %}
68+
<div class="empty">
69+
<p>No emails were sent.</p>
70+
</div>
71+
{% endif %}
72+
73+
<div class="card-block">
74+
<div class="sf-tabs sf-tabs-sm">
75+
{% for message in collector.messages %}
76+
<div class="tab">
77+
<h3 class="tab-title">Email #{{ loop.index }}</h3>
78+
<div class="tab-content">
79+
<div class="card">
80+
{% if message.headers is not defined %}
81+
<div class="card-block">
82+
<pre class="prewrap" style="max-height: 600px">{{ message.toString() }}</pre>
83+
</div>
84+
{% else %}
85+
<div class="card-block">
86+
<span class="label">Subject</span>
87+
<h2 class="m-t-10">{{ message.headers.get('subject').bodyAsString() ?? '(empty)' }}</h2>
88+
</div>
89+
90+
<div class="card-block">
91+
<div class="row">
92+
<div class="col col-4">
93+
<span class="label">From</span>
94+
<pre class="prewrap">{{ (message.headers.get('from').bodyAsString() ?? '(empty)')|replace({'From:': ''}) }}</pre>
95+
96+
<span class="label">To</span>
97+
<pre class="prewrap">{{ (message.headers.get('to').bodyAsString() ?? '(empty)')|replace({'To:': ''}) }}</pre>
98+
</div>
99+
<div class="col">
100+
<span class="label">Headers</span>
101+
<pre class="prewrap">{% for header in message.headers.all|filter(header => (header.name ?? '') not in ['Subject', 'From', 'To']) %}
102+
{{- header.toString }}
103+
{%~ endfor %}</pre>
104+
</div>
105+
</div>
106+
</div>
107+
108+
<div class="card-block">
109+
<div class="sf-tabs sf-tabs-sm">
110+
<div class="tab">
111+
<h3 class="tab-title">HTML Content</h3>
112+
<div class="tab-content">
113+
<pre class="prewrap" style="max-height: 600px">
114+
{%- if message.htmlCharset() %}
115+
{{- message.htmlBody()|convert_encoding('UTF-8', message.htmlCharset()) }}
116+
{%- else %}
117+
{{- message.htmlBody() }}
118+
{%- endif -%}
119+
</pre>
120+
</div>
121+
</div>
122+
<div class="tab">
123+
<h3 class="tab-title">Text Content</h3>
124+
<div class="tab-content">
125+
<pre class="prewrap" style="max-height: 600px">
126+
{%- if message.textCharset() %}
127+
{{- message.textBody()|convert_encoding('UTF-8', message.textCharset()) }}
128+
{%- else %}
129+
{{- message.textBody() }}
130+
{%- endif -%}
131+
</pre>
132+
</div>
133+
</div>
134+
{% for attachment in message.attachments %}
135+
<div class="tab">
136+
<h3 class="tab-title">Attachment #{{ loop.index }}</h3>
137+
<div class="tab-content">
138+
<pre class="prewrap" style="max-height: 600px">{{ attachment.toString() }}</pre>
139+
</div>
140+
</div>
141+
{% endfor %}
142+
<div class="tab">
143+
<h3 class="tab-title">Raw</h3>
144+
<div class="tab-content">
145+
<pre class="prewrap" style="max-height: 600px">{{ message.toString() }}</pre>
146+
</div>
147+
</div>
148+
</div>
149+
</div>
150+
151+
{# Message just dump the body (or each part? -> be careful, it's nested and with attachments) or Email text/html/...? #}
152+
{#
153+
<div class="card-block">
154+
<div class="sf-tabs sf-tabs-sm">
155+
<div class="tab">
156+
<h3 class="tab-title">Raw content</h3>
157+
158+
<div class="tab-content">
159+
<pre class="prewrap" style="max-height: 600px">
160+
{%- if message.charset is defined and message.charset %}
161+
{{- message.body|convert_encoding('UTF-8', message.charset) }}
162+
{%- else %}
163+
{{- message.body }}
164+
{%- endif -%}
165+
</pre>
166+
</div>
167+
</div>
168+
169+
<div class="tab">
170+
<h3 class="tab-title">Rendered content</h3>
171+
172+
<div class="tab-content">
173+
<iframe class="full-width" style="min-height: 600px" src="data:{{ message.__contentType }};base64,{{ message.__base64EncodedBody }}"></iframe>
174+
</div>
175+
</div>
176+
</div>
177+
</div>
178+
179+
{% for messagePart in message.children|filter(messagePart => messagePart.contentType in ['text/plain', 'text/html']) %}
180+
<div class="card-block">
181+
<span class="label">Alternative part ({{ messagePart.contentType }})</span>
182+
<pre class="prewrap">
183+
{%- if messagePart.charset is defined and messagePart.charset %}
184+
{{- messagePart.body|convert_encoding('UTF-8', messagePart.charset) }}
185+
{%- else %}
186+
{{- messagePart.body }}
187+
{%- endif -%}
188+
</pre>
189+
</div>
190+
{% endfor %}
191+
192+
{% set attachments = collector.extractAttachments(message) %}
193+
{% if attachments %}
194+
<div class="card-block">
195+
<span class="label">
196+
{% if attachments|length > 1 %}
197+
{{ attachments|length }} Attachments
198+
{% else %}
199+
1 Attachment
200+
{% endif %}
201+
</span>
202+
203+
<ol>
204+
{% for attachment in attachments %}
205+
<li>
206+
Filename:
207+
{{ attachment.filename }}
208+
</li>
209+
{% endfor %}
210+
</ol>
211+
</div>
212+
{% endif %}
213+
#}
214+
{% endif %}
215+
</div>
216+
</div>
217+
</div>
218+
{% endfor %}
219+
</div>
220+
</div>
221+
{% endblock %}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Component\Mailer\DataCollector;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
17+
use Symfony\Component\Mailer\EventListener\MessageLoggerListener;
18+
19+
/**
20+
* @author Fabien Potencier <[email protected]>
21+
*/
22+
class MessageDataCollector extends DataCollector
23+
{
24+
private $logger;
25+
26+
public function __construct(MessageLoggerListener $logger)
27+
{
28+
$this->logger = $logger;
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function collect(Request $request, Response $response, \Exception $exception = null)
35+
{
36+
$this->data = [
37+
'messages' => $this->logger->getMessages(),
38+
];
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public function reset()
45+
{
46+
$this->data = [];
47+
}
48+
49+
/**
50+
* @return Message[]
51+
*/
52+
public function getMessages(): array
53+
{
54+
return $this->data['messages'];
55+
}
56+
57+
/**
58+
* {@inheritdoc}
59+
*/
60+
public function getName()
61+
{
62+
return 'mailer';
63+
}
64+
}

src/Symfony/Component/Mailer/Event/MessageEvent.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use Symfony\Component\Mime\RawMessage;
1717

1818
/**
19-
* Allows the transformation of a Message.
19+
* Allows the transformation of a Message and the SMTP Envelope before the email is sent.
2020
*
2121
* @author Fabien Potencier <[email protected]>
2222
*/
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Component\Mailer\EventListener;
13+
14+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15+
use Symfony\Component\Mailer\Event\MessageEvent;
16+
use Symfony\Component\Mime\Message;
17+
18+
/**
19+
* Logs Messages.
20+
*
21+
* @author Fabien Potencier <[email protected]>
22+
*/
23+
class MessageLoggerListener implements EventSubscriberInterface
24+
{
25+
private $messages = [];
26+
27+
public function onMessage(MessageEvent $event): void
28+
{
29+
$this->messages[] = $event->getMessage();
30+
}
31+
32+
/**
33+
* @return Message[]
34+
*/
35+
public function getMessages(): array
36+
{
37+
return $this->messages;
38+
}
39+
40+
public static function getSubscribedEvents()
41+
{
42+
return [
43+
MessageEvent::class => ['onMessage', -255],
44+
];
45+
}
46+
}

0 commit comments

Comments
 (0)