Completed
Push — master ( d9a838...e63fdd )
by Craig
02:30
created

PostmarkTransport::getHtmlAndTextBody()   C

Complexity

Conditions 7
Paths 20

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 16
cts 16
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 17
nc 20
nop 1
crap 7
1
<?php
2
3
namespace Coconuts\Mail;
4
5
use Swift_MimePart;
6
use Swift_Attachment;
7
use Swift_Mime_SimpleMessage;
8
use GuzzleHttp\ClientInterface;
9
use Illuminate\Mail\Transport\Transport;
10
11
class PostmarkTransport extends Transport
12
{
13
    /**
14
     * Guzzle client instance.
15
     *
16
     * @var \GuzzleHttp\ClientInterface
17
     */
18
    protected $client;
19
20
    /**
21
     * The Postmark API key.
22
     *
23
     * @var string
24
     */
25
    protected $key;
26
27
    /**
28
     * The Postmark API end-point.
29
     *
30
     * @var string
31
     */
32
    protected $url = 'https://api.postmarkapp.com/email';
33
34
    /**
35
     * Create a new Postmark transport instance.
36
     *
37
     * @param \GuzzleHttp\ClientInterface $client
38
     * @param string $key
39
     *
40
     * @return void
41
     */
42 28
    public function __construct(ClientInterface $client, $key)
43
    {
44 28
        $this->key = $key;
45 28
        $this->client = $client;
46 28
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51 1
    public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null)
52
    {
53 1
        $this->beforeSendPerformed($message);
54
55 1
        $response = $this->client->post($this->url, $this->payload($message));
56
57 1
        $message->getHeaders()->addTextHeader(
58 1
            'X-PM-Message-Id',
59 1
            $this->getMessageId($response)
60
        );
61
62 1
        $this->sendPerformed($message);
63
64 1
        return $this->numberOfRecipients($message);
65
    }
66
67
    /**
68
     * Get all attachments for the given message.
69
     *
70
     * @param \Swift_Mime_SimpleMessage $message
71
     *
72
     * @return array
73
     */
74 18
    protected function getAttachments(Swift_Mime_SimpleMessage $message)
75
    {
76 18
        return collect($message->getChildren())
77 18
            ->filter(function ($child) {
78 15
                return $child instanceof Swift_Attachment;
79 18
            })
80 18
            ->map(function ($child) {
81
                return [
82 14
                    'Name' => $child->getHeaders()->get('content-type')->getParameter('name'),
83 14
                    'Content' => base64_encode($child->getBody()),
84 14
                    'ContentType' => $child->getContentType(),
85
                ];
86 18
            })
87 18
            ->values()
88 18
            ->toArray();
89
    }
90
91
    /**
92
     * Format the display name.
93
     *
94
     * @param  string
95
     * @return string
96
     */
97 7
    protected function getDisplayname($value)
98
    {
99 7
        if (strpos($value, ',') !== false) {
100 1
            return '"' . $value . '"';
101
        }
102
103 6
        return $value;
104
    }
105
106
    /**
107
     * Format the contacts for the API request.
108
     *
109
     * @param string|array $contacts
110
     *
111
     * @return string
112
     */
113 18
    protected function getContacts($contacts)
114
    {
115 18
        return collect($contacts)
116 18
            ->map(function ($display, $address) {
117 13
                return $display ? $this->getDisplayname($display) . " <{$address}>" : $address;
118 18
            })
119 18
            ->values()
120 18
            ->implode(',');
121
    }
122
123
    /**
124
     * Get the message ID from the response.
125
     *
126
     * @param \GuzzleHttp\Psr7\Response $response
127
     *
128
     * @return string
129
     */
130 1
    protected function getMessageId($response)
131
    {
132 1
        return object_get(
133 1
            json_decode($response->getBody()->getContents()),
134 1
            'MessageID'
135
        );
136
    }
137
138
    /**
139
     * Get the body for the given message.
140
     *
141
     * @param \Swift_Mime_SimpleMessage $message
142
     *
143
     * @return string
144
     */
145 19
    protected function getBody(Swift_Mime_SimpleMessage $message)
146
    {
147 19
        return $message->getBody() ?: '';
148
    }
149
150
    /**
151
     * Get the text and html fields for the given message.
152
     *
153
     * @param \Swift_Mime_SimpleMessage $message
154
     *
155
     * @return array
156
     */
157 17
    protected function getHtmlAndTextBody(Swift_Mime_SimpleMessage $message)
158
    {
159 17
        $data = [];
160
161 17
        switch ($message->getContentType()) {
162 17
            case 'text/html':
163 16
            case 'multipart/mixed':
164 4
            case 'multipart/related':
165 4
            case 'multipart/alternative':
166 14
                $data['HtmlBody'] = $this->getBody($message);
167 14
                break;
168
            default:
169 3
                $data['TextBody'] = $this->getBody($message);
170 3
                break;
171
        }
172
173 17
        if ($text = $this->getMimePart($message, 'text/plain')) {
174 1
            $data['TextBody'] = $text->getBody();
175
        }
176
177 17
        if ($html = $this->getMimePart($message, 'text/html')) {
178 12
            $data['HtmlBody'] = $html->getBody();
179
        }
180
181 17
        return $data;
182
    }
183
184
    /**
185
     * Get a mime part from the given message.
186
     *
187
     * @param \Swift_Mime_SimpleMessage $message
188
     * @param string $mimeType
189
     *
190
     * @return \Swift_MimePart
191
     */
192 18
    protected function getMimePart(Swift_Mime_SimpleMessage $message, $mimeType)
193
    {
194 18
        return collect($message->getChildren())
195 18
            ->filter(function ($child) {
196 15
                return $child instanceof Swift_MimePart;
197 18
            })
198 18
            ->filter(function ($child) use ($mimeType) {
199 14
                return strpos($child->getContentType(), $mimeType) === 0;
200 18
            })
201 18
            ->first();
202
    }
203
204
    /**
205
     * Get the subject for the given message.
206
     *
207
     * @param \Swift_Mime_SimpleMessage $message
208
     *
209
     * @return string
210
     */
211 19
    protected function getSubject(Swift_Mime_SimpleMessage $message)
212
    {
213 19
        return $message->getSubject() ?: '';
214
    }
215
216
    /**
217
     * Get the tag for the given message.
218
     *
219
     * @param \Swift_Mime_SimpleMessage $message
220
     *
221
     * @return string
222
     */
223 20
    protected function getTag(Swift_Mime_SimpleMessage $message)
224
    {
225 20
        return optional(
226 20
            collect($message->getHeaders()->getAll('tag'))
227 20
            ->last()
228
        )
229 20
        ->getFieldBody() ?: '';
230
    }
231
232
    /**
233
     * Get the HTTP payload for sending the Postmark message.
234
     *
235
     * @param \Swift_Mime_SimpleMessage $message
236
     *
237
     * @return array
238
     */
239 17
    protected function payload(Swift_Mime_SimpleMessage $message)
240
    {
241 17
        return collect([
242
            'headers' => [
243 17
                'Accept' => 'application/json',
244 17
                'Content-Type' => 'application/json',
245 17
                'X-Postmark-Server-Token' => $this->key,
246
            ]
247
        ])
248 17
        ->merge([
249 17
            'json' => collect([
250 17
                'Cc' => $this->getContacts($message->getCc()),
251 17
                'Bcc' => $this->getContacts($message->getBcc()),
252 17
                'Tag' => $this->getTag($message),
253 17
                'Subject' => $this->getSubject($message),
254 17
                'ReplyTo' => $this->getContacts($message->getReplyTo()),
255 17
                'Attachments' => $this->getAttachments($message),
256
            ])
257 17
            ->reject(function ($item) {
258 17
                return empty($item);
259 17
            })
260
            ->put('From', $this->getContacts($message->getFrom()))
261
            ->put('To', $this->getContacts($message->getTo()))
262
            ->merge($this->getHtmlAndTextBody($message))
263
        ])
264
        ->toArray();
265
    }
266
}
267