Skip to content

Commit 2cc5306

Browse files
committed
[Mailer] introduce debug command
Aim is to allow to test if your mailer configuration or supplier is operational in production Usage - console debug:mailer:email:send --from=a@symfony.com --to=b@symfony.com --subject=Test --body=body - console debug:mailer:email:send
1 parent 44e98db commit 2cc5306

File tree

5 files changed

+238
-0
lines changed

5 files changed

+238
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ public function load(array $configs, ContainerBuilder $container)
386386

387387
if ($this->mailerConfigEnabled = $this->isConfigEnabled($container, $config['mailer'])) {
388388
$this->registerMailerConfiguration($config['mailer'], $container, $loader);
389+
} else {
390+
$container->removeDefinition('console.command.mailer_debug');
389391
}
390392

391393
if ($this->notifierConfigEnabled = $this->isConfigEnabled($container, $config['notifier'])) {

src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
use Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand;
4040
use Symfony\Bundle\FrameworkBundle\EventListener\SuggestMissingPackageSubscriber;
4141
use Symfony\Component\Console\EventListener\ErrorListener;
42+
use Symfony\Component\Mailer\Command\MailerDebugCommand;
4243
use Symfony\Component\Messenger\Command\ConsumeMessagesCommand;
4344
use Symfony\Component\Messenger\Command\DebugCommand;
4445
use Symfony\Component\Messenger\Command\FailedMessagesRemoveCommand;
@@ -133,6 +134,12 @@
133134
])
134135
->tag('console.command', ['command' => 'debug:event-dispatcher'])
135136

