Completed
Push — develop ( 11a7de )
by Manuel
02:39
created

SpammerCommand::getFromTo()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

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