AuthNegotiation   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 8
lcom 1
cbo 10
dl 0
loc 99
ccs 40
cts 40
cp 1
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B negotiate() 0 59 7
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Smtp\Negotiation;
5
6
use Genkgo\Mail\Exception\SmtpAuthenticationException;
7
use Genkgo\Mail\Protocol\Smtp\Client;
8
use Genkgo\Mail\Protocol\Smtp\NegotiationInterface;
9
use Genkgo\Mail\Protocol\Smtp\Request\AuthLoginCommand;
10
use Genkgo\Mail\Protocol\Smtp\Request\AuthLoginPasswordRequest;
11
use Genkgo\Mail\Protocol\Smtp\Request\AuthLoginUsernameRequest;
12
use Genkgo\Mail\Protocol\Smtp\Request\AuthPlainCommand;
13
use Genkgo\Mail\Protocol\Smtp\Request\AuthPlainCredentialsRequest;
14
use Genkgo\Mail\Protocol\Smtp\Request\EhloCommand;
15
use Genkgo\Mail\Protocol\Smtp\Response\EhloResponse;
16
17
final class AuthNegotiation implements NegotiationInterface
18
{
19
    /**
20
     * @var string
21
     */
22
    private $ehlo;
23
24
    /**
25
     * @var int
26
     */
27
    private $method;
28
29
    /**
30
     * @var string
31
     */
32
    private $username;
33
34
    /**
35
     * @var string
36
     */
37
    private $password;
38
39
    /**
40
     * @param int $method
41
     * @param string $username
42
     * @param string $password
43
     */
44 6
    public function __construct(string $ehlo, int $method, string $username, string $password)
45
    {
46 6
        $this->ehlo = $ehlo;
47 6
        $this->method = $method;
48 6
        $this->username = $username;
49 6
        $this->password = $password;
50 6
    }
51
52
    /**
53
     * @param Client $client
54
     * @throws SmtpAuthenticationException
55
     */
56 5
    public function negotiate(Client $client): void
57
    {
58 5
        $method = $this->method;
59 5
        if ($method === Client::AUTH_AUTO) {
60 2
            $reply = $client->request(new EhloCommand($this->ehlo));
61 2
            $reply->assertCompleted();
62
63 2
            $ehloResponse = new EhloResponse($reply);
64
65
            $options = [
66 2
                'AUTH PLAIN' => Client::AUTH_PLAIN,
67
                'AUTH LOGIN' => Client::AUTH_LOGIN
68
            ];
69
70 2
            foreach ($options as $capability => $auth) {
71 2
                if ($ehloResponse->isAdvertising($capability)) {
72 1
                    $method = $auth;
73
                }
74
            }
75
76 2
            if ($method === Client::AUTH_AUTO) {
77 1
                throw new SmtpAuthenticationException(
78 1
                    'SMTP server does not advertise one the supported AUTH methods (AUTH PLAIN / AUTH LOGIN)'
79
                );
80
            }
81
        }
82
83 4
        switch ($method) {
84
            case Client::AUTH_PLAIN:
85
                $client
86 2
                    ->request(new AuthPlainCommand())
87 2
                    ->assertIntermediate()
88 2
                    ->request(
89 2
                        new AuthPlainCredentialsRequest(
90 2
                            $this->username,
91 2
                            $this->password
92
                        )
93
                    )
94 2
                    ->assertCompleted();
95 2
                break;
96
            case Client::AUTH_LOGIN:
97
                $client
98 2
                    ->request(new AuthLoginCommand())
99 2
                    ->assertIntermediate()
100 2
                    ->request(
101 2
                        new AuthLoginUsernameRequest(
102 2
                            $this->username
103
                        )
104
                    )
105 2
                    ->assertIntermediate()
106 2
                    ->request(
107 2
                        new AuthLoginPasswordRequest(
108 2
                            $this->password
109
                        )
110
                    )
111 2
                    ->assertCompleted();
112 2
                break;
113
        }
114 4
    }
115
}
116