@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at recaptime-dev/main 452 lines 13 kB view raw
1<?php 2 3final class PhabricatorMetaMTAMailViewController 4 extends PhabricatorMetaMTAController { 5 6 public function handleRequest(AphrontRequest $request) { 7 $viewer = $this->getViewer(); 8 9 $mail = id(new PhabricatorMetaMTAMailQuery()) 10 ->setViewer($viewer) 11 ->withIDs(array($request->getURIData('id'))) 12 ->executeOne(); 13 if (!$mail) { 14 return new Aphront404Response(); 15 } 16 17 if ($mail->hasSensitiveContent()) { 18 $title = pht('Content Redacted'); 19 } else { 20 $title = $mail->getSubject(); 21 } 22 23 $header = id(new PHUIHeaderView()) 24 ->setHeader($title) 25 ->setUser($viewer) 26 ->setPolicyObject($mail) 27 ->setHeaderIcon('fa-envelope'); 28 29 $status = $mail->getStatus(); 30 $name = PhabricatorMailOutboundStatus::getStatusName($status); 31 $icon = PhabricatorMailOutboundStatus::getStatusIcon($status); 32 $color = PhabricatorMailOutboundStatus::getStatusColor($status); 33 $header->setStatus($icon, $color, $name); 34 35 if ($mail->getMustEncrypt()) { 36 Javelin::initBehavior('phabricator-tooltips'); 37 $header->addTag( 38 id(new PHUITagView()) 39 ->setType(PHUITagView::TYPE_SHADE) 40 ->setColor('blue') 41 ->setName(pht('Must Encrypt')) 42 ->setIcon('fa-shield blue') 43 ->addSigil('has-tooltip') 44 ->setMetadata( 45 array( 46 'tip' => pht( 47 'Message content can only be transmitted over secure '. 48 'channels.'), 49 ))); 50 } 51 52 $crumbs = $this->buildApplicationCrumbs() 53 ->addTextCrumb(pht('Mail %d', $mail->getID())) 54 ->setBorder(true); 55 56 $tab_group = id(new PHUITabGroupView()) 57 ->addTab( 58 id(new PHUITabView()) 59 ->setName(pht('Message')) 60 ->setKey('message') 61 ->appendChild($this->buildMessageProperties($mail))) 62 ->addTab( 63 id(new PHUITabView()) 64 ->setName(pht('Headers')) 65 ->setKey('headers') 66 ->appendChild($this->buildHeaderProperties($mail))) 67 ->addTab( 68 id(new PHUITabView()) 69 ->setName(pht('Delivery')) 70 ->setKey('delivery') 71 ->appendChild($this->buildDeliveryProperties($mail))) 72 ->addTab( 73 id(new PHUITabView()) 74 ->setName(pht('Metadata')) 75 ->setKey('metadata') 76 ->appendChild($this->buildMetadataProperties($mail))); 77 78 $header_view = id(new PHUIHeaderView()) 79 ->setHeader(pht('Mail')); 80 81 $object_phid = $mail->getRelatedPHID(); 82 if ($object_phid) { 83 $handles = $viewer->loadHandles(array($object_phid)); 84 $handle = $handles[$object_phid]; 85 if ($handle->isComplete() && $handle->getURI()) { 86 $view_button = id(new PHUIButtonView()) 87 ->setTag('a') 88 ->setText(pht('View Object')) 89 ->setIcon('fa-chevron-right') 90 ->setHref($handle->getURI()); 91 92 $header_view->addActionLink($view_button); 93 } 94 } 95 96 $object_box = id(new PHUIObjectBoxView()) 97 ->setHeader($header_view) 98 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 99 ->addTabGroup($tab_group); 100 101 $view = id(new PHUITwoColumnView()) 102 ->setHeader($header) 103 ->setFooter($object_box); 104 105 return $this->newPage() 106 ->setTitle($title) 107 ->setCrumbs($crumbs) 108 ->setPageObjectPHIDs(array($mail->getPHID())) 109 ->appendChild($view); 110 } 111 112 private function buildMessageProperties(PhabricatorMetaMTAMail $mail) { 113 $viewer = $this->getViewer(); 114 115 $properties = id(new PHUIPropertyListView()) 116 ->setUser($viewer) 117 ->setObject($mail); 118 119 if ($mail->getFrom()) { 120 $from_str = $viewer->renderHandle($mail->getFrom()); 121 } else { 122 $from_str = pht( 123 'Sent by %s', 124 PlatformSymbols::getPlatformServerName()); 125 } 126 $properties->addProperty( 127 pht('From'), 128 $from_str); 129 130 if ($mail->getToPHIDs()) { 131 $to_list = $viewer->renderHandleList($mail->getToPHIDs()); 132 } else { 133 $to_list = pht('None'); 134 } 135 $properties->addProperty( 136 pht('To'), 137 $to_list); 138 139 if ($mail->getCcPHIDs()) { 140 $cc_list = $viewer->renderHandleList($mail->getCcPHIDs()); 141 } else { 142 $cc_list = pht('None'); 143 } 144 $properties->addProperty( 145 pht('Cc'), 146 $cc_list); 147 148 $properties->addProperty( 149 pht('Sent'), 150 phabricator_datetime($mail->getDateCreated(), $viewer)); 151 152 $properties->addSectionHeader( 153 pht('Message'), 154 PHUIPropertyListView::ICON_SUMMARY); 155 156 if ($mail->hasSensitiveContent()) { 157 $body = phutil_tag( 158 'em', 159 array(), 160 pht( 161 'The content of this mail is sensitive and it can not be '. 162 'viewed from the web UI.')); 163 } else { 164 $body = phutil_tag( 165 'div', 166 array( 167 'style' => 'white-space: pre-wrap', 168 ), 169 $mail->getBody()); 170 } 171 172 $properties->addTextContent($body); 173 174 $file_phids = $mail->getAttachmentFilePHIDs(); 175 if ($file_phids) { 176 $properties->addProperty( 177 pht('Attached Files'), 178 $viewer->loadHandles($file_phids)->renderList()); 179 } 180 181 return $properties; 182 } 183 184 private function buildHeaderProperties(PhabricatorMetaMTAMail $mail) { 185 $viewer = $this->getViewer(); 186 187 $properties = id(new PHUIPropertyListView()) 188 ->setUser($viewer) 189 ->setStacked(true); 190 191 $headers = $mail->getDeliveredHeaders(); 192 if (!$headers) { 193 $headers = array(); 194 } 195 196 // Sort headers by name. 197 $headers = isort($headers, '0'); 198 199 foreach ($headers as $header) { 200 list($key, $value) = $header; 201 $properties->addProperty($key, $value); 202 } 203 204 $encrypt_phids = $mail->getMustEncryptReasons(); 205 if ($encrypt_phids) { 206 $properties->addProperty( 207 pht('Must Encrypt'), 208 $viewer->loadHandles($encrypt_phids) 209 ->renderList()); 210 } 211 212 213 return $properties; 214 } 215 216 private function buildDeliveryProperties(PhabricatorMetaMTAMail $mail) { 217 $viewer = $this->getViewer(); 218 219 $properties = id(new PHUIPropertyListView()) 220 ->setUser($viewer); 221 222 $actors = $mail->getDeliveredActors(); 223 $reasons = null; 224 if (!$actors) { 225 if ($mail->getStatus() == PhabricatorMailOutboundStatus::STATUS_QUEUE) { 226 $delivery = $this->renderEmptyMessage( 227 pht( 228 'This message has not been delivered yet, so delivery information '. 229 'is not available.')); 230 } else { 231 $delivery = $this->renderEmptyMessage( 232 pht( 233 'This is an older message that predates recording delivery '. 234 'information, so none is available.')); 235 } 236 } else { 237 $actor = idx($actors, $viewer->getPHID()); 238 if (!$actor) { 239 $delivery = phutil_tag( 240 'em', 241 array(), 242 pht('This message was not delivered to you.')); 243 } else { 244 $deliverable = $actor['deliverable']; 245 if ($deliverable) { 246 $delivery = pht('Delivered'); 247 } else { 248 $delivery = pht('Voided'); 249 } 250 251 $reasons = new PHUIStatusListView(); 252 253 $reason_codes = $actor['reasons']; 254 if (!$reason_codes) { 255 $reason_codes = array( 256 PhabricatorMetaMTAActor::REASON_NONE, 257 ); 258 } 259 260 $icon_yes = 'fa-check green'; 261 $icon_no = 'fa-times red'; 262 263 foreach ($reason_codes as $reason) { 264 $target = phutil_tag( 265 'strong', 266 array(), 267 PhabricatorMetaMTAActor::getReasonName($reason)); 268 269 if (PhabricatorMetaMTAActor::isDeliveryReason($reason)) { 270 $icon = $icon_yes; 271 } else { 272 $icon = $icon_no; 273 } 274 275 $item = id(new PHUIStatusItemView()) 276 ->setIcon($icon) 277 ->setTarget($target) 278 ->setNote(PhabricatorMetaMTAActor::getReasonDescription($reason)); 279 280 $reasons->addItem($item); 281 } 282 } 283 } 284 285 $properties->addProperty(pht('Delivery'), $delivery); 286 if ($reasons) { 287 $properties->addProperty(pht('Reasons'), $reasons); 288 $properties->addProperty( 289 null, 290 $this->renderEmptyMessage( 291 pht( 292 'Delivery reasons are listed from weakest to strongest.'))); 293 } 294 295 $properties->addSectionHeader( 296 pht('Routing Rules'), 'fa-paper-plane-o'); 297 298 $map = $mail->getDeliveredRoutingMap(); 299 $routing_detail = null; 300 if ($map === null) { 301 if ($mail->getStatus() == PhabricatorMailOutboundStatus::STATUS_QUEUE) { 302 $routing_result = $this->renderEmptyMessage( 303 pht( 304 'This message has not been sent yet, so routing rules have '. 305 'not been computed.')); 306 } else { 307 $routing_result = $this->renderEmptyMessage( 308 pht( 309 'This is an older message which predates routing rules.')); 310 } 311 } else { 312 $rule = idx($map, $viewer->getPHID()); 313 if ($rule === null) { 314 $rule = idx($map, 'default'); 315 } 316 317 if ($rule === null) { 318 $routing_result = $this->renderEmptyMessage( 319 pht( 320 'No routing rules applied when delivering this message to you.')); 321 } else { 322 $rule_const = $rule['rule']; 323 $reason_phid = $rule['reason']; 324 switch ($rule_const) { 325 case PhabricatorMailRoutingRule::ROUTE_AS_NOTIFICATION: 326 $routing_result = pht( 327 'This message was routed as a notification because it '. 328 'matched %s.', 329 $viewer->renderHandle($reason_phid)->render()); 330 break; 331 case PhabricatorMailRoutingRule::ROUTE_AS_MAIL: 332 $routing_result = pht( 333 'This message was routed as an email because it matched %s.', 334 $viewer->renderHandle($reason_phid)->render()); 335 break; 336 default: 337 $routing_result = pht('Unknown routing rule "%s".', $rule_const); 338 break; 339 } 340 } 341 342 $routing_rules = $mail->getDeliveredRoutingRules(); 343 if ($routing_rules) { 344 $rules = array(); 345 foreach ($routing_rules as $rule) { 346 $phids = idx($rule, 'phids'); 347 if ($phids === null) { 348 $rules[] = $rule; 349 } else if (in_array($viewer->getPHID(), $phids)) { 350 $rules[] = $rule; 351 } 352 } 353 354 // Reorder rules by strength. 355 foreach ($rules as $key => $rule) { 356 $const = $rule['routingRule']; 357 $phids = $rule['phids']; 358 359 if ($phids === null) { 360 $type = 'A'; 361 } else { 362 $type = 'B'; 363 } 364 365 $rules[$key]['strength'] = sprintf( 366 '~%s%08d', 367 $type, 368 PhabricatorMailRoutingRule::getRuleStrength($const)); 369 } 370 $rules = isort($rules, 'strength'); 371 372 $routing_detail = new PHUIStatusListView(); 373 foreach ($rules as $rule) { 374 $const = $rule['routingRule']; 375 $phids = $rule['phids']; 376 377 $name = PhabricatorMailRoutingRule::getRuleName($const); 378 379 $icon = PhabricatorMailRoutingRule::getRuleIcon($const); 380 $color = PhabricatorMailRoutingRule::getRuleColor($const); 381 382 if ($phids === null) { 383 $kind = pht('Global'); 384 } else { 385 $kind = pht('Personal'); 386 } 387 388 $target = array($kind, ': ', $name); 389 $target = phutil_tag('strong', array(), $target); 390 391 $item = id(new PHUIStatusItemView()) 392 ->setTarget($target) 393 ->setNote($viewer->renderHandle($rule['reasonPHID'])) 394 ->setIcon($icon, $color); 395 396 $routing_detail->addItem($item); 397 } 398 } 399 } 400 401 $properties->addProperty(pht('Effective Rule'), $routing_result); 402 403 if ($routing_detail !== null) { 404 $properties->addProperty(pht('All Matching Rules'), $routing_detail); 405 $properties->addProperty( 406 null, 407 $this->renderEmptyMessage( 408 pht( 409 'Matching rules are listed from weakest to strongest.'))); 410 } 411 412 return $properties; 413 } 414 415 private function buildMetadataProperties(PhabricatorMetaMTAMail $mail) { 416 $viewer = $this->getViewer(); 417 418 $properties = id(new PHUIPropertyListView()) 419 ->setUser($viewer); 420 421 $properties->addProperty(pht('Message PHID'), $mail->getPHID()); 422 423 $details = $mail->getMessage(); 424 if (!phutil_nonempty_string($details)) { 425 $details = phutil_tag('em', array(), pht('None')); 426 } 427 $properties->addProperty(pht('Status Details'), $details); 428 429 $actor_phid = $mail->getActorPHID(); 430 if ($actor_phid) { 431 $actor_str = $viewer->renderHandle($actor_phid); 432 } else { 433 $actor_str = pht('Generated by Server'); 434 } 435 $properties->addProperty(pht('Actor'), $actor_str); 436 437 $related_phid = $mail->getRelatedPHID(); 438 if ($related_phid) { 439 $related = $viewer->renderHandle($mail->getRelatedPHID()); 440 } else { 441 $related = phutil_tag('em', array(), pht('None')); 442 } 443 $properties->addProperty(pht('Related Object'), $related); 444 445 return $properties; 446 } 447 448 private function renderEmptyMessage($message) { 449 return phutil_tag('em', array(), $message); 450 } 451 452}