Completed
Push — master ( b95243...4b89aa )
by Manuel
04:09 queued 02:30
created

SpammerCommand::validateInputToFrom()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 10
cts 10
cp 1
rs 8.8571
cc 5
eloc 11
nc 5
nop 1
crap 5
1
<?php
2
3
namespace EndelWar\Spammer\Command;
4
5
use Faker;
6
use Symfony\Component\Console\Command\Command;
7
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Output\OutputInterface;
11
12
class SpammerCommand extends Command
13
{
14 32
    protected function configure()
15
    {
16 32
        $count = 10;
17 32
        $smtpServerIp = '127.0.0.1';
18 32
        $smtpServerPort = '25';
19 32
        $locale = 'en_US';
20
21
        $this
22 32
            ->setName('spammer')
23 32
            ->setDescription('Send random content email')
24 32
            ->setDefinition(
25
                array(
26 32
                    new InputOption('server', 's', InputOption::VALUE_OPTIONAL, 'SMTP Server ip to send email to', $smtpServerIp),
27 32
                    new InputOption('port', 'p', InputOption::VALUE_OPTIONAL, 'SMTP Server port to send email to', $smtpServerPort),
28 32
                    new InputOption('count', 'c', InputOption::VALUE_OPTIONAL, 'Number of email to send', $count),
29 32
                    new InputOption('locale', 'l', InputOption::VALUE_OPTIONAL, 'Locale to use', $locale),
30 32
                    new InputOption('to', 't', InputOption::VALUE_OPTIONAL, 'To address or domain'),
31 32
                    new InputOption('from', 'f', InputOption::VALUE_OPTIONAL, 'From address or domain'),
32
                )
33
            );
34 32
    }
35
36
    /**
37
     * @param InputInterface $input
38
     * @param OutputInterface $output
39
     * @return integer
40
     * @throws \InvalidArgumentException
41
     */
42 31
    protected function execute(InputInterface $input, OutputInterface $output)
43
    {
44 31
        $validInput = $this->validateInput($input);
45
46 12
        $style = new OutputFormatterStyle('green', null, array('bold'));
47 12
        $output->getFormatter()->setStyle('bold', $style);
48 12
        $output->writeln('<comment>Spammer starting up</comment>');
49 12
        $message = '<info>Sending </info><bold>' . $validInput['count'] . '</bold>' .
50 12
            '<info> email to server </info><bold>' . $validInput['smtpServerIp'] . '</bold>' .
51 12
            '<info>:</info><bold>' . $validInput['smtpServerPort'] . '</bold>';
52 12
        if ($validInput['from'] !== '') {
53 3
            $message .= '<info> from </info><bold>' . $validInput['from'] . '</bold>';
54
        }
55 12
        if ($validInput['to'] !== '') {
56 3
            $message .= '<info> to </info><bold>' . $validInput['to'] . '</bold>';
57
        }
58 12
        $output->write($message);
59 12
        $output->writeln('<info> using locale </info><bold>' . $validInput['locale'] . '</bold>');
60
61 12
        $faker = Faker\Factory::create($validInput['locale']);
62 12
        $faker->seed(mt_rand());
63
64 12
        $transport = \Swift_SmtpTransport::newInstance()->setHost($validInput['smtpServerIp'])->setPort(
65 12
            $validInput['smtpServerPort']
66
        );
67 12
        $mailer = \Swift_Mailer::newInstance($transport);
68
69 12
        $numSent = 0;
70 12
        for ($i = 0; $i < $validInput['count']; $i++) {
71 12
            $emaiText = $faker->realText(mt_rand(200, 1000));
72 12
            $email_subject = implode(' ', $faker->words(mt_rand(3, 7)));
73 12
            $message = \Swift_Message::newInstance($email_subject);
74
75 12
            $from = $this->getFromTo($faker, $validInput['from']);
76 12
            $message->setFrom($from);
77
78 12
            $to = $this->getFromTo($faker, $validInput['to']);
79 12
            $message->setTo($to);
80
81 12
            $message->setBody($emaiText, 'text/plain');
82 12
            $message->addPart('<p>' . $emaiText . '</p>', 'text/html');
83
84 12
            $output->writeln('Sending email nr. ' . ($i + 1) . ': ' . key($from) . ' => ' . key($to));
85
            try {
86 12
                $numSent += $mailer->send($message);
87 1
            } catch (\Swift_TransportException $swe) {
88 1
                $output->writeln('<error>' . $swe->getMessage() . '</error>');
89
90 1
                return 1;
91
            }
92
        }
93
94 11
        $output->writeln('Sent ' . $numSent . ' messages');
95
96 11
        unset($faker);
97
98 11
        return 0;
99
    }
100
101
    /**
102
     * @param $faker
103
     * @param $validInputFromTo
104
     * @return array
105
     */
106 12
    private function getFromTo($faker, $validInputFromTo)
107
    {
108
        // generate fake address and name if null
109 12
        if ($validInputFromTo === '') {
110 11
            return [$faker->safeEmail => $faker->name];
111
        }
112
113
        // use user submitted email if is email
114 5
        if (filter_var($validInputFromTo, FILTER_VALIDATE_EMAIL)) {
115 3
            return [$validInputFromTo => $faker->name];
116
        }
117
118
        // get a random username and attach it to domain supplied by user
119 2
        $user = strstr($faker->safeEmail, '@', true);
120
121 2
        return [$user . '@' . $validInputFromTo => $faker->name];
122
    }
123
124
    /**
125
     * @param InputInterface $input
126
     * @throws \InvalidArgumentException
127
     * @return array
128
     */
129 31
    protected function validateInput(InputInterface $input)
130
    {
131 31
        $validInput = array();
132 31
        $validInput['smtpServerIp'] = $input->getOption('server');
133 31
        $this->validateInputServerIP($validInput['smtpServerIp']);
134
135 29
        $validInput['smtpServerPort'] = $input->getOption('port');
136 29
        $this->validateInputServerPort($validInput['smtpServerPort']);
137
138 26
        $validInput['count'] = (int)$input->getOption('count');
139 26
        $this->validateInputCount($validInput['count']);
140
141 25
        $validInput['locale'] = $input->getOption('locale');
142
143 25
        $validInput['to'] = $this->validateInputToFrom($input->getOption('to'));
144
145 25
        $validInput['from'] = $this->validateInputToFrom($input->getOption('from'));
146
147 12
        return $validInput;
148
    }
149
150
    /**
151
     * @param string $ip
152
     * @throws \InvalidArgumentException
153
     */
154 31
    private function validateInputServerIP($ip)
155
    {
156 31
        if (!filter_var($ip, FILTER_VALIDATE_IP)) {
157 2
            throw new \InvalidArgumentException('server option is not a valid IP');
158
        }
159 29
    }
160
161
    /**
162
     * @param int $port
163
     * @throws \InvalidArgumentException
164
     */
165 29
    private function validateInputServerPort($port)
166
    {
167 29
        if (!is_numeric($port) || ($port < 0 || $port > 65535)) {
168 3
            throw new \InvalidArgumentException('server port must be a number between 0 and 65536');
169
        }
170 26
    }
171
172
    /**
173
     * @param int $count
174
     * @throws \InvalidArgumentException
175
     */
176 26
    private function validateInputCount($count)
177
    {
178 26
        if ($count < 1) {
179 1
            throw new \InvalidArgumentException('count must be equal or greater than 1 (you want to send email, right?)');
180
        }
181 25
    }
182
183
    /**
184
     * @param $string
185
     * @return string
186
     * @throws \InvalidArgumentException
187
     */
188 25
    private function validateInputToFrom($string)
189
    {
190 25
        if (null === $string) {
191 24
            return '';
192
        }
193
194 18
        $string = strtolower($string);
195 18
        if (strpos($string, '@') !== false) {
196 10
            if (filter_var($string, FILTER_VALIDATE_EMAIL)) {
197 3
                return $string;
198
            }
199
        } else {
200 8
            if ($this->filter_var_domain($string)) {
201 2
                return $string;
202
            }
203
        }
204
205 13
        throw new \InvalidArgumentException('to and from must be a valid email address or a FQDN');
206
    }
207
208
    /**
209
     * @param $domain
210
     * @return bool|mixed
211
     */
212 8
    private function filter_var_domain($domain)
213
    {
214 8
        $domain = strtolower($domain);
215 8
        $regex = "/^((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}$/";
216
217 8
        return preg_match($regex, $domain);
218
    }
219
}
220