public function testMailSendFailures() { $user = $this->generateNewTestUser(); $phid = $user->getPHID(); // Normally, the send should succeed. $mail = new PhabricatorMetaMTAMail(); $mail->addTos(array($phid)); $mailer = new PhabricatorMailImplementationTestAdapter(); $mail->sendNow($force = true, $mailer); $this->assertEqual(PhabricatorMetaMTAMail::STATUS_SENT, $mail->getStatus()); // When the mailer fails temporarily, the mail should remain queued. $mail = new PhabricatorMetaMTAMail(); $mail->addTos(array($phid)); $mailer = new PhabricatorMailImplementationTestAdapter(); $mailer->setFailTemporarily(true); try { $mail->sendNow($force = true, $mailer); } catch (Exception $ex) { // Ignore. } $this->assertEqual(PhabricatorMetaMTAMail::STATUS_QUEUE, $mail->getStatus()); // When the mailer fails permanently, the mail should be failed. $mail = new PhabricatorMetaMTAMail(); $mail->addTos(array($phid)); $mailer = new PhabricatorMailImplementationTestAdapter(); $mailer->setFailPermanently(true); try { $mail->sendNow($force = true, $mailer); } catch (Exception $ex) { // Ignore. } $this->assertEqual(PhabricatorMetaMTAMail::STATUS_FAIL, $mail->getStatus()); }
public function processRequest() { // Get a page of mails together with pager. $request = $this->getRequest(); $user = $request->getUser(); $offset = $request->getInt('offset', 0); $related_phid = $request->getStr('phid'); $status = $request->getStr('status'); $pager = new AphrontPagerView(); $pager->setOffset($offset); $pager->setURI($request->getRequestURI(), 'offset'); $mail = new PhabricatorMetaMTAMail(); $conn_r = $mail->establishConnection('r'); $wheres = array(); if ($status) { $wheres[] = qsprintf($conn_r, 'status = %s', $status); } if ($related_phid) { $wheres[] = qsprintf($conn_r, 'relatedPHID = %s', $related_phid); } if (count($wheres)) { $where_clause = 'WHERE ' . implode($wheres, ' AND '); } else { $where_clause = 'WHERE 1 = 1'; } $data = queryfx_all($conn_r, 'SELECT * FROM %T %Q ORDER BY id DESC LIMIT %d, %d', $mail->getTableName(), $where_clause, $pager->getOffset(), $pager->getPageSize() + 1); $data = $pager->sliceResults($data); $mails = $mail->loadAllFromArray($data); // Render the details table. $rows = array(); foreach ($mails as $mail) { $next_retry = $mail->getNextRetry() - time(); if ($next_retry <= 0) { $next_retry = "None"; } else { $next_retry = phabricator_format_relative_time_detailed($next_retry); } $rows[] = array(PhabricatorMetaMTAMail::getReadableStatus($mail->getStatus()), $mail->getRetryCount(), $next_retry, phabricator_datetime($mail->getDateCreated(), $user), phabricator_format_relative_time_detailed(time() - $mail->getDateModified()), phutil_escape_html($mail->getSubject()), phutil_render_tag('a', array('class' => 'button small grey', 'href' => $this->getApplicationURI('/view/' . $mail->getID() . '/')), 'View')); } $table = new AphrontTableView($rows); $table->setHeaders(array('Status', 'Retry', 'Next', 'Created', 'Updated', 'Subject', '')); $table->setColumnClasses(array(null, null, null, null, null, 'wide', 'action')); // Render the whole page. $panel = new AphrontPanelView(); $panel->appendChild($table); $panel->setHeader('MetaMTA Messages'); $panel->appendChild($pager); $nav = $this->buildSideNavView(); $nav->selectFilter('sent'); $nav->appendChild($panel); return $this->buildApplicationPage($nav, array('title' => 'Sent Mail')); }
public function processRequest() { // Get a page of mails together with pager. $request = $this->getRequest(); $user = $request->getUser(); $offset = $request->getInt('offset', 0); $related_phid = $request->getStr('phid'); $pager = new AphrontPagerView(); $pager->setOffset($offset); $pager->setURI($request->getRequestURI(), 'offset'); $mail = new PhabricatorMetaMTAMail(); $conn_r = $mail->establishConnection('r'); if ($related_phid) { $where_clause = qsprintf($conn_r, 'WHERE relatedPHID = %s', $related_phid); } else { $where_clause = 'WHERE 1 = 1'; } $data = queryfx_all($conn_r, 'SELECT * FROM %T %Q ORDER BY id DESC LIMIT %d, %d', $mail->getTableName(), $where_clause, $pager->getOffset(), $pager->getPageSize() + 1); $data = $pager->sliceResults($data); $mails = $mail->loadAllFromArray($data); // Render the details table. $rows = array(); foreach ($mails as $mail) { $rows[] = array(PhabricatorMetaMTAMail::getReadableStatus($mail->getStatus()), $mail->getRetryCount(), $mail->getNextRetry() - time() . ' s', phabricator_datetime($mail->getDateCreated(), $user), time() - $mail->getDateModified() . ' s', phutil_escape_html($mail->getSubject()), phutil_render_tag('a', array('class' => 'button small grey', 'href' => '/mail/view/' . $mail->getID() . '/'), 'View')); } $table = new AphrontTableView($rows); $table->setHeaders(array('Status', 'Retry', 'Next', 'Created', 'Updated', 'Subject', '')); $table->setColumnClasses(array(null, null, null, null, null, 'wide', 'action')); // Render the whole page. $panel = new AphrontPanelView(); $panel->appendChild($table); $panel->setHeader('MetaMTA Messages'); if ($user->getIsAdmin()) { $panel->setCreateButton('Send New Test Message', '/mail/send/'); } $panel->appendChild($pager); return $this->buildStandardPageResponse($panel, array('title' => 'MetaMTA', 'tab' => 'queue')); }
private function buildDeliveryProperties(PhabricatorMetaMTAMail $mail) { $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView())->setUser($viewer); $actors = $mail->getDeliveredActors(); $reasons = null; if (!$actors) { if ($mail->getStatus() == PhabricatorMailOutboundStatus::STATUS_QUEUE) { $delivery = $this->renderEmptyMessage(pht('This message has not been delivered yet, so delivery information ' . 'is not available.')); } else { $delivery = $this->renderEmptyMessage(pht('This is an older message that predates recording delivery ' . 'information, so none is available.')); } } else { $actor = idx($actors, $viewer->getPHID()); if (!$actor) { $delivery = phutil_tag('em', array(), pht('This message was not delivered to you.')); } else { $deliverable = $actor['deliverable']; if ($deliverable) { $delivery = pht('Delivered'); } else { $delivery = pht('Voided'); } $reasons = id(new PHUIStatusListView()); $reason_codes = $actor['reasons']; if (!$reason_codes) { $reason_codes = array(PhabricatorMetaMTAActor::REASON_NONE); } $icon_yes = 'fa-check green'; $icon_no = 'fa-times red'; foreach ($reason_codes as $reason) { $target = phutil_tag('strong', array(), PhabricatorMetaMTAActor::getReasonName($reason)); if (PhabricatorMetaMTAActor::isDeliveryReason($reason)) { $icon = $icon_yes; } else { $icon = $icon_no; } $item = id(new PHUIStatusItemView())->setIcon($icon)->setTarget($target)->setNote(PhabricatorMetaMTAActor::getReasonDescription($reason)); $reasons->addItem($item); } } } $properties->addProperty(pht('Delivery'), $delivery); if ($reasons) { $properties->addProperty(pht('Reasons'), $reasons); $properties->addProperty(null, $this->renderEmptyMessage(pht('Delivery reasons are listed from weakest to strongest.'))); } $properties->addSectionHeader(pht('Routing Rules'), 'fa-paper-plane-o'); $map = $mail->getDeliveredRoutingMap(); $routing_detail = null; if ($map === null) { if ($mail->getStatus() == PhabricatorMailOutboundStatus::STATUS_QUEUE) { $routing_result = $this->renderEmptyMessage(pht('This message has not been sent yet, so routing rules have ' . 'not been computed.')); } else { $routing_result = $this->renderEmptyMessage(pht('This is an older message which predates routing rules.')); } } else { $rule = idx($map, $viewer->getPHID()); if ($rule === null) { $rule = idx($map, 'default'); } if ($rule === null) { $routing_result = $this->renderEmptyMessage(pht('No routing rules applied when delivering this message to you.')); } else { $rule_const = $rule['rule']; $reason_phid = $rule['reason']; switch ($rule_const) { case PhabricatorMailRoutingRule::ROUTE_AS_NOTIFICATION: $routing_result = pht('This message was routed as a notification because it ' . 'matched %s.', $viewer->renderHandle($reason_phid)->render()); break; case PhabricatorMailRoutingRule::ROUTE_AS_MAIL: $routing_result = pht('This message was routed as an email because it matched %s.', $viewer->renderHandle($reason_phid)->render()); break; default: $routing_result = pht('Unknown routing rule "%s".', $rule_const); break; } } $routing_rules = $mail->getDeliveredRoutingRules(); if ($routing_rules) { $rules = array(); foreach ($routing_rules as $rule) { $phids = idx($rule, 'phids'); if ($phids === null) { $rules[] = $rule; } else { if (in_array($viewer->getPHID(), $phids)) { $rules[] = $rule; } } } // Reorder rules by strength. foreach ($rules as $key => $rule) { $const = $rule['routingRule']; $phids = $rule['phids']; if ($phids === null) { $type = 'A'; } else { $type = 'B'; } $rules[$key]['strength'] = sprintf('~%s%08d', $type, PhabricatorMailRoutingRule::getRuleStrength($const)); } $rules = isort($rules, 'strength'); $routing_detail = id(new PHUIStatusListView()); foreach ($rules as $rule) { $const = $rule['routingRule']; $phids = $rule['phids']; $name = PhabricatorMailRoutingRule::getRuleName($const); $icon = PhabricatorMailRoutingRule::getRuleIcon($const); $color = PhabricatorMailRoutingRule::getRuleColor($const); if ($phids === null) { $kind = pht('Global'); } else { $kind = pht('Personal'); } $target = array($kind, ': ', $name); $target = phutil_tag('strong', array(), $target); $item = id(new PHUIStatusItemView())->setTarget($target)->setNote($viewer->renderHandle($rule['reasonPHID']))->setIcon($icon, $color); $routing_detail->addItem($item); } } } $properties->addProperty(pht('Effective Rule'), $routing_result); if ($routing_detail !== null) { $properties->addProperty(pht('All Matching Rules'), $routing_detail); $properties->addProperty(null, $this->renderEmptyMessage(pht('Matching rules are listed from weakest to strongest.'))); } return $properties; }