1
0
mirror of https://github.com/axllent/mailpit.git synced 2025-03-19 21:28:07 +02:00

Merge branch 'release/0.1.5'

This commit is contained in:
Ralph Slooten 2022-08-16 08:17:21 +12:00
commit 8b6b6640d5
9 changed files with 96 additions and 17 deletions

View File

@ -3,6 +3,16 @@
Notable changes to Mailpit will be documented in this file. Notable changes to Mailpit will be documented in this file.
## 0.1.5
### Feature
- Improved message search - any order & phrase quoting
### UI
- Change breakpoints for mobile view of messages
- Resize iframes with viewport resize
## 0.1.4 ## 0.1.4
### Feature ### Feature

1
go.mod
View File

@ -9,6 +9,7 @@ require (
github.com/jhillyerd/enmime v0.10.0 github.com/jhillyerd/enmime v0.10.0
github.com/k3a/html2text v1.0.8 github.com/k3a/html2text v1.0.8
github.com/klauspost/compress v1.15.9 github.com/klauspost/compress v1.15.9
github.com/mattn/go-shellwords v1.0.12
github.com/mhale/smtpd v0.8.0 github.com/mhale/smtpd v0.8.0
github.com/ostafen/clover/v2 v2.0.0-alpha.2 github.com/ostafen/clover/v2 v2.0.0-alpha.2
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.9.0

2
go.sum
View File

@ -124,6 +124,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mhale/smtpd v0.8.0 h1:5JvdsehCg33PQrZBvFyDMMUDQmvbzVpZgKob7eYBJc0= github.com/mhale/smtpd v0.8.0 h1:5JvdsehCg33PQrZBvFyDMMUDQmvbzVpZgKob7eYBJc0=
github.com/mhale/smtpd v0.8.0/go.mod h1:MQl+y2hwIEQCXtNhe5+55n0GZOjSmeqORDIXbqUL3x4= github.com/mhale/smtpd v0.8.0/go.mod h1:MQl+y2hwIEQCXtNhe5+55n0GZOjSmeqORDIXbqUL3x4=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=

View File

@ -443,33 +443,33 @@ export default {
<div class="list-group" v-if="items.length"> <div class="list-group" v-if="items.length">
<a v-for="message in items" :href="'#'+message.ID" class="row message d-flex small list-group-item list-group-item-action" <a v-for="message in items" :href="'#'+message.ID" class="row message d-flex small list-group-item list-group-item-action"
:class="message.Read ? 'read':''" XXXv-on:click="openMessage(message)"> :class="message.Read ? 'read':''" XXXv-on:click="openMessage(message)">
<div class="col-md-3"> <div class="col-lg-3">
<div class="d-md-none float-end text-muted text-nowrap small"> <div class="d-lg-none float-end text-muted text-nowrap small">
<i class="bi bi-paperclip h6 me-1" v-if="message.Attachments"></i> <i class="bi bi-paperclip h6 me-1" v-if="message.Attachments"></i>
{{ getRelativeCreated(message) }} {{ getRelativeCreated(message) }}
</div> </div>
<div class="text-truncate d-md-none privacy"> <div class="text-truncate d-lg-none privacy">
<span v-if="message.From" :title="message.From.Address">{{ message.From.Name ? message.From.Name : message.From.Address }}</span> <span v-if="message.From" :title="message.From.Address">{{ message.From.Name ? message.From.Name : message.From.Address }}</span>
</div> </div>
<div class="text-truncate d-none d-md-block privacy"> <div class="text-truncate d-none d-lg-block privacy">
<b v-if="message.From" :title="message.From.Address">{{ message.From.Name ? message.From.Name : message.From.Address }}</b> <b v-if="message.From" :title="message.From.Address">{{ message.From.Name ? message.From.Name : message.From.Address }}</b>
</div> </div>
<div class="d-none d-md-block text-truncate text-muted small privacy"> <div class="d-none d-lg-block text-truncate text-muted small privacy">
{{ getPrimaryEmailTo(message) }} {{ getPrimaryEmailTo(message) }}
<span v-if="message.To && message.To.length > 1"> <span v-if="message.To && message.To.length > 1">
[+{{message.To.length - 1}}] [+{{message.To.length - 1}}]
</span> </span>
</div> </div>
</div> </div>
<div class="col-md-6 mt-2 mt-md-0"> <div class="col-lg-6 mt-2 mt-lg-0">
<b>{{ message.Subject != "" ? message.Subject : "[ no subject ]" }}</b> <b>{{ message.Subject != "" ? message.Subject : "[ no subject ]" }}</b>
</div> </div>
<div class="d-none d-md-block col-1 small text-end text-muted"> <div class="d-none d-lg-block col-1 small text-end text-muted">
<i class="bi bi-paperclip float-start h6" v-if="message.Attachments"></i> <i class="bi bi-paperclip float-start h6" v-if="message.Attachments"></i>
{{ getFileSize(message.Size) }} {{ getFileSize(message.Size) }}
</div> </div>
<div class="d-none d-md-block col-2 small text-end text-muted"> <div class="d-none d-lg-block col-2 small text-end text-muted">
{{ getRelativeCreated(message) }} {{ getRelativeCreated(message) }}
</div> </div>
</a> </a>

View File

@ -44,6 +44,7 @@
font-family: Courier New, Courier, System, fixed-width; font-family: Courier New, Courier, System, fixed-width;
font-size: 0.85em; font-size: 0.85em;
} }
#nav-plain-text { #nav-plain-text {
white-space: pre-wrap; white-space: pre-wrap;
} }
@ -52,7 +53,7 @@
margin: 15px 0 0; margin: 15px 0 0;
th { th {
padding-right: 10px; padding-right: 1.5rem;
font-weight: normal; font-weight: normal;
vertical-align: top; vertical-align: top;
} }
@ -62,6 +63,14 @@
} }
} }
#nav-html {
padding-right: 1.5rem;
}
#preview-html {
min-height: 300px;
}
.list-group-item:first-child { .list-group-item:first-child {
border-top: 0; border-top: 0;
} }

