Completed
Pull Request — master (#29)
by Eugene
03:29
created

ClearAndLogFailedMailsCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 0
crap 1
1
<?php
2
namespace Azine\EmailBundle\Command;
3
4
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
5
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
6
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
7
use Symfony\Component\Finder\Finder;
8
use Symfony\Component\Console\Input\InputArgument;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use Symfony\Component\Console\Input\InputInterface;
11
12
use \Swift_Transport;
13
14
/**
15
 * Try to send emails that failed and are still pending in the spool-folder.
16
 *
17
 * After trying to send them one more time, delete the files and log any email-address that still failed.
18
 *
19
 * @author dominik
20
 *
21
 */
22
class ClearAndLogFailedMailsCommand extends ContainerAwareCommand
23
{
24 6
    protected function configure()
25
    {
26 6
        $this->setName('emails:clear-and-log-failures')
27 6
            ->setDescription('Clears and logs failed emails from the spool')
28 6
            ->setDefinition(array(new InputArgument(	'date',
29 6
                                                        InputArgument::OPTIONAL,
30 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" '
31
                                                    ),
32
                            ))
33 6
            ->setHelp(<<<EOF
34 6
The <info>emails:clear-and-log-failures</info> command tries to send failed emails and deletes them
35
from the spool directory after this last try. Any email-address that still failed, is logged.
36
EOF
37
            )
38
            ;
39 6
    }
40
41 5
    protected function execute(InputInterface $input, OutputInterface $output)
42
    {
43 5
        $failedRecipients = array();
44
45
        // check if the current environment is configured to spool emails
46
        try {
47
            /** @var $transport \Swift_Transport */
48 5
            $transport = $this->getContainer()->get('swiftmailer.transport.real');
49
50 1
        } catch (ServiceNotFoundException $ex) {
51 1
            $output->writeln("\n\n\nCould not load transport. Is file-spooling configured in your config.yml for this environment?\n\n\n");
52
53 1
            return;
54
        }
55
56
        try {
57 4
            $mailers = $this->getContainer()->getParameter("swiftmailer.mailers");
58 3
            $mailerName = key($mailers);
59 3
            $spoolPath = $this->getContainer()->getParameter("swiftmailer.spool.$mailerName.file.path");
60 1
        } catch (InvalidArgumentException $ex) {
61 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");
62
63 1
            return;
64
        }
65
66
        // start the mail transport
67 3
        if (!$transport->isStarted()) {
68 3
            $transport->start();
69
        }
70
71
        // find pending mails and try to send them again now
72 3
        $finder = Finder::create()->in($spoolPath)->name('*.sending');
73
74 3
        $date = $input->getArgument('date');
75
76 3
        if ($date) {
77 1
            $finder->date($date);
78
        }
79
80 3
        if ($finder->count() == 0) {
81 1
            $output->writeln("No failed-message-files found in '$spoolPath' for retry.");
82
83 1
            return;
84
        }
85
86 2
        foreach ($finder as $failedFile) {
87
            // rename the file, so no other process tries to find it
88 2
            $tmpFilename = $failedFile.'.finalretry';
89 2
            rename($failedFile, $tmpFilename);
90
91
            /** @var $message \Swift_Message */
92 2
            $message = unserialize(file_get_contents($tmpFilename));
93 2
            $output->writeln(sprintf(
94 2
                    "Retrying to send '<info>%s</info>' to '<info>%s</info>'",
95 2
                    $message->getSubject(),
96 2
                    implode(', ', array_keys($message->getTo()))
97
            ));
98
99
            try {
100 2
                $transport->send($message, $failedRecipients);
101 2
                $output->writeln('Sent!');
102
            } catch (\Swift_TransportException $e) {
103
                $output->writeln('<error>Send failed - deleting spooled message</error>');
104
            }
105
106
            // delete the file, either because it sent, or because it failed
107 2
            unlink($tmpFilename);
108
        }
109
110
        // write the failure to the log
111 2
        if (sizeof($failedRecipients) > 0) {
112
            /** @var $logger LoggerInterface */
113 2
            $logger = $this->getContainer()->get("logger");
114 2
            $logger->warning("<error>Failed to send an email to : ".implode(", ", $failedRecipients)."</error>");
115
        }
116 2
    }
117
}
118