1
0
mirror of https://github.com/axllent/mailpit.git synced 2025-04-19 12:12:26 +02:00

UI: Tab to view formatted message headers

See #71
This commit is contained in:
Ralph Slooten 2023-04-01 17:02:49 +13:00
parent f16b105d26
commit 1b798c5514
4 changed files with 77 additions and 6 deletions

View File

@ -19,7 +19,7 @@ Mailpit is inspired by [MailHog](#why-rewrite-mailhog), but much, much faster.
- Runs entirely from a single binary, no installation required
- SMTP server (default `0.0.0.0:1025`)
- Web UI to view emails (formatted HTML, highlighted HTML source, text, raw source and MIME attachments including image thumbnails)
- Web UI to view emails (formatted HTML, highlighted HTML source, text, headers, raw source and MIME attachments including image thumbnails)
- Advanced mail search ([see wiki](https://github.com/axllent/mailpit/wiki/Mail-search))
- Message tagging ([see wiki](https://github.com/axllent/mailpit/wiki/Tagging))
- Real-time web UI updates using web sockets for new mail
@ -41,10 +41,12 @@ The Mailpit web UI listens by default on `http://0.0.0.0:8025`, and the SMTP por
Mailpit runs as a single binary and can be installed in different ways:
### Install via Brew (Mac)
Add the repository to your taps with `brew tap axllent/apps`, and then install Mailpit with `brew install mailpit`.
### Install via bash script (Linux & Mac)
Linux & Mac users can install it directly to `/usr/local/bin/mailpit` with:
@ -53,14 +55,17 @@ Linux & Mac users can install it directly to `/usr/local/bin/mailpit` with:
sudo bash < <(curl -sL https://raw.githubusercontent.com/axllent/mailpit/develop/install.sh)
```
### Download static binary (Windows, Linux and Mac)
Static binaries can always be found on the [releases](https://github.com/axllent/mailpit/releases/latest). The `mailpit` binary can extracted and copied to your `$PATH`, or simply run as `./mailpit`.
### Docker
See [Docker instructions](https://github.com/axllent/mailpit/wiki/Docker-images).
### Compile from source
To build Mailpit from source see [building from source](https://github.com/axllent/mailpit/wiki/Building-from-source).

View File

@ -38,6 +38,14 @@
}
}
.nav-tabs .nav-link {
@include media-breakpoint-down(sm) {
// font-size: 14px;
padding-left: 10px;
padding-right: 10px;
}
}
#loading {
position: absolute;
top: 0;

View File

@ -0,0 +1,38 @@
<script>
import commonMixins from '../mixins.js';
export default {
props: {
message: Object
},
mixins: [commonMixins],
data() {
return {
headers: false
}
},
mounted() {
let self = this;
let uri = 'api/v1/message/' + self.message.ID + '/headers';
self.get(uri, false, function (response) {
self.headers = response.data;
});
},
}
</script>
<template>
<div v-if="headers" class="small">
<div v-for="vals, k in headers" class="row mb-2 pb-2 border-bottom w-100">
<div class="col-md-4 col-lg-3 col-xl-2 mb-2"><b>{{ k }}</b></div>
<div class="col-md-8 col-lg-9 col-xl-10 text-muted">
<div v-for="x in vals" class="mb-2 text-break">{{ x }}</div>
</div>
</div>
</div>
</template>

View File

@ -4,6 +4,7 @@ import commonMixins from '../mixins.js';
import Prism from "prismjs";
import Tags from "bootstrap5-tags";
import Attachments from './Attachments.vue';
import Headers from './Headers.vue';
export default {
props: {
@ -12,7 +13,8 @@ export default {
},
components: {
Attachments
Attachments,
Headers
},
mixins: [commonMixins],
@ -24,6 +26,7 @@ export default {
showTags: false, // to force rerendering of component
messageTags: [],
allTags: [],
loadHeaders: false
}
},
@ -34,6 +37,7 @@ export default {
self.showTags = false;
self.messageTags = self.message.Tags;
self.allTags = self.existingTags;
self.loadHeaders = false;
// delay to select first tab and add HTML highlighting (prev/next)
self.$nextTick(function () {
self.renderUI();
@ -60,9 +64,16 @@ export default {
self.allTags = self.existingTags;
window.addEventListener("resize", self.resizeIframes);
self.renderUI();
var tabEl = document.getElementById('nav-raw-tab');
tabEl.addEventListener('shown.bs.tab', function (event) {
let headersTab = document.getElementById('nav-headers-tab');
headersTab.addEventListener('shown.bs.tab', function (event) {
self.loadHeaders = true;
});
let rawTab = document.getElementById('nav-raw-tab');
rawTab.addEventListener('shown.bs.tab', function (event) {
self.srcURI = 'api/v1/message/' + self.message.ID + '/raw';
self.resizeIframes();
});
self.showTags = true;
@ -236,15 +247,21 @@ export default {
<button class="nav-link" id="nav-html-tab" data-bs-toggle="tab" data-bs-target="#nav-html" type="button"
role="tab" aria-controls="nav-html" aria-selected="true" v-if="message.HTML">HTML</button>
<button class="nav-link" id="nav-html-source-tab" data-bs-toggle="tab" data-bs-target="#nav-html-source"
type="button" role="tab" aria-controls="nav-html-source" aria-selected="false" v-if="message.HTML">HTML
Source</button>
type="button" role="tab" aria-controls="nav-html-source" aria-selected="false" v-if="message.HTML">
HTML <span class="d-sm-none">Src</span><span class="d-none d-sm-inline">Source</span>
</button>
<button class="nav-link" id="nav-plain-text-tab" data-bs-toggle="tab" data-bs-target="#nav-plain-text"
type="button" role="tab" aria-controls="nav-plain-text" aria-selected="false"
:class="message.HTML == '' ? 'show' : ''">Text</button>
<button class="nav-link" id="nav-headers-tab" data-bs-toggle="tab" data-bs-target="#nav-headers"
type="button" role="tab" aria-controls="nav-headers" aria-selected="false">
<span class="d-sm-none">Hdrs</span><span class="d-none d-sm-inline">Headers</span>
</button>
<button class="nav-link" id="nav-raw-tab" data-bs-toggle="tab" data-bs-target="#nav-raw" type="button"
role="tab" aria-controls="nav-raw" aria-selected="false">Raw</button>
</div>
</nav>
<div class="tab-content mb-5" id="nav-tabContent">
<div v-if="message.HTML != ''" class="tab-pane fade show" id="nav-html" role="tabpanel"
aria-labelledby="nav-html-tab" tabindex="0">
@ -264,6 +281,9 @@ export default {
<Attachments v-if="allAttachments(message).length" :message="message"
:attachments="allAttachments(message)"></Attachments>
</div>
<div class="tab-pane fade" id="nav-headers" role="tabpanel" aria-labelledby="nav-headers-tab" tabindex="0">
<Headers v-if="loadHeaders" :message="message"></Headers>
</div>
<div class="tab-pane fade" id="nav-raw" role="tabpanel" aria-labelledby="nav-raw-tab" tabindex="0">
<iframe v-if="srcURI" :src="srcURI" v-on:load="resizeIframe" seamless frameborder="0"
style="width: 100%; height: 300px;" id="message-src"></iframe>