mirror of
https://gitlab.com/ric_harvey/MailHog.git
synced 2024-12-18 10:27:16 +00:00
66ca91749f
- TODO support non-UTF-8 encodings
244 lines
8.5 KiB
HTML
244 lines
8.5 KiB
HTML
<style>
|
|
.messages {
|
|
padding-top: 51px;
|
|
height: 350px;
|
|
border-bottom: 1px solid #999;
|
|
overflow: hidden;
|
|
}
|
|
#messages-container {
|
|
height: 100%;
|
|
}
|
|
.preview #headers {
|
|
border-bottom: 1px solid #DDDDDD;
|
|
}
|
|
.selected {
|
|
background: #0066CC;
|
|
color: #fff;
|
|
}
|
|
table td, table th {
|
|
padding: 2px 4px 2px 8px !important;
|
|
}
|
|
#messages-container table tbody {
|
|
overflow: auto;
|
|
height: 260px;
|
|
}
|
|
#messages-container table tbody td {
|
|
overflow-x: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
table thead {
|
|
background: #eee;
|
|
}
|
|
#messages-container > table > thead > tr, #messages-container > table > tbody {
|
|
display: block;
|
|
}
|
|
table th:not(:last-child) {
|
|
border-right: 2px solid #DDD;
|
|
}
|
|
table#headers {
|
|
margin-bottom: 1px;
|
|
background: #eee;
|
|
}
|
|
#content .nav>li>a {
|
|
padding: 5px 8px;
|
|
}
|
|
.preview #headers tbody td {
|
|
width: 100%;
|
|
}
|
|
.preview #headers tbody th {
|
|
white-space: nowrap;
|
|
padding-right: 10px !important;
|
|
padding-left: 10px !important;
|
|
text-align: right;
|
|
color: #666;
|
|
font-weight: normal;
|
|
}
|
|
#preview-plain, #preview-source {
|
|
white-space: pre;
|
|
font-family: Courier New, Courier, System, fixed-width;
|
|
}
|
|
.preview .tab-content {
|
|
padding: 0;
|
|
overflow-y: scroll;
|
|
}
|
|
.mime-part {
|
|
padding: 10px;
|
|
}
|
|
.ui-resizable-handle.ui-resizable-s {
|
|
background: #aaa;
|
|
border-bottom: 1px solid #ccc;
|
|
}
|
|
</style>
|
|
<script>
|
|
var columns = [15,15,40,20,10];
|
|
var reflow = function() {
|
|
var remaining = 0;
|
|
if($('.preview').length > 0) {
|
|
remaining = $(window).height() - $('.preview .nav-tabs').offset().top
|
|
} else {
|
|
remaining = $('#messages-container').offset().top + $('#messages-container').height();
|
|
}
|
|
remaining -= $('.resize_bar').height();
|
|
$('.preview .tab-content').height(remaining - 32)
|
|
$('#messages-container table').height($('#messages-container').height())
|
|
$('#messages-container table tbody').height($('#messages-container').height() - $('#messages-container table thead').height())
|
|
|
|
var $table = $('#messages-container table');
|
|
var colWidth = [];
|
|
for(var i in columns) {
|
|
colWidth[i] = $table.innerWidth() / 100 * columns[i];
|
|
}
|
|
|
|
$table.find('thead tr').children().each(function(i, v) { $(v).width(colWidth[i]); });
|
|
$table.find('tbody tr:first').children().each(function(i, v) { $(v).width(colWidth[i]); });
|
|
}
|
|
$(function() {
|
|
$(".messages").resizable({"handles":"s"});
|
|
reflow();
|
|
$(window).resize(function() {
|
|
reflow();
|
|
}).resize();
|
|
})
|
|
</script>
|
|
<div class="modal fade" id="confirm-delete-all">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
<h4 class="modal-title">Delete all messages?</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Are you sure you want to delete all messages?</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-danger" ng-click="deleteAllConfirm()">Delete all messages</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal fade" id="release-one">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
<h4 class="modal-title">Release message</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>To release this message, enter a recipient and SMTP server address:</p>
|
|
<form role="form">
|
|
<div class="form-group">
|
|
<label for="release-message-email">Email address</label>
|
|
<input type="email" autofocus class="form-control" id="release-message-email" placeholder="someone@example.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="release-message-smtp-host">SMTP server</label>
|
|
<input type="text" class="form-control" id="release-message-smtp-host" placeholder="mail.example.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="release-message-smtp-port">SMTP port</label>
|
|
<input type="number" class="form-control" id="release-message-smtp-port" value="25">
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-danger" ng-click="confirmReleaseMessage()">Release message</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="messages">
|
|
<div id="messages-container">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>From</th>
|
|
<th>To</th>
|
|
<th>Subject</th>
|
|
<th>Received</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="message in messages | filter:searchText" ng-click="selectMessage(message)" ng-class="{ selected: message.ID == preview.ID }">
|
|
<td>
|
|
{{ message.From.Mailbox }}@{{ message.From.Domain }}
|
|
</td>
|
|
<td>
|
|
<span ng-repeat="to in message.To">
|
|
{{ to.Mailbox }}@{{ to.Domain }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
{{ tryDecodeMime(message.Content.Headers["Subject"][0]) }}
|
|
</td>
|
|
<td>
|
|
{{ date(message.Created) }}
|
|
</td>
|
|
<td>
|
|
<button class="btn btn-xs btn-default" title="Delete" ng-click="deleteOne(message)"><span class="glyphicon glyphicon-remove"></span></button>
|
|
<a class="btn btn-xs btn-default" title="Download" href="/api/v1/messages/{{ message.Id }}/download"><span class="glyphicon glyphicon-save"></span></a>
|
|
<button class="btn btn-xs btn-default" title="Release" ng-click="releaseOne(message)"><span class="glyphicon glyphicon-share"></span></button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="preview" ng-if="preview">
|
|
<table class="table" id="headers">
|
|
<tbody ng-if="!previewAllHeaders">
|
|
<tr>
|
|
<th>From</th>
|
|
<td>{{ tryDecodeMime(preview.Content.Headers["From"][0]) }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Subject</th>
|
|
<td><strong>{{ tryDecodeMime(preview.Content.Headers["Subject"][0]) }}</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<th>To</th>
|
|
<td>
|
|
<button id="show-headers" ng-click="toggleHeaders(true)" type="button" class="btn btn-default pull-right btn-xs">Show headers <span class="glyphicon glyphicon-chevron-down"></span></button>
|
|
{{ tryDecodeMime(preview.Content.Headers["To"].join(', ')) }}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
<tbody ng-if="previewAllHeaders">
|
|
<tr ng-repeat="(header, value) in preview.Content.Headers">
|
|
<th>
|
|
{{ tryDecodeMime(header) }}
|
|
</th>
|
|
<td>
|
|
<button id="hide-headers" ng-if="$last" ng-click="toggleHeaders(false)" type="button" class="btn btn-default pull-right btn-xs">Hide headers <span class="glyphicon glyphicon-chevron-up"></span></button>
|
|
<div ng-repeat="v in value">{{ v }}</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div id="content">
|
|
<ul class="nav nav-tabs">
|
|
<li ng-if="hasHTML(preview)" ng-class="{ active: hasHTML(preview) }"><a href="#preview-html" data-toggle="tab">HTML</a></li>
|
|
<li ng-class="{ active: !hasHTML(preview) }"><a href="#preview-plain" data-toggle="tab">Plain text</a></li>
|
|
<li><a href="#preview-source" data-toggle="tab">Source</a></li>
|
|
<li ng-if="preview.MIME"><a href="#preview-mime" data-toggle="tab">MIME</a></li>
|
|
</ul>
|
|
<div class="tab-content">
|
|
<div ng-if="hasHTML(preview)" ng-class="{ active: hasHTML(preview) }" class="tab-pane" id="preview-html" ng-bind-html="preview.previewHTML"></div>
|
|
<div class="tab-pane" ng-class="{ active: !hasHTML(preview) }" id="preview-plain">{{ tryDecodeContent(preview, getMessagePlain(preview)) }}</div>
|
|
<div class="tab-pane" id="preview-source">{{ getSource(preview) }}</div>
|
|
<div class="tab-pane" id="preview-mime">
|
|
<div ng-repeat="part in preview.MIME.Parts" class="mime-part">
|
|
<a href="/api/v1/messages/{{ preview.Id }}/mime/part/{{ $index }}/download" type="button" class="btn btn-default btn-sm">
|
|
<span class="glyphicon glyphicon-save"></span>
|
|
Download
|
|
</a>
|
|
{{ part.Headers["Content-Type"][0] || "Unknown type" }} ({{ part.Size }} bytes)
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|