Completed
Pull Request — master (#42)
by Frederik
02:56
created

ForceTlsUpgradeNegotiation::negotiate()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 31
c 0
b 0
f 0
ccs 0
cts 25
cp 0
rs 8.5806
cc 4
eloc 19
nc 5
nop 1
crap 20
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Imap\Negotiation;
5
6
use Genkgo\Mail\Exception\ConnectionInsecureException;
7
use Genkgo\Mail\Protocol\ConnectionInterface;
8
use Genkgo\Mail\Protocol\Imap\Client;
9
use Genkgo\Mail\Protocol\Imap\NegotiationInterface;
10
use Genkgo\Mail\Protocol\Imap\Request\CapabilityCommand;
11
use Genkgo\Mail\Protocol\Imap\Request\StartTlsCommand;
12
use Genkgo\Mail\Protocol\Imap\Response\Command\CapabilityCommandResponse;
13
use Genkgo\Mail\Protocol\Imap\Response\CompletionResult;
14
15
final class ForceTlsUpgradeNegotiation implements NegotiationInterface
16
{
17
    /**
18
     * @var ConnectionInterface
19
     */
20
    private $connection;
21
    /**
22
     * @var int
23
     */
24
    private $crypto;
25
26
    /**
27
     * ConnectionNegotiation constructor.
28
     * @param ConnectionInterface $connection
29
     * @param int $crypto
30
     */
31
    public function __construct(
32
        ConnectionInterface $connection,
33
        int $crypto
34
    ) {
35
        $this->connection = $connection;
36
        $this->crypto = $crypto;
37
    }
38
39
40
    /**
41
     * @param Client $client
42
     * @throws ConnectionInsecureException
43
     */
44
    public function negotiate(Client $client): void
45
    {
46
        if (!empty($this->connection->getMetaData(['crypto']))) {
47
            return;
48
        }
49
50
        $responseList = $client->emit(new CapabilityCommand($client->newTag()));
51
52
        $capabilities = CapabilityCommandResponse::fromResponse($responseList->first());
53
54
        $responseList
55
            ->last()
56
            ->assertCompletion(CompletionResult::ok())
57
            ->assertTagged();
58
59
        if ($capabilities->isAdvertising('STARTTLS')) {
60
            $client
61
                ->emit(new StartTlsCommand($client->newTag()))
62
                ->last()
63
                ->assertCompletion(CompletionResult::ok())
64
                ->assertTagged();
65
66
            $this->connection->upgrade($this->crypto);
67
        }
68
69
        if (empty($this->connection->getMetaData(['crypto']))) {
70
            throw new ConnectionInsecureException(
71
                'Server does not support STARTTLS. Use imaps:// or to allow insecure connections use imap-starttls://'
72
            );
73
        }
74
    }
75
}