1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @license https://github.com/f500/swiftmailer-sparkpost/blob/master/LICENSE MIT |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
namespace SwiftSparkPost; |
8
|
|
|
|
9
|
|
|
use Swift_Attachment; |
10
|
|
|
use Swift_Mime_Header; |
11
|
|
|
use Swift_Mime_Message; |
12
|
|
|
use Swift_MimePart; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* @copyright Future500 B.V. |
16
|
|
|
* @author Jasper N. Brouwer <[email protected]> |
17
|
|
|
*/ |
18
|
|
|
final class PayloadBuilder implements PayloadBuilderInterface |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* @param Swift_Mime_Message $message |
22
|
|
|
* |
23
|
|
|
* @return array |
24
|
|
|
*/ |
25
|
27 |
|
public function buildPayload(Swift_Mime_Message $message) |
26
|
|
|
{ |
27
|
|
|
$payload = [ |
28
|
27 |
|
'recipients' => $this->buildRecipients($message), |
29
|
24 |
|
'content' => $this->buildContent($message), |
30
|
8 |
|
]; |
31
|
|
|
|
32
|
24 |
|
if ($campaignId = $this->buildCampaignId($message)) { |
33
|
3 |
|
$payload['campaign_id'] = $campaignId; |
34
|
1 |
|
} |
35
|
|
|
|
36
|
24 |
|
if ($metadata = $this->buildMetadata($message)) { |
37
|
3 |
|
$payload['metadata'] = $metadata; |
38
|
1 |
|
} |
39
|
|
|
|
40
|
24 |
|
if ($substitutionData = $this->buildSubstitutionData($message)) { |
41
|
3 |
|
$payload['substitution_data'] = $substitutionData; |
42
|
1 |
|
} |
43
|
|
|
|
44
|
24 |
|
if ($options = $this->buildOptions($message)) { |
45
|
21 |
|
$payload['options'] = $options; |
46
|
7 |
|
} |
47
|
|
|
|
48
|
24 |
|
return $payload; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @param Swift_Mime_Message $message |
53
|
|
|
* |
54
|
|
|
* @return array |
55
|
|
|
* @throws Exception |
56
|
|
|
*/ |
57
|
27 |
|
private function buildRecipients(Swift_Mime_Message $message) |
58
|
|
|
{ |
59
|
27 |
|
$tos = array_merge((array) $message->getTo(), (array) $message->getCc()); |
60
|
27 |
|
$bcc = (array) $message->getBcc(); |
61
|
|
|
|
62
|
27 |
|
if (!$tos) { |
|
|
|
|
63
|
3 |
|
throw new Exception('Cannot send message without a recipient address'); |
64
|
|
|
} |
65
|
|
|
|
66
|
24 |
|
$tags = []; |
67
|
24 |
|
$metadata = []; |
68
|
24 |
|
$substitutionData = []; |
69
|
|
|
|
70
|
24 |
|
if ($message instanceof Message) { |
71
|
21 |
|
$tags = $message->getPerRecipientTags(); |
72
|
21 |
|
$metadata = $message->getPerRecipientMetadata(); |
73
|
21 |
|
$substitutionData = $message->getPerRecipientSubstitutionData(); |
74
|
7 |
|
} |
75
|
|
|
|
76
|
24 |
|
foreach ($tos as $email => $name) { |
77
|
24 |
|
$recipients[] = $this->buildRecipient($email, $name, $tags, $metadata, $substitutionData); |
|
|
|
|
78
|
8 |
|
} |
79
|
|
|
|
80
|
24 |
|
$originalEmail = current($recipients)['address']['email']; |
|
|
|
|
81
|
|
|
|
82
|
24 |
|
foreach ($bcc as $email => $name) { |
83
|
15 |
|
$recipients[] = $this->buildRecipient($email, $name, $tags, $metadata, $substitutionData, $originalEmail); |
84
|
8 |
|
} |
85
|
|
|
|
86
|
24 |
|
return $recipients; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* @param string $email |
91
|
|
|
* @param string $name |
92
|
|
|
* @param array $tags |
93
|
|
|
* @param array $metadata |
94
|
|
|
* @param array $substitutionData |
95
|
|
|
* @param string|null $originalEmail |
96
|
|
|
* |
97
|
|
|
* @return array |
98
|
|
|
*/ |
99
|
24 |
|
private function buildRecipient( |
100
|
|
|
$email, |
101
|
|
|
$name, |
102
|
|
|
array $tags, |
103
|
|
|
array $metadata, |
104
|
|
|
array $substitutionData, |
105
|
|
|
$originalEmail = null |
106
|
|
|
) { |
107
|
24 |
|
$recipient = ['address' => ['email' => $email]]; |
108
|
|
|
|
109
|
24 |
|
if ($name) { |
110
|
9 |
|
$recipient['address']['name'] = $name; |
111
|
3 |
|
} |
112
|
|
|
|
113
|
24 |
|
if ($originalEmail) { |
|
|
|
|
114
|
15 |
|
$recipient['address']['header_to'] = $originalEmail; |
115
|
5 |
|
} |
116
|
|
|
|
117
|
24 |
|
if (isset($tags[$email])) { |
118
|
3 |
|
$recipient['tags'] = $tags[$email]; |
119
|
1 |
|
} |
120
|
|
|
|
121
|
24 |
|
if (isset($metadata[$email])) { |
122
|
3 |
|
$recipient['metadata'] = $metadata[$email]; |
123
|
1 |
|
} |
124
|
|
|
|
125
|
24 |
|
if (isset($substitutionData[$email])) { |
126
|
3 |
|
$recipient['substitution_data'] = $substitutionData[$email]; |
127
|
1 |
|
} |
128
|
|
|
|
129
|
24 |
|
return $recipient; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param Swift_Mime_Message $message |
134
|
|
|
* |
135
|
|
|
* @return array |
136
|
|
|
*/ |
137
|
24 |
|
private function buildContent(Swift_Mime_Message $message) |
138
|
|
|
{ |
139
|
|
|
$content = [ |
140
|
24 |
|
'subject' => $this->convertAsteriskPipeToCurlyBraces($message->getSubject()), |
141
|
24 |
|
'from' => $this->buildFrom($message), |
142
|
8 |
|
]; |
143
|
|
|
|
144
|
24 |
|
if ($message->getReplyTo()) { |
145
|
15 |
|
$content['reply_to'] = key($message->getReplyTo()); |
146
|
5 |
|
} |
147
|
|
|
|
148
|
24 |
|
$contentMap = ['text/html' => 'html', 'text/plain' => 'text']; |
149
|
|
|
|
150
|
24 |
|
$contentType = $this->readUserContentType($message); |
151
|
24 |
|
if (isset($contentMap[$contentType])) { |
152
|
24 |
|
$content[$contentMap[$contentType]] = $this->convertAsteriskPipeToCurlyBraces($message->getBody()); |
153
|
8 |
|
} |
154
|
|
|
|
155
|
24 |
|
foreach ($message->getChildren() as $part) { |
156
|
6 |
|
if (!($part instanceof Swift_MimePart)) { |
157
|
3 |
|
continue; |
158
|
|
|
} |
159
|
|
|
|
160
|
6 |
|
$contentType = $part->getContentType(); |
161
|
6 |
|
if (isset($contentMap[$contentType])) { |
162
|
6 |
|
$content[$contentMap[$contentType]] = $this->convertAsteriskPipeToCurlyBraces($part->getBody()); |
163
|
2 |
|
} |
164
|
8 |
|
} |
165
|
|
|
|
166
|
24 |
|
if ($headers = $this->buildHeaders($message)) { |
167
|
3 |
|
$content['headers'] = $headers; |
168
|
1 |
|
} |
169
|
|
|
|
170
|
24 |
|
if ($attachments = $this->buildAttachments($message)) { |
171
|
3 |
|
$content['attachments'] = $attachments; |
172
|
1 |
|
} |
173
|
|
|
|
174
|
24 |
|
return $content; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @param Swift_Mime_Message $message |
179
|
|
|
* |
180
|
|
|
* @return array|string |
181
|
|
|
*/ |
182
|
24 |
|
private function buildFrom(Swift_Mime_Message $message) |
183
|
|
|
{ |
184
|
24 |
|
$from = $message->getFrom(); |
185
|
|
|
|
186
|
24 |
|
if (current($from)) { |
187
|
9 |
|
return ['email' => key($from), 'name' => current($from)]; |
188
|
|
|
} |
189
|
|
|
|
190
|
15 |
|
return key($from); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* @param Swift_Mime_Message $message |
195
|
|
|
* |
196
|
|
|
* @return array |
197
|
|
|
*/ |
198
|
24 |
|
private function buildHeaders(Swift_Mime_Message $message) |
199
|
|
|
{ |
200
|
24 |
|
$headers = []; |
201
|
|
|
$filter = [ |
202
|
24 |
|
'Bcc', |
203
|
8 |
|
'Cc', |
204
|
8 |
|
'Content-Transfer-Encoding', |
205
|
8 |
|
'Content-Type', |
206
|
8 |
|
'Date', |
207
|
8 |
|
'DKIM-Signature', |
208
|
8 |
|
'DomainKey-Signature', |
209
|
8 |
|
'From', |
210
|
8 |
|
'Message-ID', |
211
|
8 |
|
'MIME-Version', |
212
|
8 |
|
'Received', |
213
|
8 |
|
'Reply-To', |
214
|
8 |
|
'Return-Path', |
215
|
8 |
|
'Sender', |
216
|
8 |
|
'Subject', |
217
|
8 |
|
'To', |
218
|
8 |
|
]; |
219
|
|
|
|
220
|
|
|
/** @var Swift_Mime_Header $header */ |
221
|
24 |
|
foreach ($message->getHeaders()->getAll() as $header) { |
222
|
24 |
|
if (in_array($header->getFieldName(), $filter, true)) { |
223
|
24 |
|
continue; |
224
|
|
|
} |
225
|
|
|
|
226
|
3 |
|
$headers[] = trim($header->toString()); |
227
|
8 |
|
} |
228
|
|
|
|
229
|
24 |
|
return $headers; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* @param Swift_Mime_Message $message |
234
|
|
|
* |
235
|
|
|
* @return array |
236
|
|
|
*/ |
237
|
24 |
|
private function buildAttachments(Swift_Mime_Message $message) |
238
|
|
|
{ |
239
|
24 |
|
$attachments = []; |
240
|
|
|
|
241
|
24 |
|
foreach ($message->getChildren() as $part) { |
242
|
6 |
|
if ($part instanceof Swift_Attachment) { |
243
|
3 |
|
$attachments[] = [ |
244
|
3 |
|
'type' => $part->getContentType(), |
245
|
3 |
|
'name' => $part->getFilename(), |
246
|
5 |
|
'data' => base64_encode($part->getBody()), |
247
|
|
|
]; |
248
|
1 |
|
} |
249
|
8 |
|
} |
250
|
|
|
|
251
|
24 |
|
return $attachments; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* @param Swift_Mime_Message $message |
256
|
|
|
* |
257
|
|
|
* @return string |
258
|
|
|
*/ |
259
|
24 |
|
private function buildCampaignId(Swift_Mime_Message $message) |
260
|
|
|
{ |
261
|
24 |
|
if (!($message instanceof Message)) { |
262
|
3 |
|
return ''; |
263
|
|
|
} |
264
|
|
|
|
265
|
21 |
|
return $message->getCampaignId(); |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* @param Swift_Mime_Message $message |
270
|
|
|
* |
271
|
|
|
* @return array |
272
|
|
|
*/ |
273
|
24 |
|
private function buildMetadata(Swift_Mime_Message $message) |
274
|
|
|
{ |
275
|
24 |
|
if (!($message instanceof Message)) { |
276
|
3 |
|
return []; |
277
|
|
|
} |
278
|
|
|
|
279
|
21 |
|
return $message->getMetadata(); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* @param Swift_Mime_Message $message |
284
|
|
|
* |
285
|
|
|
* @return array |
286
|
|
|
*/ |
287
|
24 |
|
private function buildSubstitutionData(Swift_Mime_Message $message) |
288
|
|
|
{ |
289
|
24 |
|
if (!($message instanceof Message)) { |
290
|
3 |
|
return []; |
291
|
|
|
} |
292
|
|
|
|
293
|
21 |
|
return $message->getSubstitutionData(); |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* @param Swift_Mime_Message $message |
298
|
|
|
* |
299
|
|
|
* @return array |
300
|
|
|
*/ |
301
|
24 |
|
private function buildOptions(Swift_Mime_Message $message) |
302
|
|
|
{ |
303
|
24 |
|
if (!($message instanceof Message)) { |
304
|
3 |
|
return []; |
305
|
|
|
} |
306
|
|
|
|
307
|
21 |
|
return $message->getOptions(); |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Convert *|foo|* to {{foo}} |
312
|
|
|
* |
313
|
|
|
* @param string |
314
|
|
|
* |
315
|
|
|
* @return string |
316
|
|
|
*/ |
317
|
24 |
|
private function convertAsteriskPipeToCurlyBraces($content) |
318
|
|
|
{ |
319
|
24 |
|
return preg_replace('/\*\|(.+?)\|\*/', '{{\1}}', $content); |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* @param Swift_Mime_Message $message |
324
|
|
|
* |
325
|
|
|
* @return string |
326
|
|
|
*/ |
327
|
24 |
|
private function readUserContentType(Swift_Mime_Message $message) |
328
|
|
|
{ |
329
|
24 |
|
$ro = new \ReflectionObject($message); |
330
|
24 |
|
$rp = $ro->getProperty('_userContentType'); |
331
|
24 |
|
$rp->setAccessible(true); |
332
|
24 |
|
return (string) $rp->getValue($message); |
333
|
|
|
} |
334
|
|
|
} |
335
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.