| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 | <?php/** * @file * Provides integration with Mailgun's email sending API. *//** * Implements hook_menu(). */function mailgun_menu() {  $items = array();  $items['admin/config/system/mailgun'] = array(    'title' => 'Mailgun',    'description' => 'Configure Mailgun settings.',    'page callback' => 'drupal_get_form',    'page arguments' => array('mailgun_admin_settings'),    'access arguments' => array('administer mailgun'),    'file' => 'mailgun.admin.inc',  );  $items['admin/config/system/mailgun/settings'] = array(    'title' => 'Settings',    'type' => MENU_DEFAULT_LOCAL_TASK,    'weight' => 0,  );  $items['admin/config/system/mailgun/test'] = array(    'title' => 'Send test email',    'page callback' => 'drupal_get_form',    'page arguments' => array('mailgun_test_form'),    'access arguments' => array('administer mailgun'),    'description' => 'Send a test e-mail using the Mailgun API.',    'file' => 'mailgun.admin.inc',    'type' => MENU_LOCAL_TASK,    'weight' => 1,  );  return $items;}/** * Implements hook_permission(). */function mailgun_permission() {  return array(    'administer mailgun' => array(      'title' => t('Administer Mailgun'),      'description' => t('Perform administration tasks for the Mailgun e-mail sending service.'),      "restrict access" => TRUE,    ),  );}/** * Implements hook_help(). */function mailgun_help($path, $arg) {  switch ($path) {    case 'admin/config/system/mailgun':      return '<p>' . t('See <a href="@url">documentation</a> for instructions on installing and configuring Mailgun.', array('@url' => url('https://www.drupal.org/node/2547591'))) . '</p>';      break;    case 'admin/config/system/mailgun/test':      return '<p>' . t('Use this form to send a test e-mail to ensure you have correctly configured Mailgun.') . '</p>';      break;  }}/** * Implements hook_cron_queue_info(). */function mailgun_cron_queue_info() {  $queues = array();  $queues['mailgun_queue'] = array(    'worker callback' => 'mailgun_send',    'time' => 60,  );  return $queues;}/** * Implements hook_mail(). */function mailgun_mail($key, &$message, $params) {  switch ($key) {    case 'test':      $message['subject'] = t('Mailgun test email');      $message['body'] = $params['message'];      if ($params['attachment']) {        $message['params']['attachments'] = array(drupal_realpath('misc/druplicon.png'));      }      break;  }}/** * Implements hook_libraries_info(). */function mailgun_libraries_info() {  $libraries['mailgun'] = array(    'name' => 'Mailgun PHP library',    'vendor url' => 'https://documentation.mailgun.com/wrappers.html#php',    'download url' => 'https://github.com/mailgun/mailgun-php/archive/v1.7.2.zip',    'path' => 'vendor',    'version arguments' => array(      'file' => 'src/Mailgun/Constants/Constants.php',      // const SDK_VERSION = "1.7";      'pattern' => '/const SDK_VERSION = \"((\d+)\.(\d+))\";/',    ),    'files' => array(      'php' => array('autoload.php'),    ),  );  return $libraries;}/** * Get the Mailgun client to access Mailgun's endpoints. * * @param string $key *   The Mailgun API key. Leave empty to use the API key saved in database. */function mailgun_get_client($key = '') {  // Check if the Mailgun PHP library is installed.  $library = libraries_load('mailgun');  if (!$library['installed']) {    watchdog('mailgun', 'Mailgun client initialization failed: Unable to load the Mailgun PHP library.', NULL, WATCHDOG_ERROR);    return FALSE;  }  $key = (empty($key)) ? variable_get('mailgun_api_key', '') : $key;  if (empty($key)) {    watchdog('mailgun', 'Mailgun client initialization failed: Missing API key.', NULL, WATCHDOG_ERROR);    return FALSE;  }  $client = new \Mailgun\Mailgun($key);  return $client;}/** * Send an e-mail using the Mailgun API. * * @param array $mailgun_message *   A Mailgun message array. Contains the following keys: *   - from: The e-mail addressthe message will be sent from. *   - to: The e-mail addressthe message will be sent to. *   - subject: The subject of the message. *   - text: The plain-text version of the message. Processed using check_plain(). *   - html: The original message content. May contain HTML tags. *   - cc: One or more carbon copy recipients. If multiple, separate with commas. *   - bcc: One or more blind carbon copy recipients. If multiple, separate with commas. *   - o:tag: An array containing the tags to add to the message. See: https://documentation.mailgun.com/user_manual.html#tagging. *   - o:campaign: The campaign ID this message belongs to. See: https://documentation.mailgun.com/user_manual.html#um-campaign-analytics. *   - o:deliverytime: Desired time of delivery. Messages can be scheduled for a maximum of 3 days in the future. See: https://documentation.mailgun.com/api-intro.html#date-format. *   - o:dkim: Boolean indicating whether or not to enable DKIM signatures on per-message basis. *   - o:testmode: Boolean indicating whether or not to enable test mode. See: https://documentation.mailgun.com/user_manual.html#manual-testmode. *   - o:tracking: Boolean indicating whether or not to toggle tracking on a per-message basis. See: https://documentation.mailgun.com/user_manual.html#tracking-messages. *   - o:tracking-clicks: Boolean or string "htmlonly" indicating whether or not to toggle clicks tracking on a per-message basis. Has higher priority than domain-level setting. *   - o:tracking-opens: Boolean indicating whether or not to toggle clicks tracking on a per-message basis. Has higher priority than domain-level setting. *   - h:X-My-Header: h: prefix followed by an arbitrary value allows to append a custom MIME header to the message (X-My-Header in this case). For example, h:Reply-To to specify Reply-To address. *   - v:my-var: v: prefix followed by an arbitrary name allows to attach a custom JSON data to the message. See: https://documentation.mailgun.com/user_manual.html#manual-customdata. * * @return bool *   TRUE if the mail was successfully accepted, FALSE otherwise. */function mailgun_send($mailgun_message) {  $client = mailgun_get_client();  if (!$client) {    return FALSE;  }  // Test mode  if (variable_get('mailgun_test', FALSE)) {    $mailgun_message['o:testmode'] = 'yes';  }  // Merge the $mailgun_message array with options.  $mailgun_message += $mailgun_message['params'];  unset($mailgun_message['params']);  if (variable_get('mailgun_domain', '_sender') == '_sender') {    // Extract the domain from the sender's email address. Use regular expression to check since it could be either a plain email address or in the form "Name <example@example.com>".    $tokens = (preg_match('/^\s*(.+?)\s*<\s*([^>]+)\s*>$/', $mailgun_message['from'], $matches) === 1) ? explode('@', $matches[2]) : explode('@', $mailgun_message['from']);    $mail_domain = array_pop($tokens);    // Retrieve a list of available domains first.    $domains = array();    try {      $result = $client->get('domains');      if ($result->http_response_code == 200) {        foreach ($result->http_response_body->items as $item) {          $domains[$item->name] = $item->name;        }      }      else {        watchdog('mailgun', 'Mailgun server returned a %code error. Could not retrieve domain list.', array('%code' => $result->http_response_code), WATCHDOG_ERROR);      }    } catch (Exception $e) {      watchdog('mailgun', 'An exception occurred while retrieving domains. @code: @message', array('@code' => $e->getCode(), '@message' => $e->getMessage()), WATCHDOG_ERROR);    }    if (empty($domains)) {      // No domain available. Although this shouldn't happen, doesn't hurt to check.      return FALSE;    }    // Now, we need to get the working domain. This is generally the domain the From address is on or the root domain of it.    $working_domain = '';    if ($key = array_search($mail_domain, $domains) !== FALSE) {      // Great. Found it.      $working_domain = $mail_domain;    }    else {      // Oops. No match. Perhaps it's a subdomain instead.      foreach ($domains as $domain) {        if (strpos($domain, $mail_domain) !== FALSE) {          // Got it.          $working_domain = $domain;          break;        }      }    }    // There is a chance that the user is attempting to send from an email address that's on a domain not yet added to the Mailgun account.    // In that case, abort sending and report error.    if (empty($working_domain)) {      watchdog('mailgun', 'Unable to locate a working domain for From address %mail. Aborting sending.', array('%mail' => $mailgun_message['from']), WATCHDOG_ERROR);      return FALSE;    }  }  else {    $working_domain = variable_get('mailgun_domain', '');  }  // Attachments  $post_data = array();  if (!empty($mailgun_message['attachments'])) {    // Send message with attachments.    $post_data['attachment'] = $mailgun_message['attachments'];    unset($mailgun_message['attachments']);  }    try {    $result = $client->sendMessage($working_domain, $mailgun_message, $post_data);    // For a list of HTTP response codes, see: https://documentation.mailgun.com/api-intro.html#errors.    if ($result->http_response_code == 200) {      if (variable_get('mailgun_log', FALSE)) {        watchdog('mailgun', 'Successfully sent message from %from to %to. %code: %message.', array('%from' => $mailgun_message['from'], '%to' => $mailgun_message['to'], '%code' => $result->http_response_code, '%message' => $result->http_response_body->message));      }      return TRUE;    }    else {      watchdog('mailgun', 'Failed to send message from %from to %to. %code: %message.', array('%from' => $mailgun_message['from'], '%to' => $mailgun_message['to'], '%code' => $result->http_response_code, '%message' => $result->http_response_body->message), WATCHDOG_ERROR);      return FALSE;    }  } catch (Exception $e) {    watchdog('mailgun', 'Exception occurred while trying to send test email from %from to %to. @code: @message.', array('%from' => $mailgun_message['from'], '%to' => $mailgun_message['to'], '@code' => $e->getCode(), '@message' => $e->getMessage()));  }}
 |