Skip to content

Commit e5a6c8e

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 49eafee commit e5a6c8e

File tree

4 files changed

+238
-0
lines changed

4 files changed

+238
-0
lines changed

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;
@@ -293,5 +294,11 @@
293294
service('secrets.local_vault'),
294295
])
295296
->tag('console.command', ['command' => 'secrets:encrypt-from-local'])
297+
298+
->set('console.command.mailer_debug', MailerDebugCommand::class)
299+
->args([
300+
service('mailer.mailer')->ignoreOnInvalid(),
301+
])
302+
->tag('console.command', ['command' => 'debug:mailer:send-email'])
296303
;
297304
};

src/Symfony/Component/Mailer/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.3.0
5+
-----
6+
7+
* added `console debug:mailer:send-email` command to check if your mailer configuration or supplier is (still) operational in production
8+
49
5.2.0
510
-----
611

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
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
29+
*/
30+
class MailerDebugCommand extends Command
31+
{
32+
/** {@inheritdoc} */
33+
protected static $defaultName = 'debug:mailer:send-email';
34+
35+
/** @var ?MailerInterface */
36+
private $mailer;
37+
38+
/** @var SymfonyStyle */
39+
private $io;
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public function __construct(?MailerInterface $mailer)
45+
{
46+
parent::__construct();
47+
48+
$this->mailer = $mailer;
49+
}
50+
51+
/**
52+
* {@inheritdoc}
53+
*/
54+
public function isEnabled()
55+
{
56+
return null !== $this->mailer;
57+
}
58+
59+
/**
60+
* {@inheritdoc}
61+
*/
62+
protected function configure()
63+
{
64+
$this->setDescription('Send simple email message')
65+
->setDefinition([
66+
new InputOption('from', null, InputOption::VALUE_REQUIRED, 'The from email of the message'),
67+
new InputOption('to', null, InputOption::VALUE_REQUIRED, 'The to email of the message'),
68+
new InputOption('subject', null, InputOption::VALUE_REQUIRED, 'The subject of the message'),
69+
new InputOption('body', null, InputOption::VALUE_REQUIRED, 'The body of the message'),
70+
])
71+
->setHelp(
72+
<<<EOF
73+
The <info>%command.name%</info> command creates and sends a simple email message.
74+
Usage:
75+
- <info>php %command.full_name%</info> will trigger the interactive mode
76+
- <info>php %command.full_name% --from=a@symfony.com --to=b@symfony.com --subject=Test --body=body</info>
77+
EOF
78+
);
79+
}
80+
81+
/**
82+
* {@inheritdoc}
83+
*/
84+
protected function initialize(InputInterface $input, OutputInterface $output)
85+
{
86+
$this->io = new SymfonyStyle($input, $output);
87+
}
88+
89+
/**
90+
* {@inheritdoc}
91+
*
92+
* @throws TransportExceptionInterface
93+
*/
94+
protected function execute(InputInterface $input, OutputInterface $output): int
95+
{
96+
$email = $this->createEmail($input);
97+
98+
try {
99+
$this->mailer->send($email);
100+
} catch (TransportExceptionInterface $e) {
101+
$this->io->error('Fail to send email.');
102+
throw $e;
103+
}
104+
105+
$this->io->success(
106+
sprintf(
107+
'Email was successfully sent to "%s".',
108+
(string) $input->getOption('to')
109+
)
110+
);
111+
112+
return Command::SUCCESS;
113+
}
114+
115+
/**
116+
* {@inheritdoc}
117+
*/
118+
protected function interact(InputInterface $input, OutputInterface $output)
119+
{
120+
foreach ($input->getOptions() as $option => $value) {
121+
if (null === $value) {
122+
$input->setOption($option, $this->io->ask(sprintf('%s', ucfirst($option))));
123+
}
124+
}
125+
}
126+
127+
private function createEmail(InputInterface $input): Email
128+
{
129+
return (new Email())
130+
->from($input->getOption('from'))
131+
->to($input->getOption('to'))
132+
->priority(Email::PRIORITY_HIGH)
133+
->subject($input->getOption('subject'))
134+
->text($input->getOption('body'))
135+
->html($input->getOption('body'));
136+
}
137+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
27+
$mailer = $this->createMock(MailerInterface::class);
28+
$mailer->expects($this->once())->method('send')->with($expectedMail);
29+
30+
$command = new MailerDebugCommand($mailer);
31+
32+
$application = new Application();
33+
$application->add($command);
34+
$tester = new CommandTester($application->get('debug:mailer:send-email'));
35+
$tester->execute([
36+
'--from' => 'a@symfony.com',
37+
'--to' => 'b@symfony.com',
38+
'--subject' => 'Test',
39+
'--body' => 'body',
40+
]);
41+
42+
$this->assertSame(0, $tester->getStatusCode());
43+
$this->assertStringContainsString('[OK] Email was successfully sent to "b@symfony.com"', $tester->getDisplay());
44+
}
45+
46+
public function testSendMailInteractive()
47+
{
48+
$expectedMail = $this->createExpectedMail();
49+
50+
$mailer = $this->createMock(MailerInterface::class);
51+
$mailer->expects($this->once())->method('send')->with($expectedMail);
52+
53+
$command = new MailerDebugCommand($mailer);
54+
55+
$application = new Application();
56+
$application->add($command);
57+
$tester = new CommandTester($application->get('debug:mailer:send-email'));
58+
$tester->setInputs([
59+
'a@symfony.com',
60+
'b@symfony.com',
61+
'Test',
62+
'body',
63+
]);
64+
65+
$tester->execute(
66+
[],
67+
['interactive' => true]
68+
);
69+
70+
$this->assertSame(0, $tester->getStatusCode());
71+
72+
$this->assertStringContainsString("From:\n", $tester->getDisplay());
73+
$this->assertStringContainsString("To:\n", $tester->getDisplay());
74+
$this->assertStringContainsString("Subject:\n", $tester->getDisplay());
75+
$this->assertStringContainsString("Body:\n", $tester->getDisplay());
76+
$this->assertStringContainsString('[OK] Email was successfully sent to "b@symfony.com"', $tester->getDisplay());
77+
}
78+
79+
private function createExpectedMail(): Email
80+
{
81+
return (new Email())
82+
->from('a@symfony.com')
83+
->to('b@symfony.com')
84+
->priority(Email::PRIORITY_HIGH)
85+
->subject('Test')
86+
->text('body')
87+
->html('body');
88+
}
89+
}

0 commit comments

Comments
 (0)