Completed
Push — master ( 503b9d...92f54d )
by Frederik
03:38
created

AuthNegotiation   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 8
lcom 1
cbo 9
dl 0
loc 94
rs 10
c 0
b 0
f 0
ccs 41
cts 41
cp 1

2 Methods

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