mirror of
https://github.com/axllent/mailpit.git
synced 2025-01-22 03:39:59 +02:00
Merge branch 'release/v1.6.20'
This commit is contained in:
commit
3431f18a3f
@ -2,6 +2,15 @@
|
||||
|
||||
Notable changes to Mailpit will be documented in this file.
|
||||
|
||||
## [v1.6.20]
|
||||
|
||||
### Feature
|
||||
- Convert links into clickable hyperlinks in plain text message content
|
||||
|
||||
### Libs
|
||||
- Update node modules
|
||||
|
||||
|
||||
## [v1.6.19]
|
||||
|
||||
### Fix
|
||||
|
67
package-lock.json
generated
67
package-lock.json
generated
@ -36,9 +36,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.4.tgz",
|
||||
"integrity": "sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz",
|
||||
"integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
@ -47,9 +47,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime-corejs3": {
|
||||
"version": "7.22.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.3.tgz",
|
||||
"integrity": "sha512-6bdmknScYKmt8I9VjsJuKKGr+TwUb555FTf6tT1P/ANlCjTHCiYLhiQ4X/O7J731w5NOqu8c1aYHEVuOwPz7jA==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.5.tgz",
|
||||
"integrity": "sha512-TNPDN6aBFaUox2Lu+H/Y1dKKQgr4ucz/FGyCz67RVYLsBpVpUFf1dDngzg+Od8aqbrqwyztkaZjtWCZEUOT8zA==",
|
||||
"dependencies": {
|
||||
"core-js-pure": "^3.30.2",
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
@ -421,9 +421,9 @@
|
||||
"integrity": "sha512-kXOeFbfCm4fFf2A3WwVEeQj55tMZa8c8/f9AKHMobQMkzNUfUj+antR3fRPaZJawsa1aZiP/Da3ndpZrwEe4rQ=="
|
||||
},
|
||||
"node_modules/@lit/reactive-element": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.1.tgz",
|
||||
"integrity": "sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==",
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.2.tgz",
|
||||
"integrity": "sha512-rDfl+QnCYjuIGf5xI2sVJWdYIi56CTCwWa+nidKYX6oIuBYwUbT/vX4qbUDlHiZKJ/3FRNQ/tWJui44p6/stSA==",
|
||||
"dependencies": {
|
||||
"@lit-labs/ssr-dom-shim": "^1.0.0"
|
||||
}
|
||||
@ -1063,9 +1063,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/bootstrap5-tags": {
|
||||
"version": "1.5.22",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap5-tags/-/bootstrap5-tags-1.5.22.tgz",
|
||||
"integrity": "sha512-wRpPtBBql6FvXKdSKUgFBkmmkGgsZJCzZ0bC9DvfHKylnQ4gS2pHpXB2UkIEWa/c+vENbBIyUDMSAvcZ4ujyQg=="
|
||||
"version": "1.5.24",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap5-tags/-/bootstrap5-tags-1.5.24.tgz",
|
||||
"integrity": "sha512-+mH9WfNnz81CFoyui8G166YLe0ASEiSPb17DMdejCVdIOu7YGuSmYFfCAz/oqdD09vKege9yU6/YyXPOlGURGQ=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
@ -1201,9 +1201,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/core-js-pure": {
|
||||
"version": "3.30.2",
|
||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.30.2.tgz",
|
||||
"integrity": "sha512-p/npFUJXXBkCCTIlEGBdghofn00jWG6ZOtdoIXSJmAu2QBvN0IqpZXWweOytcwE6cfx8ZvVUy1vw8zxhe4Y2vg==",
|
||||
"version": "3.31.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.31.0.tgz",
|
||||
"integrity": "sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg==",
|
||||
"hasInstallScript": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@ -1683,9 +1683,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lit": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/lit/-/lit-2.7.4.tgz",
|
||||
"integrity": "sha512-cgD7xrZoYr21mbrkZIuIrj98YTMw/snJPg52deWVV4A8icLyNHI3bF70xsJeAgwTuiq5Kkd+ZR8gybSJDCPB7g==",
|
||||
"version": "2.7.5",
|
||||
"resolved": "https://registry.npmjs.org/lit/-/lit-2.7.5.tgz",
|
||||
"integrity": "sha512-i/cH7Ye6nBDUASMnfwcictBnsTN91+aBjXoTHF2xARghXScKxpD4F4WYI+VLXg9lqbMinDfvoI7VnZXjyHgdfQ==",
|
||||
"dependencies": {
|
||||
"@lit/reactive-element": "^1.6.0",
|
||||
"lit-element": "^3.3.0",
|
||||
@ -2062,9 +2062,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||
"integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.11.2",
|
||||
@ -2080,15 +2080,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/querystring": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||
"integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
|
||||
"deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
|
||||
"engines": {
|
||||
"node": ">=0.4.x"
|
||||
}
|
||||
},
|
||||
"node_modules/ramda": {
|
||||
"version": "0.29.0",
|
||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz",
|
||||
@ -2209,9 +2200,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.62.1",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz",
|
||||
"integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==",
|
||||
"version": "1.63.4",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.63.4.tgz",
|
||||
"integrity": "sha512-Sx/+weUmK+oiIlI+9sdD0wZHsqpbgQg8wSwSnGBjwb5GwqFhYNwwnI+UWZtLjKvKyFlKkatRK235qQ3mokyPoQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
@ -2526,12 +2517,12 @@
|
||||
"integrity": "sha512-tdOvLfRzHolwYcHS6HIX860MkK9LQ4+oLuNwFYL7bpgTEO64PZrcQxkisgwJYCfF8sKiWLwwu1c83DvMkbefIQ=="
|
||||
},
|
||||
"node_modules/url": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
|
||||
"integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/url/-/url-0.11.1.tgz",
|
||||
"integrity": "sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA==",
|
||||
"dependencies": {
|
||||
"punycode": "1.3.2",
|
||||
"querystring": "0.2.0"
|
||||
"punycode": "^1.4.1",
|
||||
"qs": "^6.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
|
@ -163,6 +163,27 @@ export default {
|
||||
self.scrollInPlace = true;
|
||||
self.$emit('loadMessages');
|
||||
});
|
||||
},
|
||||
|
||||
// Convert plain text to HTML including anchor links
|
||||
textToHTML: function (s) {
|
||||
// escape to HTML
|
||||
let html = s
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'")
|
||||
|
||||
// full links with http(s)
|
||||
let re = /(\b(https?|ftp):\/\/[\-\w@:%_\+.~#?,&\/\/=;]+)\b/gim
|
||||
html = html.replace(re, '<a href="$&" target="_blank" rel="noopener">$&</a>')
|
||||
|
||||
// plain www links without https?:// prefix
|
||||
let re2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim
|
||||
html = html.replace(re2, '$1<a href="http://$2" target="_blank" rel="noopener">$2</a>')
|
||||
|
||||
return html
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -272,28 +293,28 @@ export default {
|
||||
role="tab" aria-controls="nav-html" aria-selected="true" v-if="message.HTML"
|
||||
v-on:click="showMobileBtns = true; resizeIframes()">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 "
|
||||
v-on:click=" showMobileBtns = false ">
|
||||
type="button" role="tab" aria-controls="nav-html-source" aria-selected="false" v-if="message.HTML"
|
||||
v-on:click=" showMobileBtns = false">
|
||||
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' : '' " v-on:click=" showMobileBtns = false ">Text</button>
|
||||
:class="message.HTML == '' ? 'show' : ''" v-on:click=" showMobileBtns = false">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"
|
||||
v-on:click=" showMobileBtns = false ">
|
||||
v-on:click=" showMobileBtns = 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"
|
||||
v-on:click=" showMobileBtns = false ">Raw</button>
|
||||
v-on:click=" showMobileBtns = false">Raw</button>
|
||||
|
||||
<div class="d-none d-lg-block ms-auto me-2" v-if=" showMobileBtns ">
|
||||
<div class="d-none d-lg-block ms-auto me-2" v-if="showMobileBtns">
|
||||
<template v-for=" vals, key in responsiveSizes ">
|
||||
<button class="btn" :class=" scaleHTMLPreview == key ? 'btn-outline-primary' : '' "
|
||||
:disabled=" scaleHTMLPreview == key " :title=" 'Switch to ' + key + ' view' "
|
||||
v-on:click=" scaleHTMLPreview = key ">
|
||||
<i class="bi" :class=" 'bi-' + key "></i>
|
||||
<button class="btn" :class="scaleHTMLPreview == key ? 'btn-outline-primary' : ''"
|
||||
:disabled="scaleHTMLPreview == key" :title="'Switch to ' + key + ' view'"
|
||||
v-on:click=" scaleHTMLPreview = key">
|
||||
<i class="bi" :class="'bi-' + key"></i>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
@ -301,31 +322,31 @@ export default {
|
||||
</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"
|
||||
<div v-if="message.HTML != ''" class="tab-pane fade show" id="nav-html" role="tabpanel"
|
||||
aria-labelledby="nav-html-tab" tabindex="0">
|
||||
<div id="responsive-view" :class=" scaleHTMLPreview " :style=" responsiveSizes[scaleHTMLPreview] ">
|
||||
<iframe target-blank="" class="tab-pane d-block" id="preview-html" :srcdoc=" message.HTML "
|
||||
v-on:load=" resizeIframe " seamless frameborder="0" style="width: 100%; height: 100%;">
|
||||
<div id="responsive-view" :class="scaleHTMLPreview" :style="responsiveSizes[scaleHTMLPreview]">
|
||||
<iframe target-blank="" class="tab-pane d-block" id="preview-html" :srcdoc="message.HTML"
|
||||
v-on:load="resizeIframe" seamless frameborder="0" style="width: 100%; height: 100%;">
|
||||
</iframe>
|
||||
</div>
|
||||
<Attachments v-if=" allAttachments(message).length " :message=" message "
|
||||
:attachments=" allAttachments(message) "></Attachments>
|
||||
<Attachments v-if="allAttachments(message).length" :message="message"
|
||||
:attachments="allAttachments(message)"></Attachments>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-html-source" role="tabpanel" aria-labelledby="nav-html-source-tab"
|
||||
tabindex="0" v-if=" message.HTML ">
|
||||
tabindex="0" v-if="message.HTML">
|
||||
<pre><code class="language-html">{{ message.HTML }}</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-plain-text" role="tabpanel" aria-labelledby="nav-plain-text-tab" tabindex="0"
|
||||
:class=" message.HTML == '' ? 'show' : '' ">
|
||||
<div class="text-view">{{ message.Text }}</div>
|
||||
<Attachments v-if=" allAttachments(message).length " :message=" message "
|
||||
:attachments=" allAttachments(message) "></Attachments>
|
||||
:class="message.HTML == '' ? 'show' : ''">
|
||||
<div class="text-view" v-html="textToHTML(message.Text)"></div>
|
||||
<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>
|
||||
<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"
|
||||
<iframe v-if="srcURI" :src="srcURI" v-on:load="resizeIframe" seamless frameborder="0"
|
||||
style="width: 100%; height: 300px;" id="message-src"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user