mandrill.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. <?php
  2. /**
  3. * @file
  4. * Wrapper class around the Mandrill API.
  5. */
  6. /**
  7. * Class MandrillException.
  8. */
  9. class MandrillException extends Exception {
  10. }
  11. /**
  12. * Class DrupalMandrill.
  13. */
  14. class DrupalMandrill {
  15. const API_VERSION = '1.0';
  16. const END_POINT = 'https://mandrillapp.com/api/';
  17. protected $api;
  18. /**
  19. * Default to a 300 second timeout on server calls
  20. */
  21. protected $timeout = 300;
  22. /**
  23. * Constructor to set internal values.
  24. *
  25. * @param string $api_key
  26. * Mandrill API key.
  27. * @param int $timeout
  28. * Server timeout.
  29. *
  30. * @throws MandrillException.
  31. */
  32. public function __construct($api_key, $timeout = 300) {
  33. if (empty($api_key)) {
  34. throw new MandrillException('Invalid API key');
  35. }
  36. try {
  37. $response = $this->request('users/ping', array('key' => $api_key));
  38. if ($response != 'PONG!') {
  39. throw new MandrillException('Invalid API key: ' . $response);
  40. }
  41. $this->api = $api_key;
  42. $this->timeout = $timeout;
  43. }
  44. catch (Exception $e) {
  45. throw new MandrillException($e->getMessage());
  46. }
  47. }
  48. /**
  49. * Make a request to Mandrill's API.
  50. *
  51. * Every API call uses this function to actually make the request to
  52. * Mandrill's servers.
  53. *
  54. * @link https://mandrillapp.com/api/docs/
  55. *
  56. * @param string $method
  57. * API method name
  58. * @param array $args
  59. * query arguments
  60. * @param string $http
  61. * GET or POST request type
  62. * @param string $output
  63. * API response format (json,php,xml,yaml). json and xml are decoded into
  64. * arrays automatically.
  65. *
  66. * @return array
  67. * Array on success.
  68. *
  69. * @throws MandrillException.
  70. */
  71. protected function request($method, $args = array(), $http = 'POST', $output = 'json') {
  72. if (!isset($args['key'])) {
  73. $args['key'] = $this->api;
  74. }
  75. $api_version = self::API_VERSION;
  76. $dot_output = ('json' == $output) ? '' : ".{$output}";
  77. $url = self::END_POINT . "{$api_version}/{$method}{$dot_output}";
  78. $params = drupal_json_encode($args);
  79. switch ($http) {
  80. case 'GET':
  81. $url .= '?' . $params;
  82. $response = drupal_http_request($url, array(
  83. 'method' => 'GET',
  84. 'timeout' => $this->timeout,
  85. ));
  86. break;
  87. case 'POST':
  88. $response = drupal_http_request($url, array(
  89. 'method' => 'POST',
  90. 'data' => $params,
  91. 'timeout' => $this->timeout,
  92. ));
  93. break;
  94. default:
  95. throw new MandrillException('Unknown request type');
  96. }
  97. $response_code = $response->code;
  98. if (0 == $response_code) {
  99. return $response->error;
  100. }
  101. $body = $response->data;
  102. switch ($output) {
  103. case 'json':
  104. $body = json_decode($body, TRUE);
  105. break;
  106. case 'php':
  107. $body = unserialize($body);
  108. break;
  109. }
  110. if (200 == $response_code) {
  111. return $body;
  112. }
  113. else {
  114. $message = isset($body['message']) ? $body['message'] : $body;
  115. if (is_array($message)) {
  116. $message = "Unspecified Error";
  117. }
  118. throw new MandrillException($message, $response_code);
  119. }
  120. }
  121. /**
  122. * @link https://mandrillapp.com/api/docs/users.html#method=ping
  123. *
  124. * @return array|MandrillException
  125. */
  126. public function users_ping() {
  127. return $this->request('users/ping');
  128. }
  129. /**
  130. * @link https://mandrillapp.com/api/docs/users.html#method=info
  131. *
  132. * @return array|MandrillException
  133. */
  134. public function users_info() {
  135. return $this->request('users/info');
  136. }
  137. /**
  138. * @link https://mandrillapp.com/api/docs/users.html#method=senders
  139. *
  140. * @return array|MandrillException
  141. */
  142. public function users_senders() {
  143. return $this->request('users/senders');
  144. }
  145. /**
  146. * @link https://mandrillapp.com/api/docs/senders.html#method=domains
  147. *
  148. * @return array|MandrillException
  149. */
  150. public function senders_domains() {
  151. return $this->request('senders/domains');
  152. }
  153. /**
  154. * @link https://mandrillapp.com/api/docs/senders.html#method=list
  155. *
  156. * @return array|MandrillException
  157. */
  158. public function senders_list() {
  159. return $this->request('senders/list');
  160. }
  161. /**
  162. * @link https://mandrillapp.com/api/docs/senders.html#method=info
  163. *
  164. * @return array|MandrillException
  165. */
  166. public function senders_info($email) {
  167. return $this->request('senders/info', array('address' => $email));
  168. }
  169. /**
  170. * @link https://mandrillapp.com/api/docs/senders.html#method=time-series
  171. *
  172. * @return array|MandrillException
  173. */
  174. public function senders_time_series($email) {
  175. return $this->request('senders/time-series', array('address' => $email));
  176. }
  177. /**
  178. * @link https://mandrillapp.com/api/docs/subaccounts.html#method=method-list
  179. *
  180. * @return array|MandrillException
  181. */
  182. public function subaccounts() {
  183. return $this->request('subaccounts/list');
  184. }
  185. /**
  186. * @link https://mandrillapp.com/api/docs/tags.html#method=list
  187. *
  188. * @return array|MandrillException
  189. */
  190. public function tags_list() {
  191. return $this->request('tags/list');
  192. }
  193. /**
  194. * @link https://mandrillapp.com/api/docs/tags.html#method=info
  195. *
  196. * @return array|MandrillException
  197. */
  198. public function tags_info($tag) {
  199. return $this->request('tags/info', array('tag' => $tag));
  200. }
  201. /**
  202. * @link https://mandrillapp.com/api/docs/tags.html#method=time-series
  203. *
  204. * @return array|MandrillException
  205. */
  206. public function tags_time_series($tag) {
  207. return $this->request('tags/time-series', array('tag' => $tag));
  208. }
  209. /**
  210. * @link https://mandrillapp.com/api/docs/tags.html#method=all-time-series
  211. *
  212. * @return array|MandrillException
  213. */
  214. public function tags_all_time_series() {
  215. return $this->request('tags/all-time-series');
  216. }
  217. /**
  218. * @link https://mandrillapp.com/api/docs/templates.html#method=add
  219. *
  220. * @return array|MandrillException
  221. */
  222. public function templates_add($name, $code) {
  223. return $this->request('templates/add', array(
  224. 'name' => $name,
  225. 'code' => $code,
  226. ));
  227. }
  228. /**
  229. * @link https://mandrillapp.com/api/docs/templates.html#method=update
  230. *
  231. * @return array|MandrillException
  232. */
  233. public function templates_update($name, $code) {
  234. return $this->request('templates/update', array(
  235. 'name' => $name,
  236. 'code' => $code,
  237. ));
  238. }
  239. /**
  240. * @link https://mandrillapp.com/api/docs/templates.html#method=delete
  241. *
  242. * @return array|MandrillException
  243. */
  244. public function templates_delete($name) {
  245. return $this->request('templates/delete', array('name' => $name));
  246. }
  247. /**
  248. * @link https://mandrillapp.com/api/docs/templates.html#method=info
  249. *
  250. * @return array|MandrillException
  251. */
  252. public function templates_info($name) {
  253. return $this->request('templates/info', array('name' => $name));
  254. }
  255. /**
  256. * @link https://mandrillapp.com/api/docs/templates.html#method=list
  257. *
  258. * @return array|MandrillException
  259. */
  260. public function templates_list() {
  261. return $this->request('templates/list');
  262. }
  263. /**
  264. * @link https://mandrillapp.com/api/docs/templates.html#method=time-series
  265. *
  266. * @return array|MandrillException
  267. */
  268. public function templates_time_series($name) {
  269. return $this->request('templates/time-series', array('name' => $name));
  270. }
  271. /**
  272. * @link https://mandrillapp.com/api/docs/urls.html#method=list
  273. *
  274. * @return array|MandrillException
  275. */
  276. public function urls_list() {
  277. return $this->request('urls/list');
  278. }
  279. /**
  280. * @link https://mandrillapp.com/api/docs/urls.html#method=time-series
  281. *
  282. * @return array|MandrillException
  283. */
  284. public function urls_time_series($url) {
  285. return $this->request('urls/time-series', array('url' => $url));
  286. }
  287. /**
  288. * @link https://mandrillapp.com/api/docs/urls.html#method=search
  289. *
  290. * @return array|MandrillException
  291. */
  292. public function urls_search($q) {
  293. return $this->request('urls/search', array('q' => $q));
  294. }
  295. /**
  296. * @link https://mandrillapp.com/api/docs/webhooks.html#method=add
  297. *
  298. * @return array|MandrillException
  299. */
  300. public function webhooks_add($url, $events) {
  301. return $this->request('webhooks/add', array(
  302. 'url' => $url,
  303. 'events' => $events,
  304. ));
  305. }
  306. /**
  307. * @link https://mandrillapp.com/api/docs/webhooks.html#method=update
  308. *
  309. * @return array|MandrillException
  310. */
  311. public function webhooks_update($id, $url, $events) {
  312. return $this->request('webhooks/update', array(
  313. 'id' => $id,
  314. 'url' => $url,
  315. 'events' => $events,
  316. ));
  317. }
  318. /**
  319. * @link https://mandrillapp.com/api/docs/webhooks.html#method=delete
  320. *
  321. * @return array|MandrillException
  322. */
  323. public function webhooks_delete($id) {
  324. return $this->request('webhooks/delete', array('id' => $id));
  325. }
  326. /**
  327. * @link https://mandrillapp.com/api/docs/webhooks.html#method=info
  328. *
  329. * @return array|MandrillException
  330. */
  331. public function webhooks_info($id) {
  332. return $this->request('webhooks/info', array('id' => $id));
  333. }
  334. /**
  335. * @link https://mandrillapp.com/api/docs/webhooks.html#method=list
  336. *
  337. * @return array|MandrillException
  338. */
  339. public function webhooks_list() {
  340. return $this->request('webhooks/list');
  341. }
  342. /**
  343. * @link https://mandrillapp.com/api/docs/messages.html#method=search
  344. *
  345. * @return array|MandrillException
  346. */
  347. public function messages_search($query, $date_from = '', $date_to = '', $tags = array(), $senders = array(), $limit = 100) {
  348. return $this->request('messages/search', compact('query', 'date_from', 'date_to', 'tags', 'senders', 'limit'));
  349. }
  350. /**
  351. * @link https://mandrillapp.com/api/docs/messages.html#method=send
  352. *
  353. * @return array|MandrillException
  354. */
  355. public function messages_send($message) {
  356. return $this->request('messages/send', array('message' => $message));
  357. }
  358. /**
  359. * @link https://mandrillapp.com/api/docs/messages.html#method=send-template
  360. *
  361. * @return array|MandrillException
  362. */
  363. public function messages_send_template($template_name, $template_content, $message) {
  364. return $this->request('messages/send-template', compact('template_name', 'template_content', 'message'));
  365. }
  366. /**
  367. * Return an array structure for a message attachment.
  368. *
  369. * @param string $path
  370. * Attachment path.
  371. *
  372. * @return array
  373. * Attachment structure.
  374. *
  375. * @throws MandrillException
  376. * @throws Exception
  377. */
  378. public static function getAttachmentStruct($path) {
  379. $struct = array();
  380. try {
  381. if (!@is_file($path)) {
  382. throw new Exception($path . ' is not a valid file.');
  383. }
  384. $filename = basename($path);
  385. if (!function_exists('get_magic_quotes')) {
  386. function get_magic_quotes() {
  387. return FALSE;
  388. }
  389. }
  390. if (!function_exists('set_magic_quotes')) {
  391. function set_magic_quotes($value) {
  392. return TRUE;
  393. }
  394. }
  395. if (strnatcmp(phpversion(), '6') >= 0) {
  396. $magic_quotes = get_magic_quotes_runtime();
  397. set_magic_quotes_runtime(0);
  398. }
  399. $file_buffer = file_get_contents($path);
  400. $file_buffer = chunk_split(base64_encode($file_buffer), 76, "\n");
  401. if (strnatcmp(phpversion(), '6') >= 0) {
  402. set_magic_quotes_runtime($magic_quotes);
  403. }
  404. $mime_type = file_get_mimetype($path);
  405. if (!DrupalMandrill::isValidContentType($mime_type)) {
  406. throw new Exception($mime_type . ' is not a valid content type (it should be ' . implode('*,', self::getValidContentTypes()) . ').');
  407. }
  408. $struct['type'] = $mime_type;
  409. $struct['name'] = $filename;
  410. $struct['content'] = $file_buffer;
  411. }
  412. catch (Exception $e) {
  413. throw new MandrillException('Error creating the attachment structure: ' . $e->getMessage());
  414. }
  415. return $struct;
  416. }
  417. /**
  418. * Helper to determine attachment is valid.
  419. *
  420. * @static
  421. *
  422. * @param $ct
  423. *
  424. * @return bool
  425. */
  426. protected static function isValidContentType($ct) {
  427. $valids = self::getValidContentTypes();
  428. foreach ($valids as $vct) {
  429. if (strpos($ct, $vct) !== FALSE) {
  430. return TRUE;
  431. }
  432. }
  433. return FALSE;
  434. }
  435. /**
  436. * Return an array of valid content types.
  437. *
  438. * @static
  439. *
  440. * @return array
  441. * Valid content types to attach to an email.
  442. */
  443. protected static function getValidContentTypes() {
  444. $valid_types = array(
  445. 'image/',
  446. 'text/',
  447. 'application/pdf',
  448. 'application/x-zip',
  449. );
  450. drupal_alter('mandrill_valid_attachment_types', $valid_types);
  451. return $valid_types;
  452. }
  453. }