Completed
Push — master ( b92a49...e8f5e1 )
by Rasmus
12:47 queued 09:15
created

SMTPMailService::send()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 12
ccs 10
cts 10
cp 1
rs 9.4285
cc 1
eloc 7
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Kodus\Mail\SMTP;
4
5
use Kodus\Mail\MailService;
6
use Kodus\Mail\Message;
7
use Kodus\Mail\MIMEWriter;
8
9
/**
10
 * This Mail Service implementation delivers Messages directly to an SMTP server.
11
 *
12
 * It will block the script while connecting and delivering the Message.
13
 */
14
class SMTPMailService implements MailService
15
{
16
    /**
17
     * @var SMTPAuthenticator
18
     */
19
    protected $authenticator;
20
21
    /**
22
     * @var string
23
     */
24
    protected $client_domain;
25
26
    /**
27
     * @var SMTPConnector
28
     */
29
    private $connector;
30
31
    /**
32
     * @var SMTPClient|null
33
     */
34
    private $client;
35
36
    /**
37
     * @param SMTPConnector     $connector     provides the SMTP connection
38
     * @param SMTPAuthenticator $authenticator performs SMTP authentication
39
     * @param string            $client_domain client domain-name (provided in handshakes when connecting)
40
     */
41 1
    public function __construct(SMTPConnector $connector, SMTPAuthenticator $authenticator, $client_domain)
42
    {
43 1
        $this->connector = $connector;
44 1
        $this->authenticator = $authenticator;
45 1
        $this->client_domain = $client_domain;
46 1
    }
47
48 1
    public function send(Message $message)
49
    {
50 1
        $this->getClient()->sendMail(
51 1
            $this->getSender($message),
52 1
            $this->getRecipients($message),
53 1
            function ($socket) use ($message) {
54 1
                $writer = new MIMEWriter($socket);
55
56 1
                $writer->writeMessage($message);
57 1
            }
58 1
        );
59 1
    }
60
61
    /**
62
     * Internally disconnect the SMTP Client.
63
     *
64
     * Long-running services may wish to disconnect the SMTP client after sending a batch
65
     * of Messages, to avoid timeouts.
66
     *
67
     * @return void
68
     */
69
    public function disconnect()
70
    {
71
        // NOTE: this will cause the SMTP Client instance will fall out of scope, which
72
        //       will trigger it's destructor, which will send QUIT and close the socket.
73
74
        $this->client = null;
75
    }
76
77
    /**
78
     * Connect and authenticate SMTP Client (if not already connected)
79
     *
80
     * @return SMTPClient
81
     */
82 1
    protected function getClient()
83
    {
84 1
        if (! isset($this->client)) {
85 1
            $this->client = $this->connector->connect($this->client_domain);
86
87 1
            $this->authenticator->authenticate($this->client);
88 1
        }
89
90 1
        return $this->client;
91
    }
92
93
    /**
94
     * Determine the sender e-mail address from the "Sender" or first "From" field of the Message
95
     *
96
     * @param Message $message
97
     *
98
     * @return string sender e-mail address
99
     */
100 1
    private function getSender(Message $message)
101
    {
102 1
        $sender = $message->getSender();
103
104 1
        if ($sender) {
105 1
            return $sender->getEmail();
106
        }
107
108 1
        $from = $message->getFrom();
109
110 1
        return $from[0]->getEmail();
111
    }
112
113
    /**
114
     * Extract recipient e-mail addresses from the "To", "CC" and "BCC" fields of the Message
115
     *
116
     * @param Message $message
117
     *
118
     * @return string[] list of recipient e-mail addresses
119
     */
120 1
    private function getRecipients(Message $message)
121
    {
122 1
        $recipients = [];
123
124 1
        foreach ($message->getTo() as $recipient) {
0 ignored issues
show
Bug introduced by
The expression $message->getTo() of type object<Kodus\Mail\Addres...ct<Kodus\Mail\Address>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
125 1
            $recipients[] = $recipient->getEmail();
126 1
        }
127
128 1
        foreach ($message->getCC() as $recipient) {
0 ignored issues
show
Bug introduced by
The expression $message->getCC() of type object<Kodus\Mail\Addres...ct<Kodus\Mail\Address>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
129 1
            $recipients[] = $recipient->getEmail();
130 1
        }
131
132 1
        foreach ($message->getBCC() as $recipient) {
0 ignored issues
show
Bug introduced by
The expression $message->getBCC() of type object<Kodus\Mail\Addres...ct<Kodus\Mail\Address>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
133 1
            $recipients[] = $recipient->getEmail();
134 1
        }
135
136 1
        return $recipients;
137
    }
138
}
139