Completed
Pull Request — master (#42)
by Frederik
01:59
created

AuthNegotiation   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 9
dl 0
loc 85
ccs 35
cts 35
cp 1
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B negotiate() 0 52 6
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Imap\Negotiation;
5
6
use Genkgo\Mail\Exception\ImapAuthenticationException;
7
use Genkgo\Mail\Protocol\Imap\Client;
8
use Genkgo\Mail\Protocol\Imap\NegotiationInterface;
9
use Genkgo\Mail\Protocol\Imap\Request\AuthPlainCommand;
10
use Genkgo\Mail\Protocol\Imap\Request\AuthPlainCredentialsRequest;
11
use Genkgo\Mail\Protocol\Imap\Request\CapabilityCommand;
12
use Genkgo\Mail\Protocol\Imap\Response\Command\CapabilityCommandResponse;
13
use Genkgo\Mail\Protocol\Imap\Response\CompletionResult;
14
15
final class AuthNegotiation implements NegotiationInterface
16
{
17
    /**
18
     * @var int
19
     */
20
    private $method;
21
    /**
22
     * @var string
23
     */
24
    private $username;
25
    /**
26
     * @var string
27
     */
28
    private $password;
29
30
    /**
31
     * AuthNegotiation constructor.
32
     * @param int $method
33
     * @param string $username
34
     * @param string $password
35
     */
36 3
    public function __construct(int $method, string $username, string $password)
37
    {
38 3
        $this->method = $method;
39 3
        $this->username = $username;
40 3
        $this->password = $password;
41 3
    }
42
43
    /**
44
     * @param Client $client
45
     * @throws ImapAuthenticationException
46
     */
47 3
    public function negotiate(Client $client): void
48
    {
49 3
        $method = $this->method;
50 3
        if ($method === Client::AUTH_AUTO) {
51 2
            $responseList = $client->emit(new CapabilityCommand($client->newTag()));
52
53 2
            $capabilities = CapabilityCommandResponse::fromString($responseList->first()->getBody());
54
55
            $responseList
56 2
                ->last()
57 2
                ->assertCompletion(CompletionResult::ok())
58 2
                ->assertTagged();
59
60
            $options = [
61 2
                'AUTH=PLAIN' => Client::AUTH_PLAIN,
62
            ];
63
64 2
            foreach ($options as $capability => $auth) {
65 2
                if ($capabilities->isAdvertising($capability)) {
66 2
                    $method = $auth;
67
                }
68
            }
69
70 2
            if ($method === Client::AUTH_AUTO) {
71 1
                throw new ImapAuthenticationException(
72 1
                    'IMAP server does not advertise one the supported AUTH methods (AUTH PLAIN)'
73
                );
74
            }
75
        }
76
77
        switch ($method) {
78 2
            case Client::AUTH_PLAIN:
79 2
                $tag = $client->newTag();
80
                $client
81 2
                    ->emit(new AuthPlainCommand($tag))
82 2
                    ->first()
83 2
                    ->assertContinuation();
84
85
                $client
86 2
                    ->emit(
87 2
                        new AuthPlainCredentialsRequest(
88 2
                            $tag,
89 2
                            $this->username,
90 2
                            $this->password
91
                        )
92
                    )
93 2
                    ->last()
94 2
                    ->assertCompletion(CompletionResult::ok())
95 2
                    ->assertTagged();
96 2
                break;
97
        }
98
    }
99
}