DataCapability::manifest()   B
last analyzed

Complexity

Conditions 9
Paths 21

Size

Total Lines 50

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 9

Importance

Changes 0
Metric Value
dl 0
loc 50
ccs 28
cts 28
cp 1
rs 7.5353
c 0
b 0
f 0
cc 9
nc 21
nop 2
crap 9
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Smtp\Capability;
5
6
use Genkgo\Mail\GenericMessage;
7
use Genkgo\Mail\Protocol\ConnectionInterface;
8
use Genkgo\Mail\Protocol\Smtp\BackendInterface;
9
use Genkgo\Mail\Protocol\Smtp\CapabilityInterface;
10
use Genkgo\Mail\Protocol\Smtp\GreyListInterface;
11
use Genkgo\Mail\Protocol\Smtp\Session;
12
use Genkgo\Mail\Protocol\Smtp\SpamDecideScore;
13
use Genkgo\Mail\Protocol\Smtp\SpamScoreInterface;
14
15
final class DataCapability implements CapabilityInterface
16
{
17
    /**
18
     * @var BackendInterface
19
     */
20
    private $backend;
21
22
    /**
23
     * @var SpamScoreInterface
24
     */
25
    private $spamScore;
26
27
    /**
28
     * @var SpamDecideScore
29
     */
30
    private $spamDecideScore;
31
32
    /**
33
     * @var GreyListInterface
34
     */
35
    private $greyListing;
36
37
    /**
38
     * @param BackendInterface $backend
39
     * @param SpamScoreInterface $spamScore
40
     * @param GreyListInterface $greyListing
41
     * @param SpamDecideScore $spamDecideScore
42
     */
43 6
    public function __construct(
44
        BackendInterface $backend,
45
        SpamScoreInterface $spamScore,
46
        GreyListInterface $greyListing,
47
        SpamDecideScore $spamDecideScore
48
    ) {
49 6
        $this->backend = $backend;
50 6
        $this->spamScore = $spamScore;
51 6
        $this->spamDecideScore = $spamDecideScore;
52 6
        $this->greyListing = $greyListing;
53 6
    }
54
55
    /**
56
     * @param ConnectionInterface $connection
57
     * @param Session $session
58
     * @return Session
59
     */
60 5
    public function manifest(ConnectionInterface $connection, Session $session): Session
61
    {
62 5
        $connection->send('354 Enter message, ending with "." on a line by itself');
63 5
        $data = [];
64
65 5
        while (true) {
66 5
            $line = $connection->receive();
67
68 5
            if ($line === '.') {
69 5
                break;
70
            }
71
72 5
            $data[] = $line;
73
        }
74
75
        try {
76 5
            $message = GenericMessage::fromString(\implode("\r\n", $data));
77 1
        } catch (\InvalidArgumentException $e) {
78 1
            $connection->send('500 Malformed message');
79 1
            return $session;
80
        }
81
82 4
        $spamScore = $this->spamScore->calculate($message);
83
84 4
        if ($this->spamDecideScore->isSpam($spamScore)) {
85 1
            $connection->send('550 Message discarded as high-probability spam');
86 1
            return $session;
87
        }
88
89 3
        if ($this->spamDecideScore->isLikelySpam($spamScore) && !$this->greyListing->contains($message)) {
90 2
            $this->greyListing->attach($message);
91 2
            $connection->send('421 Please try again later');
92 2
            return $session;
93
        }
94
95 2
        $this->greyListing->detach($message);
96
97 2
        $folder = 'INBOX';
98
99 2
        if ($this->spamDecideScore->isLikelySpam($spamScore)) {
100 1
            $folder = 'JUNK';
101
        }
102
103 2
        foreach ($session->getRecipients() as $recipient) {
104 1
            $this->backend->store($recipient, $message, $folder);
105
        }
106
107 2
        $connection->send('250 Message received, queue for delivering');
108 2
        return $session->withMessage($message);
109
    }
110
111
    /**
112
     * @return string
113
     */
114 1
    public function advertise(): string
115
    {
116 1
        return 'DATA';
117
    }
118
}
119