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

AuthNegotiation::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
ccs 0
cts 6
cp 0
rs 9.4285
cc 1
eloc 4
nc 1
nop 3
crap 2
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
    public function __construct(int $method, string $username, string $password)
37
    {
38
        $this->method = $method;
39
        $this->username = $username;
40
        $this->password = $password;
41
    }
42
43
    /**
44
     * @param Client $client
45
     * @throws ImapAuthenticationException
46
     */
47
    public function negotiate(Client $client): void
48
    {
49
        $method = $this->method;
50
        if ($method === Client::AUTH_AUTO) {
51
            $responseList = $client->emit(new CapabilityCommand($client->newTag()));
52
53
            $capabilities = CapabilityCommandResponse::fromResponse($responseList->first());
54
55
            $responseList
56
                ->last()
57
                ->assertCompletion(CompletionResult::ok())
58
                ->assertTagged();
59
60
            $options = [
61
                'AUTH=PLAIN' => Client::AUTH_PLAIN,
62
            ];
63
64
            foreach ($options as $capability => $auth) {
65
                if ($capabilities->isAdvertising($capability)) {
66
                    $method = $auth;
67
                }
68
            }
69
70
            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
        switch ($method) {
78
            case Client::AUTH_PLAIN:
79
                $tag = $client->newTag();
80
                $client
81
                    ->emit(new AuthPlainCommand($tag))
82
                    ->first()
83
                    ->assertContinuation();
84
85
                $client
86
                    ->emit(
87
                        new AuthPlainCredentialsRequest(
88
                            $tag,
89
                            $this->username,
90
                            $this->password
91
                        )
92
                    )
93
                    ->last()
94
                    ->assertCompletion(CompletionResult::ok())
95
                    ->assertTagged();
96
                break;
97
        }
98
    }
99
}