· 6 years ago · Apr 04, 2019, 01:02 PM
1<?php
2
3/**
4 * Mailjet Public API
5 *
6 * @package API v0.3
7 * @author Mailjet
8 * @link http://api.mailjet.com/
9 *
10 * For PHP v >= 5.3
11 *
12 */
13
14class Mailjet
15{
16 # Wrapper version, changed for each release
17 const WRAPPER_VERSION = '1.1.0';
18
19 # Mailjet API version
20 var $version = 'v3';
21
22 # Connect with https protocol
23 var $secure = true;
24
25 # Mode debug ? 0 : none; 1 : errors only; 2 : all
26 var $debug = 0;
27
28 # Edit with your Mailjet API keys (you can find them here : https://app.mailjet.com/account/api_keys)
29 var $apiKey = '';
30 var $secretKey = '';
31
32 // Ressources arrays
33
34 /*
35 * Newsletter resources
36 */
37 private static $_newsletterResources = array(
38 "newsletterDetailContent",
39 "newsletterSend",
40 "newsletterSchedule",
41 "newsletterTest",
42 "newsletterStatus"
43 );
44
45 /*
46 * Contact resources
47 * "contactManageManyContacts" not in as it is a special case.
48 */
49 private static $_contactResources = array(
50 "contactManageContactsLists",
51 "contactGetContactsLists"
52 );
53
54 /*
55 * Contactslist resources
56 */
57 private static $_contactslistResources = array (
58 "contactslistManageContact",
59 "contactslistManageManyContacts"
60 );
61
62 /*
63 * Template resources
64 */
65 private static $_templateResources = array (
66 "templateDetailContent"
67 );
68
69 /*
70 * dns resources
71 */
72 private static $_dnsResources = array (
73 "dnsCheck"
74 );
75
76 # Constructor function
77 public function __construct($apiKey = false, $secretKey = false, $preprod = false)
78 {
79 if ($apiKey) {
80 $this->apiKey = $apiKey;
81 }
82 if ($secretKey) {
83 $this->secretKey = $secretKey;
84 }
85 $this->apiUrl = $this->getApiUrl($preprod);
86 $this->wrapperVersion = $this->readWrapperVersion();
87 }
88
89 private function getApiUrl ($preprod)
90 {
91 if ($preprod)
92 {
93 return (($this->secure) ? 'https' : 'http') . '://api.preprod.mailjet.com/' . $this->version . '0';
94 }
95 else
96 {
97 return (($this->secure) ? 'https' : 'http') . '://api.mailjet.com/' . $this->version;
98 }
99 }
100
101 public function curl_setopt_custom_postfields($curl_handle, $postfields, $headers = null) {
102 $algos = hash_algos();
103 $hashAlgo = null;
104
105 foreach (array('sha1', 'md5') as $preferred) {
106 if (in_array($preferred, $algos)) {
107 $hashAlgo = $preferred;
108 break;
109 }
110 }
111
112 if ($hashAlgo === null) {
113 list($hashAlgo) = $algos;
114 }
115
116 $boundary =
117 '----------------------------' .
118 substr(hash($hashAlgo, 'cURL-php-multiple-value-same-key-support' . microtime()), 0, 12);
119
120 $body = array();
121 $crlf = "\r\n";
122
123 foreach ($postfields as $key => $value) {
124 if (is_array($value)) {
125 foreach ($value as $filename => $path) {
126 // attachment
127 if (strpos($path, '@') === 0) {
128 preg_match('/^@(.*?)$/', $path, $matches);
129 list($dummy, $path) = $matches;
130
131 if (is_int($filename)) {
132 $filename = basename($path);
133 }
134
135 $body[] = '--' . $boundary;
136 $body[] = 'Content-Disposition: form-data; name="' . $key . '"; filename="' . $filename . '"';
137 $body[] = 'Content-Type: application/octet-stream';
138 $body[] = '';
139 $body[] = file_get_contents($path);
140 }
141 // Array of recipients
142 else if ('to' == $key || 'cc' == $key || 'bcc' == $key) {
143 $body[] = '--' . $boundary;
144 $body[] = 'Content-Disposition: form-data; name="' . $key . '"';
145 $body[] = '';
146 $body[] = trim($path);
147 }
148 }
149 }
150 else {
151 $body[] = '--' . $boundary;
152 $body[] = 'Content-Disposition: form-data; name="' . $key . '"';
153 $body[] = '';
154 $body[] = $value;
155 }
156 }
157
158 $body[] = '--' . $boundary . '--';
159 $body[] = '';
160 $contentType = 'multipart/form-data; boundary=' . $boundary;
161 $content = join($crlf, $body);
162 $contentLength = strlen($content);
163
164 curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array(
165 'Content-Length: ' . $contentLength,
166 'Expect: 100-continue',
167 'Content-Type: ' . $contentType,
168 ));
169
170 curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $content);
171 }
172
173 public function __call($resource, $args)
174 {
175 # Parameters array
176 $params = (sizeof($args) > 0) ? $args[0] : array();
177
178 # Request method, GET by default
179 if (isset($params["method"]))
180 {
181 $request = strtoupper($params["method"]);
182 unset($params['method']);
183 }
184 else
185 {
186 $request = 'GET';
187 }
188
189 # Request ID, empty by default
190 $id = isset($params["ID"]) ? $params["ID"] : '';
191
192 /*
193 Using SendAPI without the "to" parameter but with "cc" AND/OR "bcc"
194 Our API needs the "to" parameter filled to send email
195 We give it a default value with an email @example.org. See http://en.wikipedia.org/wiki/Example.com
196 */
197 if ($resource == "sendEmail" && (empty($params["to"]) && (!empty($params["cc"]) || !empty($params["bcc"])))) {
198 $params["to"] = "mailjet@example.org";
199 }
200
201 if ($id == '')
202 {
203 # Request Unique field, empty by default
204 $unique = isset($params["unique"]) ? $params["unique"] : '';
205 unset($params["unique"]);
206 # Make request
207 $result = $this->sendRequest($resource, $params, $request, $unique);
208 }
209 else
210 {
211 # Make request
212 $result = $this->sendRequest($resource, $params, $request, $id);
213 }
214
215 # Return result
216 $return = ($result === true) ? $this->_response : false;
217 if ($this->debug == 2 || ($this->debug == 1 && $return == false)) {
218 $this->debug();
219 }
220
221 return $return;
222 }
223
224 /**
225 *
226 * @param string $method REST or DATA
227 * @param string $resourceBase Base resource
228 * @param int $resourceID Base resource ID
229 * @param string $action Action on resource
230 *
231 * @return string Returns the call's url.
232 */
233 private function makeUrl($method, $resourceBase, $resourceID, $action)
234 {
235 return $this->apiUrl.'/'.$method.'/'.$resourceBase.'/'.$resourceID.'/'.strtolower($action);
236 }
237
238 /**
239 *
240 * @param string $method REST or DATA
241 * @param string $resourceBase Base resource
242 * @param int $resourceID Base resource ID
243 * @param string $resource The whole resource, before parsing
244 *
245 * @return string Returns the call's url.
246 */
247 private function makeUrlFromFilter($method, $resourceBase, $resourceID, $resource)
248 {
249 $matches = array();
250 preg_match('/'.$resourceBase.'([a-zA-Z]+)/', $resource, $matches);
251
252 $action = $matches[1];
253 return $this->makeUrl($method, $resourceBase, $resourceID, $action);
254 }
255
256 public function requestUrlBuilder($resource, $params = array(), $request, $id)
257 {
258 if ($resource == "sendEmail") {
259 $this->call_url = $this->apiUrl."/send/message";
260 }
261 else if ($resource == "send") {
262 $this->call_url = $this->apiUrl."/send"; //json support for SendAPI
263 }
264 else if ($resource == "uploadCSVContactslistData") {
265 if (!empty($params['_contactslist_id'])) {
266 $contactslist_id = $params['_contactslist_id'];
267 }
268 else if (!empty($params['ID'])) {
269 $contactslist_id = $params['ID'];
270 }
271 $this->call_url = $this->makeUrl('DATA', 'Contactslist', $contactslist_id, 'CSVData/text:plain'); // Was $this->call_url = $this->apiUrl."/DATA/contactslist/". $contactslist_id ."/CSVData/text:plain";
272 }
273 else if (($resource == "addHTMLbody") || ($resource == "getHTMLbody")) {
274 if (!empty($params['_newsletter_id'])) {
275 $newsletter_id = $params['_newsletter_id'];
276 }
277 else if (!empty($params['ID'])) {
278 $newsletter_id = $params['ID'];
279 }
280 $this->call_url = $this->makeUrl('DATA', 'NewsLetter', $newsletter_id, 'HTML/text/html/LAST');
281 }
282 else if (in_array($resource, self::$_newsletterResources))
283 {
284 $this->call_url = $this->makeUrlFromFilter('REST', 'newsletter', $params['ID'], $resource); // Was $this->call_url = $this->apiUrl."/REST/newsletter/". $newsletter_id ."/".strtolower($action);
285 }
286 else if (in_array($resource, self::$_templateResources))
287 {
288 $this->call_url = $this->makeUrlFromFilter('REST', 'template', $params['ID'], $resource);
289 }
290 else if (in_array($resource, self::$_dnsResources))
291 {
292 $this->call_url = $this->makeUrlFromFilter('REST', 'dns', $params['ID'], $resource);
293 }
294 else if (in_array($resource, self::$_contactResources))
295 {
296 $this->call_url = $this->makeUrlFromFilter('REST', 'contact', $params['ID'], $resource); // Was $this->call_url = $this->apiUrl."/REST/contact/". $contact_id . "/".strtolower($action);
297 }
298 else if ($resource == "contactManageManyContacts")
299 {
300 $this->call_url = $this->apiUrl."/REST/contact/managemanycontacts";
301 }
302 else if (in_array($resource, self::$_contactslistResources))
303 {
304 $this->call_url = $this->makeUrlFromFilter('REST', 'contactslist', $params['ID'], $resource); // Was $this->call_url = $this->apiUrl."/REST/contactslist/". $contactslist_id . "/".strtolower($action);
305 }
306 else {
307 $this->call_url = $this->apiUrl . '/REST/' . $resource;
308 }
309
310 if ($request == "GET" || $request == "POST") {
311 if (count($params) > 0)
312 {
313 $this->call_url .= '?';
314
315 foreach ($params as $key => $value) {
316 // In a GET request, put an underscore char in front of params to avoid it being treated as a filter
317 $firstChar = substr($key, 0, -(strlen($key) - 1));
318
319 if ($request == "GET") {
320 $okFirstChar = ($firstChar != "_");
321 $queryStringKey = $key;
322 }
323 else {
324 $okFirstChar = ($firstChar == "_");
325 $queryStringKey = substr($key, 1);
326 }
327
328 if ($okFirstChar && ($key != "ID"))
329 {
330 $query_string[$queryStringKey] = $queryStringKey . '=' . urlencode($value);
331 $this->call_url .= $query_string[$queryStringKey] . '&';
332 }
333 }
334
335 $this->call_url = substr($this->call_url, 0, -1);
336 }
337 }
338
339 if (($request == "VIEW" || $request == "DELETE" || $request == "PUT") && $resource != "addHTMLbody" && $resource != "uploadCSVContactslistData")
340 {
341 if ($id != '')
342 {
343 if ($resource == "contactslistManageManyContacts")
344 {
345 $this->call_url .= '/' . $params["JobID"];
346 }
347 else
348 {
349 $this->call_url .= '/' . $id;
350 }
351 }
352 }
353
354 return $this->call_url;
355 }
356
357 public function sendRequest($resource = false, $params = array(), $request = "GET", $id = '')
358 {
359 # Method
360 $this->_method = $resource;
361 $this->_request = $request;
362
363 # Build request URL
364 $url = $this->requestUrlBuilder($resource, $params, $request, $id);
365
366 // fix bug for sort (ID+DESC), replace %2B in url by +
367 $url = preg_replace('#Sort=(.+)%2B(DESC|ASC|)?#sUi', 'Sort=$1+$2', $url);
368
369 # Set up and execute the curl process
370 $curl_handle = curl_init();
371 curl_setopt($curl_handle, CURLOPT_URL, $url);
372 curl_setopt($curl_handle, CURLOPT_USERAGENT, 'mailjet-api-v3-php-simple/' . $this->wrapperVersion . '; PHP v. ' . phpversion());
373 curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
374 curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
375 curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
376 curl_setopt($curl_handle, CURLOPT_USERPWD, $this->apiKey . ':' . $this->secretKey);
377
378 $this->_request_post = false;
379
380 if (($request == 'POST') || ($request == 'PUT')):
381 curl_setopt($curl_handle, CURLOPT_POST, 1);
382
383 // Exclude filters from payload. See http://stackoverflow.com/questions/4260086/php-how-to-use-array-filter-to-filter-array-keys
384 $paramsFiltered = array_filter(array_keys($params), function($k) {
385 return substr($k, 0, 1) != '_';
386 });
387 $params = array_intersect_key($params, array_flip($paramsFiltered));
388
389 if ($this->debug == 2) {
390 var_dump($params);
391 }
392
393 if ($resource == "sendEmail") {
394 $this->curl_setopt_custom_postfields($curl_handle, $params);
395 }
396 else if ($resource == "addHTMLbody")
397 {
398 curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $params['html_content']);
399 curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array(
400 'Content-Type: text/html'
401 ));
402 }
403 //
404 else if ($resource == "uploadCSVContactslistData")
405 {
406 curl_setopt($curl_handle, CURLOPT_BINARYTRANSFER, TRUE);
407 curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $params['csv_content']);
408 curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array(
409 'Content-Type: text/plain'
410 ));
411 }
412 //
413 else
414 {
415 if ((in_array($resource, self::$_newsletterResources)) ||
416 ($resource == "contactManageContactsLists") ||
417 ($resource == "contactManageManyContacts") ||
418 (in_array($resource, self::$_contactslistResources)) ||
419 (in_array($resource, self::$_templateResources)) ||
420 (in_array($resource, self::$_dnsResources)))
421 {
422 unset($params['ID']);
423 }
424
425 $j_e = null;
426 if (version_compare(phpversion(), '5.4.0', '<')) {
427 $j_e = str_replace('\\/', '/', json_encode($params));
428 } else {
429 // 64 => unescaped_slashes
430 $j_e = json_encode($params, 64);
431 }
432
433 curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $j_e);
434 curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array(
435 'Content-Type: application/json'
436 ));
437 }
438 $this->_request_post = $params;
439 endif;
440
441 if ($request == 'DELETE') {
442 curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, "DELETE");
443 }
444
445 if ($request == 'PUT') {
446 curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, "PUT");
447 }
448
449 $buffer = curl_exec($curl_handle);
450
451 if ($this->debug == 2) {
452 var_dump($buffer);
453 }
454
455 # Response code
456 $this->_response_code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
457
458 # Close curl process
459 curl_close($curl_handle);
460
461 # Return response
462 if (($this->_response_code == 200) && ($resource == "getHTMLbody")) {
463 $this->_response = $buffer;
464 }
465 else
466 {
467 /*
468 * This prevents the rounding error on 32 bits systems with PHP version >= 5.4
469 */
470 if (defined('JSON_BIGINT_AS_STRING'))
471 {
472 $this->_response = json_decode($buffer, false, 512, JSON_BIGINT_AS_STRING);
473 }
474 else
475 { // PHP v <= 5.3.* doens't support the fourth parameter of json_decode
476 $this->_response = json_decode($buffer, false, 512);
477 }
478 }
479
480 if ($request == 'POST') {
481 return ($this->_response_code == 201 || $this->_response_code == 200) ? true : false;
482 }
483 if ($request == 'DELETE') {
484 return ($this->_response_code == 204) ? true : false;
485 }
486 return ($this->_response_code == 200) ? true : false;
487 }
488
489 public function debug()
490 {
491 echo '<style type="text/css">';
492 echo '
493
494 #debugger {width: 100%; font-family: arial;}
495 #debugger table {padding: 0; margin: 0 0 20px; width: 100%; font-size: 11px; text-align: left;border-collapse: collapse;}
496 #debugger th, #debugger td {padding: 2px 4px;}
497 #debugger tr.h {background: #999; color: #fff;}
498 #debugger tr.Success {background:#90c306; color: #fff;}
499 #debugger tr.Error {background:#c30029 ; color: #fff;}
500 #debugger tr.Not-modified {background:orange ; color: #fff;}
501 #debugger th {width: 20%; vertical-align:top; padding-bottom: 8px;}
502
503 ';
504 echo '</style>';
505
506 echo '<div id="debugger">';
507
508 if (isset($this->_response_code)):
509 if (($this->_response_code == 200) || ($this->_response_code == 201) || ($this->_response_code == 204)):
510 echo '<table>';
511 echo '<tr class="Success"><th>Success</th><td></td></tr>';
512 echo '<tr><th>Status code</th><td>' . $this->_response_code . '</td></tr>';
513
514 if (isset($this->_response)):
515 echo '<tr><th>Response</th><td><pre>' . utf8_decode(print_r($this->_response, 1)) . '</pre></td></tr>';
516 endif;
517
518 echo '</table>';
519 elseif ($this->_response_code == 304):
520 echo '<table>';
521 echo '<tr class="Not-modified"><th>Error</th><td></td></tr>';
522 echo '<tr><th>Error no</th><td>' . $this->_response_code . '</td></tr>';
523 echo '<tr><th>Message</th><td>Not Modified</td></tr>';
524 echo '</table>';
525 else:
526 echo '<table>';
527 echo '<tr class="Error"><th>Error</th><td></td></tr>';
528 echo '<tr><th>Error no</th><td>' . $this->_response_code . '</td></tr>';
529 if (isset($this->_response)):
530 if (is_array($this->_response) OR is_object($this->_response)):
531 echo '<tr><th>Status</th><td><pre>' . print_r($this->_response, true) . '</pre></td></tr>';
532 else:
533 echo '<tr><th>Status</th><td><pre>' . $this->_response . '</pre></td></tr>';
534 endif;
535 endif;
536 echo '</table>';
537 endif;
538 endif;
539
540 $call_url = parse_url($this->call_url);
541
542 echo '<table>';
543 echo '<tr class="h"><th>API config</th><td></td></tr>';
544 echo '<tr><th>Protocole</th><td>' . $call_url['scheme'] . '</td></tr>';
545 echo '<tr><th>Host</th><td>' . $call_url['host'] . '</td></tr>';
546 echo '<tr><th>Version</th><td>' . $this->version . '</td></tr>';
547 echo '<tr><th>Wrapper Version</th><td>' . $this->readWrapperVersion() . '</td></tr>';
548 echo '</table>';
549
550 echo '<table>';
551 echo '<tr class="h"><th>Call infos</th><td></td></tr>';
552 echo '<tr><th>Resource</th><td>' . $this->_method . '</td></tr>';
553 echo '<tr><th>Request type</th><td>' . $this->_request . '</td></tr>';
554 echo '<tr><th>Get Arguments</th><td>';
555
556 if (isset($call_url['query'])) {
557 $args = explode("&", $call_url['query']);
558 foreach ($args as $arg) {
559 $arg = explode("=", $arg);
560 echo '' . $arg[0] . ' = <span style="color:#ff6e56;">' . $arg[1] . '</span><br/>';
561 }
562 }
563
564 echo '</td></tr>';
565
566 if ($this->_request_post) {
567 echo '<tr><th>Post Arguments</th><td>';
568
569 foreach ($this->_request_post as $k => $v) {
570 if (is_array($v))
571 {
572 foreach ($v as $key => $value)
573 {
574 echo $key . ' = <span style="color:#ff6e56;">' . $value . '</span><br/>';
575 }
576 }
577 else
578 {
579 echo $k . ' = <span style="color:#ff6e56;">' . $v . '</span><br/>';
580 }
581 }
582
583 echo '</td></tr>';
584 }
585
586 echo '<tr><th>Call url</th><td>' . $this->call_url . '</td></tr>';
587 echo '</table>';
588
589 echo '</div>';
590 }
591
592 private function readWrapperVersion() {
593 return Mailjet::WRAPPER_VERSION;
594 }
595}