Completed
Pull Request — master (#21)
by
unknown
01:23
created

PostmarkTransport::getMessageId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 7
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
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
use Coconuts\Mail\Exceptions\PostmarkException;
11
12
class PostmarkTransport extends Transport
13
{
14
    /**
15
     * Guzzle client instance.
16
     *
17
     * @var \GuzzleHttp\ClientInterface
18
     */
19
    protected $client;
20
21
    /**
22
     * The Postmark API key.
23
     *
24
     * @var string
25
     */
26
    protected $key;
27
28
    /**
29
     * The Postmark API end-point.
30
     *
31
     * @var string
32
     */
33
    protected $url = 'https://api.postmarkapp.com/email';
34
35
    /**
36
     * Create a new Postmark transport instance.
37
     *
38
     * @param \GuzzleHttp\ClientInterface $client
39
     * @param string $key
40
     *
41
     * @return void
42
     * @throws \Coconuts\Mail\Exceptions\PostmarkException
43
     */
44
    public function __construct(ClientInterface $client, $key)
45
    {
46
        if (empty(trim($key))) {
47
            throw new PostmarkException(
48
                'The Postmark secret is not set. Make sure that the `postmark.secret` config key is set.'
49
            );
50
        }
51
52
        $this->key = $key;
53
        $this->client = $client;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null)
60
    {
61
        $this->beforeSendPerformed($message);
62
63
        $response = $this->client->post($this->url, $this->payload($message));
64
65
        $message->getHeaders()->addTextHeader(
66
            'X-PM-Message-Id',
67
            $this->getMessageId($response)
68
        );
69
70
        $this->sendPerformed($message);
71
72
        return $this->numberOfRecipients($message);
73
    }
74
75
    /**
76
     * Get all attachments for the given message.
77
     *
78
     * @param \Swift_Mime_SimpleMessage $message
79
     *
80
     * @return array
81
     */
82
    protected function getAttachments(Swift_Mime_SimpleMessage $message)
83
    {
84
        return collect($message->getChildren())
85
            ->filter(function ($child) {
86
                return $child instanceof Swift_Attachment;
87
            })
88
            ->map(function ($child) {
89
                return [
90
                    'Name' => $child->getHeaders()->get('content-type')->getParameter('name'),
91
                    'Content' => base64_encode($child->getBody()),
92
                    'ContentType' => $child->getContentType(),
93
                ];
94
            })
95
            ->values()
96
            ->toArray();
97
    }
98
99
    /**
100
     * Format the display name.
101
     *
102
     * @param  string
103
     * @return string
104
     */
105
    protected function getDisplayname($value)
106
    {
107
        if (strpos($value, ',') !== false) {
108
            return '"' . $value . '"';
109
        }
110
111
        return $value;
112
    }
113
114
    /**
115
     * Format the contacts for the API request.
116
     *
117
     * @param string|array $contacts
118
     *
119
     * @return string
120
     */
121
    protected function getContacts($contacts)
122
    {
123
        return collect($contacts)
124
            ->map(function ($display, $address) {
125
                return $display ? $this->getDisplayname($display) . " <{$address}>" : $address;
126
            })
127
            ->values()
128
            ->implode(',');
129
    }
130
131
    /**
132
     * Get the message ID from the response.
133
     *
134
     * @param \GuzzleHttp\Psr7\Response $response
135
     *
136
     * @return string
137
     */
138
    protected function getMessageId($response)
139
    {
140
        return object_get(
141
            json_decode($response->getBody()->getContents()),
142
            'MessageID'
143
        );
144
    }
145
146
    /**
147
     * Get the body for the given message.
148
     *
149
     * @param \Swift_Mime_SimpleMessage $message
150
     *
151
     * @return string
152
     */
153
    protected function getBody(Swift_Mime_SimpleMessage $message)
154
    {
155
        return $message->getBody() ?: '';
156
    }
157
158
    /**
159
     * Get the text and html fields for the given message.
160
     *
161
     * @param \Swift_Mime_SimpleMessage $message
162
     *
163
     * @return array
164
     */
165
    protected function getHtmlAndTextBody(Swift_Mime_SimpleMessage $message)
166
    {
167
        $key = collect([
168
            'text/html' => 'HtmlBody',
169
            'multipart/mixed' => 'HtmlBody',
170
            'multipart/related' => 'HtmlBody',
171
            'multipart/alternative' => 'HtmlBody',
172
        ])
173
        ->get($message->getContentType(), 'TextBody');
174
175
        return collect([
176
            $key => $this->getBody($message)
177
        ])->when($this->getMimePart($message, 'text/plain'), function ($collection, $value) {
0 ignored issues
show
Documentation introduced by
$this->getMimePart($message, 'text/plain') is of type object<Swift_MimePart>|null, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
178
            return $collection->put('TextBody', $value->getBody());
179
        })->when($this->getMimePart($message, 'text/html'), function ($collection, $value) {
180
            return $collection->put('HtmlBody', $value->getBody());
181
        })->all();
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|null
191
     */
192
    protected function getMimePart(Swift_Mime_SimpleMessage $message, $mimeType)
193
    {
194
        return collect($message->getChildren())
195
            ->filter(function ($child) {
196
                return $child instanceof Swift_MimePart;
197
            })
198
            ->filter(function ($child) use ($mimeType) {
199
                return strpos($child->getContentType(), $mimeType) === 0;
200
            })
201
            ->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
    protected function getSubject(Swift_Mime_SimpleMessage $message)
212
    {
213
        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
    protected function getTag(Swift_Mime_SimpleMessage $message)
224
    {
225
        return optional(
226
            collect($message->getHeaders()->getAll('tag'))
227
            ->last()
228
        )
229
        ->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
    protected function payload(Swift_Mime_SimpleMessage $message)
240
    {
241
        return collect([
242
            'headers' => [
243
                'Accept' => 'application/json',
244
                'Content-Type' => 'application/json',
245
                'X-Postmark-Server-Token' => $this->key,
246
            ]
247
        ])
248
        ->merge([
249
            'json' => collect([
250
                'Cc' => $this->getContacts($message->getCc()),
251
                'Bcc' => $this->getContacts($message->getBcc()),
252
                'Tag' => $this->getTag($message),
253
                'Subject' => $this->getSubject($message),
254
                'ReplyTo' => $this->getContacts($message->getReplyTo()),
255
                'Attachments' => $this->getAttachments($message),
256
            ])
257
            ->reject(function ($item) {
258
                return empty($item);
259
            })
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