Completed
Push — master ( 3a3e10...89e4e8 )
by Sebastian
08:48
created

Mail::setupMailer()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 10
cts 10
cp 1
rs 9.2728
c 0
b 0
f 0
cc 5
nc 5
nop 2
crap 5
1
<?php
2
namespace phpbu\App\Log;
3
4
use phpbu\App\Cli\Statistics;
5
use phpbu\App\Exception;
6
use phpbu\App\Event;
7
use phpbu\App\Listener;
8
use phpbu\App\Result;
9
use phpbu\App\Log\MailTemplate as TPL;
10
use phpbu\App\Util\Arr;
11
use phpbu\App\Util\Str;
12
use PHPMailer\PHPMailer\PHPMailer;
13
14
/**
15
 * Mail Logger
16
 *
17
 * @package    phpbu
18
 * @subpackage Log
19
 * @author     Sebastian Feldmann <[email protected]>
20
 * @copyright  Sebastian Feldmann <[email protected]>
21
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
22
 * @link       http://phpbu.de/
23
 * @since      Class available since Release 1.0.0
24
 */
25
class Mail implements Listener, Logger
26
{
27
    /**
28
     * Mailer instance
29
     *
30
     * @var \PHPMailer\PHPMailer\PHPMailer;
31
     */
32
    protected $mailer;
33
34
    /**
35
     * Mail subject
36
     *
37
     * @var string
38
     */
39
    protected $subject;
40
41
    /**
42
     * From email address
43
     *
44
     * @var string
45
     */
46
    protected $senderMail;
47
48
    /**
49
     * From name
50
     *
51
     * @var string
52
     */
53
    protected $senderName;
54
55
    /**
56
     * Transport type [mail|smtp|null]
57
     *
58
     * @var string
59
     */
60
    protected $transportType;
61
62
    /**
63
     * List of mail recipients
64
     *
65
     * @var array<string>
66
     */
67
    protected $recipients = [];
68
69
    /**
70
     * Amount of executed backups
71
     *
72
     * @var integer
73
     */
74
    private $numBackups = 0;
75
76
    /**
77
     * Amount of executed checks
78
     *
79
     * @var integer
80
     */
81
    private $numChecks = 0;
82
83
    /**
84
     * Amount of executed Syncs
85
     *
86
     * @var integer
87
     */
88
    private $numSyncs = 0;
89
90
    /**
91
     * Amount of executed Crypts
92
     *
93
     * @var integer
94
     */
95
    private $numCrypts = 0;
96
97
    /**
98
     * Amount of executed Cleanups
99
     *
100
     * @var integer
101
     */
102
    private $numCleanups = 0;
103
104
    /**
105
     * Send mail only if there was an error
106
     *
107
     * @var bool
108
     */
109
    private $sendOnlyOnError = false;
110
111
    /**
112
     * Send mails on simulation runs.
113
     *
114
     * @var bool
115
     */
116
    private $sendSimulating = true;
117
118
    /**
119
     * Is current execution a simulation.
120
     *
121
     * @var bool
122
     */
123
    private $isSimulation = false;
124
125
    /**
126
     * Returns an array of event names this subscriber wants to listen to.
127
     *
128
     * The array keys are event names and the value can be:
129
     *
130
     *  * The method name to call (priority defaults to 0)
131
     *  * An array composed of the method name to call and the priority
132
     *  * An array of arrays composed of the method names to call and respective
133
     *    priorities, or 0 if unset
134
     *
135
     * @return array The event names to listen to
136
     */
137
    public static function getSubscribedEvents()
138 1
    {
139
        return [
140
            'phpbu.backup_start'  => 'onBackupStart',
141 1
            'phpbu.check_start'   => 'onCheckStart',
142
            'phpbu.crypt_start'   => 'onCryptStart',
143
            'phpbu.sync_start'    => 'onSyncStart',
144
            'phpbu.cleanup_start' => 'onCleanupStart',
145
            'phpbu.app_end'       => 'onPhpbuEnd',
146
        ];
147
    }
148
149
    /**
150
     * Setup the Logger.
151
     *
152
     * @see    \phpbu\App\Log\Logger::setup
153
     * @param  array $options
154
     * @throws \phpbu\App\Exception
155
     */
156
    public function setup(array $options)
157 12
    {
158
        if (empty($options['recipients'])) {
159 12
            throw new Exception('no recipients given');
160 1
        }
161
        $mails                 = $options['recipients'];
162 11
        $server                = gethostname();
163 11
        $this->sendOnlyOnError = Str::toBoolean(Arr::getValue($options, 'sendOnlyOnError'), false);
164 11
        $this->sendSimulating  = Str::toBoolean(Arr::getValue($options, 'sendOnSimulation'), true);
165 11
        $this->subject         = Arr::getValue($options, 'subject', 'PHPBU backup report from ' . $server);
166 11
        $this->senderMail      = Arr::getValue($options, 'sender.mail', 'phpbu@' . $server);
167 11
        $this->senderName      = Arr::getValue($options, 'sender.name');
168 11
        $this->transportType   = Arr::getValue($options, 'transport', 'mail');
169 11
        $this->recipients      = array_map('trim', explode(';', $mails));
170 11
        $this->isSimulation    = Arr::getValue($options, '__simulate__', false);
171 11
172
        // create transport an mailer
173
        $this->mailer = new PHPMailer();
174 11
        $this->setupMailer($this->transportType, $options);
175 9
    }
176 9
177
    /**
178
     * Handle the phpbu end event.
179
     *
180
     * @param  \phpbu\App\Event\App\End $event
181
     * @throws \phpbu\App\Exception
182
     */
183
    public function onPhpbuEnd(Event\App\End $event)
184 4
    {
185
        $result = $event->getResult();
186 4
187
        if ($this->shouldMailBeSend($result)) {
188 4
            $header  = $this->getHeaderHtml();
189 4
            $status  = $this->getStatusHtml($result);
190 4
            $errors  = $this->getErrorHtml($result);
191 4
            $info    = $this->getInfoHtml($result);
192 4
            $footer  = $this->getFooterHtml();
193 4
            $body    = '<html><body ' . TPL::getSnippet('sBody') . '>'
194 4
                     . $header
195 4
                     . $status
196 4
                     . $errors
197 4
                     . $info
198 4
                     . $footer
199 4
                     . '</body></html>';
200 4
            $sent    = null;
0 ignored issues
show
Unused Code introduced by
$sent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
201 4
            $state   = $result->allOk() ? 'OK' : ($result->backupOkButSkipsOrFails() ? 'WARNING' : 'ERROR');
202 4
203
            $this->mailer->Subject = $this->subject . ' [' . $state . ']';
204
            $this->mailer->setFrom($this->senderMail, $this->senderName);
205
            $this->mailer->msgHTML($body);
206 4
207 4
            foreach ($this->recipients as $recipient) {
208 4
                $this->mailer->addAddress($recipient);
209 4
            }
210 4
211
            if (!$this->mailer->send()) {
212 4
                throw new Exception($this->mailer->ErrorInfo);
213
            }
214
        }
215
    }
216 4
217
    /**
218
     * Backup start event.
219
     *
220 4
     * @param \phpbu\App\Event\Backup\Start $event
221
     */
222
    public function onBackupStart(Event\Backup\Start $event)
223
    {
224
        $this->numBackups++;
225
    }
226
227 4
    /**
228
     * Check start event.
229 4
     *
230 4
     * @param \phpbu\App\Event\Check\Start $event
231
     */
232
    public function onCheckStart(Event\Check\Start $event)
233
    {
234
        $this->numChecks++;
235
    }
236
237 1
    /**
238
     * Crypt start event.
239 1
     *
240 1
     * @param \phpbu\App\Event\Crypt\Start $event
241
     */
242
    public function onCryptStart(Event\Crypt\Start $event)
243
    {
244
        $this->numCrypts++;
245
    }
246
247 1
    /**
248
     * Sync start event.
249 1
     *
250 1
     * @param \phpbu\App\Event\Sync\Start $event
251
     */
252
    public function onSyncStart(Event\Sync\Start $event)
253
    {
254
        $this->numSyncs++;
255
    }
256
257 1
    /**
258
     * Cleanup start event.
259 1
     *
260 1
     * @param \phpbu\App\Event\Cleanup\Start $event
261
     */
262
    public function onCleanupStart(Event\Cleanup\Start $event)
263
    {
264
        $this->numCleanups++;
265
    }
266
267 1
    /**
268
     * Configure PHPMailer
269 1
     *
270 1
     * @param  string                         $type
271
     * @param  array                          $options
272
     * @throws \phpbu\App\Exception
273
     */
274
    protected function setupMailer($type, array $options)
275
    {
276
        switch ($type) {
277
            case 'null':
278
                $this->isSimulation = true;
279
                break;
280 11
281
            case 'smtp':
282 11
                $this->setupSmtpMailer($options);
283
                break;
284 11
285
            case 'mail':
286 4
            case 'sendmail':
287 4
                $this->setupSendmailMailer($options);
288
                break;
289 7
290 2
            // UPS! no transport given
291 1
            default:
292
                throw new Exception(sprintf('mail transport not supported: \'%s\'', $type));
293 5
        }
294 3
    }
295 4
296 4
    /**
297
     * Should a mail be send
298
     *
299
     * @param  \phpbu\App\Result $result
300 1
     * @return bool
301
     */
302 9
    protected function shouldMailBeSend(Result $result) : bool
303
    {
304
        // send mails if
305
        // there is an error or send error only is inactive
306
        // and
307
        // simulation settings do not prevent sending
308
        return (!$this->sendOnlyOnError || !$result->allOk()) && ($this->sendSimulating || !$this->isSimulation);
309
    }
310
311 4
    /**
312
     * Setup smtp mailing
313
     *
314
     * @param  array $options
315
     * @return void
316
     * @throws \phpbu\App\Exception
317 4
     */
318
    protected function setupSmtpMailer(array $options)
319
    {
320
        if (!isset($options['smtp.host'])) {
321
            throw new Exception('option \'smtp.host\' ist missing');
322
        }
323
        $host       = $options['smtp.host'];
324
        $port       = Arr::getValue($options, 'smtp.port', 25);
325
        $username   = Arr::getValue($options, 'smtp.username');
326
        $password   = Arr::getValue($options, 'smtp.password');
327 2
        $encryption = Arr::getValue($options, 'smtp.encryption');
328
329 2
        $this->mailer->isSMTP();
330 1
        $this->mailer->Host     = $host;
331
        $this->mailer->Port     = $port;
332 1
333 1
        if ($username && $password) {
334 1
            $this->mailer->SMTPAuth = true;
335 1
            $this->mailer->Username = $username;
336 1
            $this->mailer->Password = $password;
337
        }
338
        if ($encryption) {
339 1
            $this->mailer->SMTPSecure = $encryption;
340
        }
341 1
    }
342 1
343 1
    /**
344
     * Setup the php mail transport
345 1
     *
346 1
     * @param  array $options
347
     * @return void
348 1
     */
349
    protected function setupSendmailMailer(array $options)
350
    {
351
        // nothing to do here
352
    }
353
354
    /**
355
     * Return mail header html
356
     *
357 4
     * @return string
358
     * @throws \phpbu\App\Exception
359 4
     */
360 1
    protected function getHeaderHtml()
361 1
    {
362
        return '<table ' . TPL::getSnippet('sTableContent') . '><tr><td ' . TPL::getSnippet('sTableContentCol') . '>' .
363 1
               '<table ' . TPL::getSnippet('sTableHeader') . '><tr><td>PHPBU - backup report</td></tr></table>';
364
    }
365 3
366
    /**
367
     * Return mail status html
368
     *
369
     * @param  \phpbu\App\Result $result
370
     * @return string
371
     * @throws \phpbu\App\Exception
372
     */
373 4
    protected function getStatusHtml(Result $result)
374
    {
375 4
        if (count($result->getBackups()) === 0) {
376 4
            $color  = TPL::getSnippet('cStatusWARN');
377
            $status = 'WARNING';
378
        } elseif ($result->allOk()) {
379
            $color  = TPL::getSnippet('cStatusOK');
380
            $status = 'OK';
381
        } elseif ($result->backupOkButSkipsOrFails()) {
382
            $color  = TPL::getSnippet('cStatusWARN');
383
            $status = 'WARNING';
384
        } else {
385 4
            $color  = TPL::getSnippet('cStatusFAIL');
386
            $status = 'FAILURE';
387 4
        }
388 1
        $info = sprintf(
389 1
            '(%d %s, %d %s, %d %s, %d %s, %d %s)',
390 3
            count($result->getBackups()),
391 1
            Str::appendPluralS('backup', count($result->getBackups())),
392 1
            $this->numChecks,
393 2
            Str::appendPluralS('check', $this->numChecks),
394 1
            $this->numCrypts,
395 1
            Str::appendPluralS('crypt', $this->numCrypts),
396
            $this->numSyncs,
397 1
            Str::appendPluralS('sync', $this->numSyncs),
398 1
            $this->numCleanups,
399
            Str::appendPluralS('cleanup', $this->numCleanups)
400 4
        );
401 4
        $html = '<table ' . sprintf(TPL::getSnippet('sTableStatus'), $color) . '>' .
402 4
                 '<tr><td>' .
403 4
                  '<span ' . TPL::getSnippet('sTableStatusText') . '>' . date('Y-m-d H:i') . '</span>' .
404 4
                  '<h1 ' . TPL::getSnippet('sTableStatusHead') . '>' . $status . '</h1>' .
405 4
                  '<span ' . TPL::getSnippet('sTableStatusText') . '>' . $info . '</span>' .
406 4
                 '</td></tr>' .
407 4
                '</table>';
408 4
409 4
        return $html;
410 4
    }
411 4
412
    /**
413 4
     * Get error information
414 4
     *
415 4
     * @param  \phpbu\App\Result $result
416 4
     * @return string
417 4
     * @throws \phpbu\App\Exception
418 4
     */
419 4
    protected function getErrorHtml(Result $result)
420
    {
421 4
        $html   = '';
422
        $errors = $result->getErrors();
423
        if (count($errors)) {
424
            $html .= '<table ' . TPL::getSnippet('sTableError') . '>';
425
            /* @var $e Exception */
426
            foreach ($errors as $e) {
427
                $html .= '<tr><td ' . TPL::getSnippet('sTableErrorCol') . '>' .
428
                    sprintf(
429
                        "Exception '%s' with message '%s' in %s:%d",
430 4
                        get_class($e),
431
                        $e->getMessage(),
432 4
                        $e->getFile(),
433 4
                        $e->getLine()
434 4
                    ) .
435 1
                    '</td></tr>';
436
437 1
            }
438 1
            $html .= '</table>';
439 1
        }
440 1
        return $html;
441 1
    }
442 1
443 1
    /**
444 1
     * Return backup html information
445
     *
446 1
     * @param  \phpbu\App\Result $result
447
     * @return string
448
     * @throws \phpbu\App\Exception
449 1
     */
450
    protected function getInfoHtml(Result $result)
451 4
    {
452
        $html    = '';
453
        $backups = $result->getBackups();
454
        if (count($backups)) {
455
            $html .= '<table ' . TPL::getSnippet('sTableBackup') . '>';
456
            /** @var \phpbu\App\Result\Backup $backup */
457
            foreach ($backups as $backup) {
458
                if ($backup->allOk()) {
459
                    $color  = TPL::getSnippet('cStatusOK');
460 4
                    $status = 'OK';
461
                } elseif ($backup->okButSkipsOrFails()) {
462 4
                    $color  = TPL::getSnippet('cStatusWARN');
463 4
                    $status = 'WARNING';
464 4
                } else {
465 3
                    $color  = TPL::getSnippet('cStatusFAIL');
466
                    $status = 'FAILURE';
467 3
                }
468 3
                $html .= '<tr>' .
469 1
                          '<td ' . sprintf(TPL::getSnippet('sTableBackupStatusColumn'), $color) . ' colspan="4">' .
470 1
                          sprintf('backup <em>%s</em>', $backup->getName()) .
471 2
                          ' <span ' . TPL::getSnippet('sTableBackupStatusText') . '>' . $status . '</span>' .
472 1
                          '</td>' .
473 1
                         '</tr>' .
474
                         '<tr>' .
475 1
                          '<td ' . TPL::getSnippet('sRowHead') . '>&nbsp;</td>' .
476 1
                          '<td ' . TPL::getSnippet('sRowHead') . ' align="right">executed</td>' .
477
                          '<td ' . TPL::getSnippet('sRowHead') . ' align="right">skipped</td>' .
478
                          '<td ' . TPL::getSnippet('sRowHead') . ' align="right">failed</td>' .
479 3
                         '</tr>';
480 3
481 3
                $html .= '<tr>' .
482 3
                          '<td ' . TPL::getSnippet('sRowCheck') . '>checks</td>' .
483 3
                          '<td ' . TPL::getSnippet('sRowCheck') . ' align="right">' .
484 3
                            $backup->checkCount() . '
485 3
                           </td>' .
486 3
                          '<td ' . TPL::getSnippet('sRowCheck') . ' align="right">
487 3
                            &nbsp;
488 3
                           </td>' .
489 3
                          '<td ' . TPL::getSnippet('sRowCheck') . ' align="right">' .
490
                            $backup->checkCountFailed() .
491
                          '</td>' .
492 3
                         '</tr>' .
493 3
                         '<tr>' .
494 3
                          '<td ' . TPL::getSnippet('sRowCrypt') . '>crypts</td>' .
495
                          '<td ' . TPL::getSnippet('sRowCrypt') . ' align="right">' .
496 3
                            $backup->cryptCount() .
497
                          '</td>' .
498
                          '<td ' . TPL::getSnippet('sRowCrypt') . ' align="right">' .
499 3
                            $backup->cryptCountSkipped() .
500 3
                          '</td>' .
501 3
                          '<td ' . TPL::getSnippet('sRowCrypt') . ' align="right">' .
502 3
                            $backup->cryptCountFailed() .
503 3
                          '</td>' .
504 3
                         '</tr>' .
505 3
                         '<tr>' .
506 3
                          '<td ' . TPL::getSnippet('sRowSync') . '>syncs</td>' .
507 3
                          '<td ' . TPL::getSnippet('sRowSync') . ' align="right">' .
508 3
                            $backup->syncCount() . '</td>' .
509 3
                          '<td ' . TPL::getSnippet('sRowSync') . ' align="right">' .
510 3
                            $backup->syncCountSkipped() .
511 3
                          '</td>' .
512 3
                          '<td ' . TPL::getSnippet('sRowSync') . ' align="right">' .
513 3
                            $backup->syncCountFailed() .
514 3
                          '</td>' .
515 3
                         '</tr>' .
516 3
                         '<tr>' .
517 3
                          '<td ' . TPL::getSnippet('sRowCleanup') . '>cleanups</td>' .
518 3
                          '<td ' . TPL::getSnippet('sRowCleanup') . ' align="right">' .
519 3
                            $backup->cleanupCount() .
520 3
                          '</td>' .
521 3
                          '<td ' . TPL::getSnippet('sRowCleanup') . ' align="right">' .
522 3
                            $backup->cleanupCountSkipped() .
523 3
                          '</td>' .
524 3
                          '<td ' . TPL::getSnippet('sRowCleanup') . ' align="right">' .
525 3
                            $backup->cleanupCountFailed() .
526 3
                          '</td>' .
527 3
                         '</tr>';
528 3
529 3
            }
530 3
            $html .= '</table>';
531 3
        }
532 3
        return $html;
533 3
    }
534 3
535 3
    /**
536 3
     * Return mail body footer
537 3
     *
538
     * @return string
539
     * @throws \phpbu\App\Exception
540 3
     */
541
    protected function getFooterHtml()
542 4
    {
543
        return '<p ' . TPL::getSnippet('sStats') . '>' . Statistics::resourceUsage() . '</p>' .
544
               '</td></tr></table>';
545
    }
546
}
547