ClearAndLogFailedMailsCommand::execute()   B
last analyzed

Complexity

Conditions 9
Paths 40

Size

Total Lines 73
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 9.0128

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 9
eloc 39
c 2
b 0
f 1
nc 40
nop 2
dl 0
loc 73
ccs 35
cts 37
cp 0.9459
crap 9.0128
rs 7.7404

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Azine\EmailBundle\Command;
4
5
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
6
use Symfony\Component\Console\Input\InputArgument;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Output\OutputInterface;
9
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
10
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
11
use Symfony\Component\Finder\Finder;
12
13
/**
14
 * Try to send emails that failed and are still pending in the spool-folder.
15
 *
16
 * After trying to send them one more time, delete the files and log any email-address that still failed.
17
 *
18
 * @author dominik
19
 */
20
class ClearAndLogFailedMailsCommand extends ContainerAwareCommand
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Bundle\Framework...d\ContainerAwareCommand has been deprecated: since Symfony 4.2, use {@see Command} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

20
class ClearAndLogFailedMailsCommand extends /** @scrutinizer ignore-deprecated */ ContainerAwareCommand
Loading history...
21
{
22 6
    protected function configure()
23
    {
24 6
        $this->setName('emails:clear-and-log-failures')
25 6
            ->setDescription('Clears and logs failed emails from the spool')
26 6
            ->setDefinition(array(new InputArgument('date',
27 6
                                                        InputArgument::OPTIONAL,
28 6
                                                        'Try to send and then delete all failed emails that are older than "date". The date must be something that strtotime() is able to parse:  => e.g. "since yesterday", "until 2 days ago", "> now - 2 hours", ">= 2005-10-15" '
29
                                                    ),
30
                            ))
31 6
            ->setHelp(<<<EOF
32 6
The <info>emails:clear-and-log-failures</info> command tries to send failed emails and deletes them
33
from the spool directory after this last try. Any email-address that still failed, is logged.
34
EOF
35
            )
36
            ;
37 6
    }
38
39 5
    protected function execute(InputInterface $input, OutputInterface $output)
40
    {
41 5
        $failedRecipients = array();
42
43
        // check if the current environment is configured to spool emails
44
        try {
45
            /** @var $transport \Swift_Transport */
46 5
            $transport = $this->getContainer()->get('swiftmailer.transport.real');
47 1
        } catch (ServiceNotFoundException $ex) {
48 1
            $output->writeln("\n\n\nCould not load transport. Is file-spooling configured in your config.yml for this environment?\n\n\n");
49
50 1
            return;
51
        }
52
53
        try {
54 4
            $mailers = $this->getContainer()->getParameter('swiftmailer.mailers');
55 3
            $mailerName = key($mailers);
56 3
            $spoolPath = $this->getContainer()->getParameter("swiftmailer.spool.$mailerName.file.path");
57 1
        } catch (InvalidArgumentException $ex) {
58 1
            $output->writeln("\n\n\nCould not find file spool path. Is file-spooling configured in your config.yml for this environment?\n\n\n");
59
60 1
            return;
61
        }
62
63
        // start the mail transport
64 3
        if (!$transport->isStarted()) {
65 3
            $transport->start();
66
        }
67
68
        // find pending mails and try to send them again now
69 3
        $finder = Finder::create()->in($spoolPath)->name('*.sending');
70
71 3
        $date = $input->getArgument('date');
72
73 3
        if ($date) {
74 1
            $finder->date($date);
75
        }
76
77 3
        if (0 == $finder->count()) {
78 1
            $output->writeln("No failed-message-files found in '$spoolPath' for retry.");
79
80 1
            return;
81
        }
82
83 2
        foreach ($finder as $failedFile) {
84
            // rename the file, so no other process tries to find it
85 2
            $tmpFilename = $failedFile.'.finalretry';
86 2
            rename($failedFile, $tmpFilename);
87
88
            /** @var $message \Swift_Message */
89 2
            $message = unserialize(file_get_contents($tmpFilename));
90 2
            $output->writeln(sprintf(
91 2
                    "Retrying to send '<info>%s</info>' to '<info>%s</info>'",
92 2
                    $message->getSubject(),
93 2
                    implode(', ', array_keys($message->getTo()))
94
            ));
95
96
            try {
97 2
                $transport->send($message, $failedRecipients);
98 2
                $output->writeln('Sent!');
99
            } catch (\Swift_TransportException $e) {
100
                $output->writeln('<error>Send failed - deleting spooled message</error>');
101
            }
102
103
            // delete the file, either because it sent, or because it failed
104 2
            unlink($tmpFilename);
105
        }
106
107
        // write the failure to the log
108 2
        if (sizeof($failedRecipients) > 0) {
109
            /** @var $logger LoggerInterface */
110 2
            $logger = $this->getContainer()->get('logger');
111 2
            $logger->warning('<error>Failed to send an email to : '.implode(', ', $failedRecipients).'</error>');
112
        }
113 2
    }
114
}
115