137+
->set('console.command.mailer_debug', MailerDebugCommand::class)
138+
->args([
139+
service('mailer.mailer')->ignoreOnInvalid(),
140+
])
141+
->tag('console.command', ['command' => 'debug:mailer:send-email'])
142+
136143
->set('console.command.messenger_consume_messages', ConsumeMessagesCommand::class)
137144
->args([
138145
abstract_arg('Routable message bus'),

src/Symfony/Component/Mailer/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ CHANGELOG
55
-----
66

77
* added the `mailer` monolog channel and set it on all transport definitions
8+
* added `console debug:mailer:send-email` command to check if your mailer configuration or supplier is (still) operational
9+
810

911
5.2.0
1012
-----
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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\Command;
13+
14+
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Input\InputInterface;
16+
use Symfony\Component\Console\Input\InputOption;
17+
use Symfony\Component\Console\Output\OutputInterface;
18+
use Symfony\Component\Console\Style\SymfonyStyle;
19+
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
20+
use Symfony\Component\Mailer\MailerInterface;
21+
use Symfony\Component\Mime\Email;
22+
23+
/**
24+
* Helps making sure your mailer provider is operational.
25+
*
26+
* @author Guillaume MOREL <me@gmorel.io>
27+
*/
28+
final class MailerDebugCommand extends Command
29+
{
30+
/** {@inheritdoc} */
31+
protected static $defaultName = 'debug:mailer:send-email';
32+
33+
/** @var ?MailerInterface */
34+
private $mailer;
35+
36+
/** @var SymfonyStyle */
37+
private $io;
38+
39+
/**
40+
* {@inheritdoc}
41+
*/
42+
public function __construct(?MailerInterface $mailer)
43+
{
44+
parent::__construct();
45+
46+
$this->mailer = $mailer;
47+
}
48+
49+
/**
50+
* {@inheritdoc}
51+
*/
52+
protected function configure()
53+
{
54+
$this->setDescription('Send simple email message')
55+
->addArgument('from', null, 'The from address of the message')
56+
->addArgument('to', null, 'The to address of the message')
57+
->addOption('subject', null, InputOption::VALUE_REQUIRED, 'The subject of the message', 'Testing Mailer Component')
58+
->addOption('body', null, InputOption::VALUE_REQUIRED, 'The body of the message', 'This is a test email.')
59+
->setHelp(
60+
<<<EOF
61+
The <info>%command.name%</info> command creates and sends a simple email message.
62+
Usage:
63+
- <info>php %command.full_name%</info> will trigger the interactive mode
64+
- <info>php %command.full_name% from=a@symfony.com to=b@symfony.com</info>
65+
- <info>php %command.full_name% from=a@symfony.com to=b@symfony.com --subject=Test --body=body</info>
66+
EOF
67+
);
68+
}
69+
70+
/**
71+
* {@inheritdoc}
72+
*/
73+
protected function initialize(InputInterface $input, OutputInterface $output)
74+
{
75+
$this->io = new SymfonyStyle($input, $output);
76+
}
77+
78+
/**
79+
* {@inheritdoc}
80+
*
81+
* @throws TransportExceptionInterface
82+
*/
83+
protected function execute(InputInterface $input, OutputInterface $output): int
84+
{
85+
$email = $this->createEmail($input);
86+
87+
$this->mailer->send($email);
88+
89+
$this->io->success(
90+
sprintf(
91+
'Email was successfully sent to "%s".',
92+
(string) $input->getArgument('to')
93+
)
94+
);
95+
96+
return Command::SUCCESS;
97+
}
98+
99+
private function createEmail(InputInterface $input): Email
100+
{
101+
$subject = $input->getOption('subject');
102+
$body = $input->getOption('body');
103+
104+
return (new Email())
105+
->from($input->getArgument('from'))
106+
->to($input->getArgument('to'))
107+
->priority(Email::PRIORITY_HIGH)
108+
->subject($subject)
109+
->text($body)
110+
->html(
111+
<<<HTML
112+
<!doctype html>
113+
<html>
114+
<head>
115+
<meta name="viewport" content="width=device-width" />
116+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
117+
<title>$subject</title>
118+
</head>
119+
<body>
120+
<p>$body</p>
121+
</body>
122+
</html>
123+
HTML
124+
);
125+
}
126+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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\Tests\Command;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Console\Application;
16+
use Symfony\Component\Console\Tester\CommandTester;
17+
use Symfony\Component\Mailer\Command\MailerDebugCommand;
18+
use Symfony\Component\Mailer\MailerInterface;
19+
use Symfony\Component\Mime\Email;
20+
21+
class MailerDebugCommandTest extends TestCase
22+
{
23+
public function testSendMail()
24+
{
25+
$expectedMail = $this->createExpectedMail(
26+
'a@symfony.com',
27+
'b@symfony.com',
28+
'Test',
29+
'body'
30+
);
31+
32+
$mailer = $this->createMock(MailerInterface::class);
33+
$mailer->expects($this->once())->method('send')->with($expectedMail);
34+
35+
$command = new MailerDebugCommand($mailer);
36+
37+
$application = new Application();
38+
$application->add($command);
39+
$tester = new CommandTester($application->get('debug:mailer:send-email'));
40+
$tester->execute([
41+
'from' => 'a@symfony.com',
42+
'to' => 'b@symfony.com',
43+
'--subject' => 'Test',
44+
'--body' => 'body',
45+
]);
46+
47+
$this->assertSame(0, $tester->getStatusCode());
48+
$this->assertStringContainsString('[OK] Email was successfully sent to "b@symfony.com"', $tester->getDisplay());
49+
}
50+
51+
public function testSendMailNoSubject()
52+
{
53+
$expectedMail = $this->createExpectedMail(
54+
'a@symfony.com',
55+
'b@symfony.com',
56+
'Testing Mailer Component',
57+
'This is a test email.'
58+
);
59+
60+
$mailer = $this->createMock(MailerInterface::class);
61+
$mailer->expects($this->once())->method('send')->with($expectedMail);
62+
63+
$command = new MailerDebugCommand($mailer);
64+
65+
$application = new Application();
66+
$application->add($command);
67+
$tester = new CommandTester($application->get('debug:mailer:send-email'));
68+
$tester->execute([
69+
'from' => 'a@symfony.com',
70+
'to' => 'b@symfony.com',
71+
]);
72+
73+
$this->assertSame(0, $tester->getStatusCode());
74+
$this->assertStringContainsString('[OK] Email was successfully sent to "b@symfony.com"', $tester->getDisplay());
75+
}
76+
77+
private function createExpectedMail(string $from, string $to, string $subject, string $body): Email
78+
{
79+
return (new Email())
80+
->from($from)
81+
->to($to)
82+
->priority(Email::PRIORITY_HIGH)
83+
->subject($subject)
84+
->text($body)
85+
->html(
86+
<<<HTML
87+
<!doctype html>
88+
<html>
89+
<head>
90+
<meta name="viewport" content="width=device-width" />
91+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
92+
<title>$subject</title>
93+
</head>
94+
<body>
95+
<p>$body</p>
96+
</body>
97+
</html>
98+
HTML
99+
);
100+
}
101+
}

0 commit comments

Comments
 (0)