Mailgun::send()   F
last analyzed

Complexity

Conditions 21
Paths > 20000

Size

Total Lines 80
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 63.9251

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 21
eloc 50
nc 53150
nop 1
dl 0
loc 80
ccs 27
cts 50
cp 0.54
crap 63.9251
rs 0
c 3
b 1
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Omnimail;
4
5
use Http\Client\HttpClient;
6
use Mailgun\Messages\Exceptions\InvalidParameter;
7
use Mailgun\Messages\MessageBuilder;
8
use Omnimail\Exception\EmailDeliveryException;
9
use Omnimail\Exception\Exception;
10
use Omnimail\Exception\InvalidRequestException;
11
use Omnimail\Exception\UnauthorizedException;
12
use Psr\Log\LoggerInterface;
13
use Mailgun\Mailgun as MailgunAPI;
14
15
class Mailgun implements MailerInterface
16
{
17
    protected $apiKey;
18
    protected $domain;
19
    protected $mailgun;
20
    protected $logger;
21
    protected $httpClient;
22
    protected $tmpfiles = [];
23
24
    /**
25
     * @param string $apiKey
26
     * @param string $domain
27
     * @param LoggerInterface|null $logger
28
     * @param HttpClient $httpClient
29
     */
30
    public function __construct(
31
        $apiKey = null,
32
        $domain = null,
33
        LoggerInterface $logger = null,
34 1
        HttpClient $httpClient = null
35
    ) {
36 1
        $this->apiKey = $apiKey;
37
        $this->domain = $domain;
38
        $this->logger = $logger;
39 1
        $this->httpClient = $httpClient;
40
        $this->mailgun = new MailgunAPI($this->apiKey, $this->httpClient);
41 1
    }
42 1
43
    public function getApiKey()
44
    {
45
        return $this->apiKey;
46
    }
47
48
    public function setApiKey($apiKey)
49
    {
50
        $this->apiKey = $apiKey;
51
        $this->mailgun = new MailgunAPI($this->apiKey, $this->httpClient);
52
    }
53
54
    public function getDomain()
55
    {
56
        return $this->domain;
57
    }
58
59
    public function setDomain($domain)
60
    {
61
        $this->domain = $domain;
62
    }
63
64
    public function getLogger()
65
    {
66
        return $this->logger;
67
    }
68
69
    public function setLogger($logger)
70
    {
71 4
        $this->logger = $logger;
72
    }
73 4
74 4
    public function getHttpClient()
75 4
    {
76 4
        return $this->httpClient;
77 4
    }
78 4
79
    public function setHttpClient($httpClient)
80 2
    {
81
        $this->httpClient = $httpClient;
82
        $this->mailgun = new MailgunAPI($this->apiKey, $this->httpClient);
83 2
    }
84
85 2
    /**
86 2
     * @param EmailInterface $email
87 2
     * @throws EmailDeliveryException
88
     * @throws Exception
89
     * @throws InvalidRequestException
90
     * @throws UnauthorizedException
91 2
     */
92
    public function send(EmailInterface $email)
93 2
    {
94
        try {
95
            $builder = $this->mailgun->MessageBuilder();
0 ignored issues
show
Deprecated Code introduced by
The function Mailgun\Mailgun::MessageBuilder() has been deprecated: Will be removed in 3.0. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

95
            $builder = /** @scrutinizer ignore-deprecated */ $this->mailgun->MessageBuilder();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
96
97 2
            if ($email->getTos()) {
98
                foreach ($email->getTos() as $recipient) {
99
                    $builder->addToRecipient($this->mapEmails($email->getTos()));
100
                }
101
            }
102
103 2
            $builder->setFromAddress($this->mapEmail($email->getFrom()));
104
105
            if ($email->getReplyTos()) {
106
                $builder->setReplyToAddress($this->mapEmails($email->getReplyTos()));
107
            }
108
109 2
            if ($email->getCcs()) {
110 2
                foreach ($email->getCcs() as $recipient) {
111
                    $builder->addCcRecipient($this->mapEmail($recipient));
112
                }
113 2
            }
114 2
115
            if ($email->getBccs()) {
116
                foreach ($email->getBccs() as $recipient) {
117 2
                    $builder->addBccRecipient($this->mapEmail($recipient));
118
                }
119
            }
120
121 2
            if ($email->getSubject()) {
122
                $builder->setSubject($email->getSubject());
123
            }
124
125
            if ($email->getTextBody()) {
126 2
                $builder->setTextBody($email->getTextBody());
127 2
            }
128 2
129 2
            if ($email->getHtmlBody()) {
130
                $builder->setHtmlBody($email->getHtmlBody());
131
            }
132 1
133 1
            if ($email->getAttachments()) {
134 1
                $this->mapAttachments($email->getAttachments(), $builder);
135
                $this->mapInlineAttachments($email->getAttachments(), $builder);
136
            }
137
138
            $result = $this->mailgun->post(
0 ignored issues
show
Deprecated Code introduced by
The function Mailgun\Mailgun::post() has been deprecated: Will be removed in 3.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

138
            $result = /** @scrutinizer ignore-deprecated */ $this->mailgun->post(

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
139
                "{$this->domain}/messages",
140
                $builder->getMessage(),
141
                $builder->getFiles()
142
            );
143
144
            switch ($result->http_response_code) {
145 1
                case 200:
146 1
                    break;
147
                case 400:
148 1
                    throw new InvalidRequestException;
149
                case 401:
150
                    throw new UnauthorizedException;
151
                case 402:
152
                    throw new EmailDeliveryException;
153 1
                default:
154 1
                    throw new Exception('Unknown error', 603);
155
            }
156
157 1
            if ($this->logger) {
158 1
                $this->logger->info("Email sent: '{$email->getSubject()}'", $email->toArray());
159 2
            }
160
        } catch (Exception $e) {
161 1
            if ($this->logger) {
162
                $this->logger->error("Email error: '{$e->getMessage()}'", $email->toArray());
163
            }
164
            throw $e;
165
        } catch (\Exception $e) {
166
            if ($this->logger) {
167
                $this->logger->error("Email error: '{$e->getMessage()}'", $email->toArray());
168 2
            }
169
            throw new Exception($e->getMessage(), $e->getCode(), $e);
170 2
        } finally {
171
            $this->removeTmpfiles();
172
        }
173 2
    }
174
175
    /**
176
     * @param array $emails
177
     * @return string
178
     */
179
    private function mapEmails(array $emails)
180
    {
181
        $returnValue = '';
182
        foreach ($emails as $email) {
183
            $returnValue .= $this->mapEmail($email) . ', ';
184
        }
185
        return $returnValue ? substr($returnValue, 0, -2) : '';
186
    }
187
188
    /**
189
     * @param array $email
190
     * @return string
191
     */
192
    private function mapEmail(array $email)
193
    {
194
        return !empty($email['name']) ? "'{$email['name']}' <{$email['email']}>" : $email['email'];
195
    }
196
197
    /**
198
     * @param AttachmentInterface[]|array|null $attachments
199
     * @param MessageBuilder $builder
200
     * @return array|null
201
     */
202
    private function mapAttachments(array $attachments, MessageBuilder $builder)
203
    {
204
        foreach ($attachments as $attachment) {
205
            if ($attachment->getContentId()) {
206
                continue;
207
            }
208
209
            if ($attachment->getPath()) {
210
                $file = $attachment->getPath();
211
            } elseif ($attachment->getContent()) {
212
                $this->addTmpfile($file = tmpfile());
213
                fwrite($file, $attachment->getContent());
214
            } else {
215
                continue;
216
            }
217
            $builder->addAttachment($file, $attachment->getName());
218
        }
219
220
        return null;
221
    }
222
223
    private function addTmpfile($file)
224
    {
225
        $this->tmpfiles[] = $file;
226
    }
227 2
228
    /**
229 2
     * @param AttachmentInterface[]|array|null $attachments
230 2
     * @param MessageBuilder $builder
231 2
     * @return void
232
     * @throws InvalidParameter
233 2
     */
234
    private function mapInlineAttachments(array $attachments, MessageBuilder $builder)
235
    {
236
        foreach ($attachments as $attachment) {
237
            if (!$attachment->getContentId()) {
238
                continue;
239
            }
240 2
241
            if ($attachment->getPath()) {
242 2
                $file = $attachment->getPath();
243
            } elseif ($attachment->getContent()) {
244
                $this->addTmpfile($file = tmpfile());
245
                fwrite($file, $attachment->getContent());
246
            } else {
247
                continue;
248
            }
249
            $builder->addInlineImage($file, $attachment->getContentId());
250
        }
251
    }
252
253
    private function removeTmpfiles()
254
    {
255
        foreach ($this->tmpfiles as $file) {
256
            fclose($file);
257
        }
258
    }
259
}
260