View File

@ -15,6 +15,7 @@ export default {
iframes: [], // for resizing iframes: [], // for resizing
} }
}, },
mounted() { mounted() {
var self = this; var self = this;
@ -46,11 +47,29 @@ export default {
self.srcURI = 'api/' + self.mailbox + '/' + self.message.ID + '/source'; self.srcURI = 'api/' + self.mailbox + '/' + self.message.ID + '/source';
}); });
}, },
unmounted: function() {
window.removeEventListener("resize", this.resizeIframes);
},
methods: { methods: {
resizeIframe: function(el) { resizeIframe: function(el) {
let i = el.target; let i = el.target;
i.style.height = i.contentWindow.document.body.scrollHeight + 50 + 'px'; i.style.height = i.contentWindow.document.body.scrollHeight + 50 + 'px';
}, },
resizeIframes: function() {
let h = document.getElementById('preview-html');
if (h) {
h.style.height = h.contentWindow.document.body.scrollHeight + 50 + 'px';
}
let s = document.getElementById('message-src');
if (s) {
s.style.height = s.contentWindow.document.body.scrollHeight + 50 + 'px';
}
},
allAttachments: function(message){ allAttachments: function(message){
let a = []; let a = [];
for (let i in message.Attachments) { for (let i in message.Attachments) {

View File

@ -18,6 +18,7 @@ import (
"github.com/axllent/mailpit/server/websockets" "github.com/axllent/mailpit/server/websockets"
"github.com/jhillyerd/enmime" "github.com/jhillyerd/enmime"
"github.com/klauspost/compress/zstd" "github.com/klauspost/compress/zstd"
"github.com/mattn/go-shellwords"
"github.com/ostafen/clover/v2" "github.com/ostafen/clover/v2"
) )
@ -327,21 +328,58 @@ func List(mailbox string, start, limit int) ([]data.Summary, error) {
} }
// Search returns a summary of items mathing a search. It searched the SearchText field. // Search returns a summary of items mathing a search. It searched the SearchText field.
func Search(mailbox, search string, start, limit int) ([]data.Summary, error) { func Search(mailbox, s string, start, limit int) ([]data.Summary, error) {
mailbox = sanitizeMailboxName(mailbox) mailbox = sanitizeMailboxName(mailbox)
sq := fmt.Sprintf("(?i)%s", cleanString(regexp.QuoteMeta(search))) s = strings.ToLower(s)
s = strings.Replace(s, "'", `\'`, -1)
s = strings.Replace(s, "(", ``, -1)
s = strings.Replace(s, ")", ``, -1)
// add another quote if quotes are odd
quotes := strings.Count(s, `"`)
if quotes%2 != 0 {
s += `"`
}
p := shellwords.NewParser()
args, err := p.Parse(s)
if err != nil {
return nil, errors.New("Your search contains invalid characters")
}
results := []data.Summary{}
include := []string{}
for _, w := range args {
word := cleanString(w)
if word != "" {
include = append(include, fmt.Sprintf("%s", regexp.QuoteMeta(word)))
}
}
if len(include) == 0 {
return results, nil
}
var where clover.Criteria
for i, w := range include {
if i == 0 {
where = clover.Field("SearchText").Like(w)
} else {
where = where.And(clover.Field("SearchText").Like(w))
}
}
q, err := db.FindAll(clover.NewQuery(mailbox). q, err := db.FindAll(clover.NewQuery(mailbox).
Skip(start). Skip(start).
Limit(limit). Limit(limit).
Sort(clover.SortOption{Field: "Created", Direction: -1}). Sort(clover.SortOption{Field: "Created", Direction: -1}).
Where(clover.Field("SearchText").Like(sq))) Where(where))
if err != nil { if err != nil {
return nil, err return nil, err
} }
results := []data.Summary{}
for _, d := range q { for _, d := range q {
cs := &data.Summary{} cs := &data.Summary{}
if err := d.Unmarshal(cs); err != nil { if err := d.Unmarshal(cs); err != nil {

View File

@ -259,9 +259,9 @@ RepeatTest:
case 2: case 2:
search = fmt.Sprintf("to-%d@example.com", i) search = fmt.Sprintf("to-%d@example.com", i)
case 3: case 3:
search = fmt.Sprintf("Subject line %d end", i) search = fmt.Sprintf("\"Subject line %d end\"", i)
default: default:
search = fmt.Sprintf("the email body %d jdsauk dwqmdqw", i) search = fmt.Sprintf("\"the email body %d jdsauk dwqmdqw\"", i)
} }
summaries, err := Search(DefaultMailbox, search, 0, 10) summaries, err := Search(DefaultMailbox, search, 0, 10)

View File

@ -178,7 +178,7 @@ func GithubUpdate(repo, appName, currentVersion string) (string, error) {
// get the running binary // get the running binary
oldExec, err := os.Executable() oldExec, err := os.Executable()
if err != nil { if err != nil {
panic(err) return "", err
} }
if err = replaceFile(oldExec, newExec); err != nil { if err = replaceFile(oldExec, newExec); err != nil {