4 * Mail adapter that uses Mailgun's web API to deliver email.
6 final class PhabricatorMailMailgunAdapter
7 extends PhabricatorMailAdapter
{
9 const ADAPTERTYPE
= 'mailgun';
11 public function getSupportedMessageTypes() {
13 PhabricatorMailEmailMessage
::MESSAGETYPE
,
17 public function supportsMessageIDHeader() {
21 protected function validateOptions(array $options) {
22 PhutilTypeSpec
::checkMap(
25 'api-key' => 'string',
27 'api-hostname' => 'string',
31 public function newDefaultOptions() {
35 'api-hostname' => 'api.mailgun.net',
39 public function sendMessage(PhabricatorMailExternalMessage
$message) {
40 $api_key = $this->getOption('api-key');
41 $domain = $this->getOption('domain');
42 $api_hostname = $this->getOption('api-hostname');
45 $subject = $message->getSubject();
46 if ($subject !== null) {
47 $params['subject'] = $subject;
50 $from_address = $message->getFromAddress();
52 $params['from'] = (string)$from_address;
55 $to_addresses = $message->getToAddresses();
58 foreach ($to_addresses as $address) {
59 $to[] = (string)$address;
61 $params['to'] = implode(', ', $to);
64 $cc_addresses = $message->getCCAddresses();
67 foreach ($cc_addresses as $address) {
68 $cc[] = (string)$address;
70 $params['cc'] = implode(', ', $cc);
73 $reply_address = $message->getReplyToAddress();
75 $params['h:reply-to'] = (string)$reply_address;
78 $headers = $message->getHeaders();
80 foreach ($headers as $header) {
81 $name = $header->getName();
82 $value = $header->getValue();
83 $params['h:'.$name] = $value;
87 $text_body = $message->getTextBody();
88 if ($text_body !== null) {
89 $params['text'] = $text_body;
92 $html_body = $message->getHTMLBody();
93 if ($html_body !== null) {
94 $params['html'] = $html_body;
97 $mailgun_uri = urisprintf(
98 'https://%s/v2/%s/messages',
102 $future = id(new HTTPSFuture($mailgun_uri, $params))
104 ->setHTTPBasicAuthCredentials('api', new PhutilOpaqueEnvelope($api_key))
107 $attachments = $message->getAttachments();
108 foreach ($attachments as $attachment) {
109 $future->attachFileData(
111 $attachment->getData(),
112 $attachment->getFilename(),
113 $attachment->getMimeType());
116 list($body) = $future->resolvex();
120 $response = phutil_json_decode($body);
121 } catch (PhutilJSONParserException
$ex) {
122 throw new PhutilProxyException(
123 pht('Failed to JSON decode response.'),
127 if (!idx($response, 'id')) {
128 $message = $response['message'];
131 'Request failed with errors: %s.',