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

AuthNegotiation::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 3
crap 1
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 2
    public function __construct(int $method, string $username, string $password)
37
    {
38 2
        $this->method = $method;
39 2
        $this->username = $username;
40 2
        $this->password = $password;
41 2
    }
42
43
    /**
44
     * @param Client $client
45
     * @throws ImapAuthenticationException
46
     */
47 2
    public function negotiate(Client $client): void
48
    {
49 2
        $method = $this->method;
50 2
        if ($method === Client::AUTH_AUTO) {
51 1
            $responseList = $client->emit(new CapabilityCommand($client->newTag()));
52
53 1
            $capabilities = CapabilityCommandResponse::fromResponse($responseList->first());
54
55
            $responseList
56 1
                ->last()
57 1
                ->assertCompletion(CompletionResult::ok())
58 1
                ->assertTagged();
59
60
            $options = [
61 1
                'AUTH=PLAIN' => Client::AUTH_PLAIN,
62
            ];
63
64 1
            foreach ($options as $capability => $auth) {
65 1
                if ($capabilities->isAdvertising($capability)) {
66 1
                    $method = $auth;
67
                }
68
            }
69
70 1
            if ($method === Client::AUTH_AUTO) {
71
                throw new ImapAuthenticationException(
72
                    'IMAP server does not advertise one the supported AUTH methods (AUTH PLAIN)'
73
                );
74
            }
75
        }
76
77 2
        switch ($method) {
78
            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
}