Completed
Push — master ( 0b85b5...e09a4f )
by Craig
02:16
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 29
    public function __construct(ClientInterface $client, $key)
43
    {
44 29
        $this->key = $key;
45 29
        $this->client = $client;
46 29
    }
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 19
    protected function getAttachments(Swift_Mime_SimpleMessage $message)
75
    {
76 19
        return collect($message->getChildren())
77 19
            ->filter(function ($child) {
78 16
                return $child instanceof Swift_Attachment;
79 19
            })
80 19
            ->map(function ($child) {
81
                return [
82 15
                    'Name' => $child->getHeaders()->get('content-type')->getParameter('name'),
83 15
                    'Content' => base64_encode($child->getBody()),
84 15
                    'ContentType' => $child->getContentType(),
85
                ];
86 19
            })
87 19
            ->toArray();
88
    }
89
90
    /**
91
     * Format the display name.
92
     *
93
     * @param  string
94
     * @return string
95
     */
96 7
    protected function getDisplayname($value)
97
    {
98 7
        if (strpos($value, ',') !== false) {
99 1
            return '"' . $value . '"';
100
        }
101
102 6
        return $value;
103
    }
104
105
    /**
106
     * Format the contacts for the API request.
107
     *
108
     * @param string|array $contacts
109
     *
110
     * @return string
111
     */
112 19
    protected function getContacts($contacts)
113
    {
114 19
        return collect($contacts)
115 19
            ->map(function ($display, $address) {
116 14
                return $display ? $this->getDisplayname($display) . " <{$address}>" : $address;
117 19
            })
118 19
            ->values()
119 19
            ->implode(',');
120
    }
121
122
    /**
123
     * Get the message ID from the response.
124
     *
125
     * @param \GuzzleHttp\Psr7\Response $response
126
     *
127
     * @return string
128
     */
129 1
    protected function getMessageId($response)
130
    {
131 1
        return object_get(
132 1
            json_decode($response->getBody()->getContents()),
133 1
            'MessageID'
134
        );
135
    }
136
137
    /**
138
     * Get the body for the given message.
139
     *
140
     * @param \Swift_Mime_SimpleMessage $message
141
     *
142
     * @return string
143
     */
144 20
    protected function getBody(Swift_Mime_SimpleMessage $message)
145
    {
146 20
        return $message->getBody() ?: '';
147
    }
148
149
    /**
150
     * Get the text and html fields for the given message.
151
     *
152
     * @param \Swift_Mime_SimpleMessage $message
153
     *
154
     * @return array
155
     */
156 18
    protected function getHtmlAndTextBody(Swift_Mime_SimpleMessage $message)
157
    {
158 18
        $data = [];
159
160 18
        switch ($message->getContentType()) {
161 18
            case 'text/html':
162 17
            case 'multipart/mixed':
163 4
            case 'multipart/related':
164 4
            case 'multipart/alternative':
165 15
                $data['HtmlBody'] = $this->getBody($message);
166 15
                break;
167
            default:
168 3
                $data['TextBody'] = $this->getBody($message);
169 3
                break;
170
        }
171
172 18
        if ($text = $this->getMimePart($message, 'text/plain')) {
173 14
            $data['TextBody'] = $text->getBody();
174
        }
175
176 18
        if ($html = $this->getMimePart($message, 'text/html')) {
177 13
            $data['HtmlBody'] = $html->getBody();
178
        }
179
180 18
        return $data;
181
    }
182
183
    /**
184
     * Get a mime part from the given message.
185
     *
186
     * @param \Swift_Mime_SimpleMessage $message
187
     * @param string $mimeType
188
     *
189
     * @return \Swift_MimePart
190
     */
191 19
    protected function getMimePart(Swift_Mime_SimpleMessage $message, $mimeType)
192
    {
193 19
        return collect($message->getChildren())
194 19
            ->filter(function ($child) {
195 16
                return $child instanceof Swift_MimePart;
196 19
            })
197 19
            ->filter(function ($child) use ($mimeType) {
198 15
                return strpos($child->getContentType(), $mimeType) === 0;
199 19
            })
200 19
            ->first();
201
    }
202
203
    /**
204
     * Get the subject for the given message.
205
     *
206
     * @param \Swift_Mime_SimpleMessage $message
207
     *
208
     * @return string
209
     */
210 20
    protected function getSubject(Swift_Mime_SimpleMessage $message)
211
    {
212 20
        return $message->getSubject() ?: '';
213
    }
214
215
    /**
216
     * Get the tag for the given message.
217
     *
218
     * @param \Swift_Mime_SimpleMessage $message
219
     *
220
     * @return string
221
     */
222 21
    protected function getTag(Swift_Mime_SimpleMessage $message)
223
    {
224 21
        return optional(
225 21
            collect($message->getHeaders()->getAll('tag'))
226 21
            ->last()
227
        )
228 21
        ->getFieldBody() ?: '';
229
    }
230
231
    /**
232
     * Get the HTTP payload for sending the Postmark message.
233
     *
234
     * @param \Swift_Mime_SimpleMessage $message
235
     *
236
     * @return array
237
     */
238 18
    protected function payload(Swift_Mime_SimpleMessage $message)
239
    {
240 18
        return collect([
241
            'headers' => [
242 18
                'Accept' => 'application/json',
243 18
                'Content-Type' => 'application/json',
244 18
                'X-Postmark-Server-Token' => $this->key,
245
            ]
246
        ])
247 18
        ->merge([
248 18
            'json' => collect([
249 18
                'Cc' => $this->getContacts($message->getCc()),
250 18
                'Bcc' => $this->getContacts($message->getBcc()),
251 18
                'Tag' => $this->getTag($message),
252 18
                'Subject' => $this->getSubject($message),
253 18
                'ReplyTo' => $this->getContacts($message->getReplyTo()),
254 18
                'Attachments' => $this->getAttachments($message),
255
            ])
256 18
            ->reject(function ($item) {
257 18
                return empty($item);
258 18
            })
259
            ->put('From', $this->getContacts($message->getFrom()))
260
            ->put('To', $this->getContacts($message->getTo()))
261
            ->merge($this->getHtmlAndTextBody($message))
262
        ])
263
        ->toArray();
264
    }
265
}
266