1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-20 04:20:55 +01:00

Improve error and header behaviors for Mailgun received mail webhook

Summary:
Ref T10709. Two issues:

  - If a user sends an invalid `!command`, we can throw, which means we don't return HTTP 200. This makes Mailgun re-send the mail later.
  - We don't parse headers of the modern API correctly, so the "Message-ID" failsafe doesn't work. Parse them correctly. I //believe// Mailgun's API changed at some point.

Test Plan:
This is difficult to test exhaustively in isolation. I used Mailgun's web tools to verify the format of the hook request, and faked some requests locally.

I'll keep an eye on this as it goes to production and make sure the fix is correct there.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10709

Differential Revision: https://secure.phabricator.com/D15575
This commit is contained in:
epriestley 2016-04-02 10:34:13 -07:00
parent 27e13ea03f
commit a8c9a5597d

View file

@ -28,14 +28,14 @@ final class PhabricatorMetaMTAMailgunReceiveController
pht('Mail signature is not valid. Check your Mailgun API key.')); pht('Mail signature is not valid. Check your Mailgun API key.'));
} }
$user = $request->getUser(); $raw_headers = $request->getStr('message-headers');
$raw_headers = $request->getStr('headers');
$raw_headers = explode("\n", rtrim($raw_headers));
$raw_dict = array(); $raw_dict = array();
foreach (array_filter($raw_headers) as $header) { if (strlen($raw_headers)) {
list($name, $value) = explode(':', $header, 2); $raw_headers = phutil_json_decode($raw_headers);
$raw_dict[$name] = ltrim($value); foreach ($raw_headers as $raw_header) {
list($name, $value) = $raw_header;
$raw_dict[$name] = $value;
}
} }
$headers = array( $headers = array(
@ -65,9 +65,25 @@ final class PhabricatorMetaMTAMailgunReceiveController
} }
} }
$received->setAttachments($file_phids); $received->setAttachments($file_phids);
$received->save();
$received->processReceivedMail(); try {
$received->save();
$received->processReceivedMail();
} catch (Exception $ex) {
// We can get exceptions here in two cases.
// First, saving the message may throw if we have already received a
// message with the same Message ID. In this case, we're declining to
// process a duplicate message, so failing silently is correct.
// Second, processing the message may throw (for example, if it contains
// an invalid !command). This will generate an email as a side effect,
// so we don't need to explicitly handle the exception here.
// In these cases, we want to return HTTP 200. If we do not, MailGun will
// re-transmit the message later.
phlog($ex);
}
$response = new AphrontWebpageResponse(); $response = new AphrontWebpageResponse();
$response->setContent(pht("Got it! Thanks, Mailgun!\n")); $response->setContent(pht("Got it! Thanks, Mailgun!\n"));