Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/metamta/controller/PhabricatorMetaMTAMailViewController.php
12256 views
1
<?php
2
3
final 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 = id(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 = id(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 ($details === null || !strlen($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
}
453
454