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 f143ee4

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

File tree

Expand file treeCollapse file tree

8 files changed

+369
-1
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+369
-1
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+4Lines 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

+17Lines 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>
+221Lines 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 %}
+1Lines changed: 1 addition & 0 deletions
Loading
+64Lines 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 <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\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 <fabien@symfony.com>
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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Mailer/Event/MessageEvent.php
+1-1Lines 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 <fabien@symfony.com>
2222
*/
+46Lines 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 <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\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 <fabien@symfony.com>
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.