mirror of
https://github.com/axllent/mailpit.git
synced 2025-08-15 20:13:16 +02:00
Merge branch 'release/v1.20.1'
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@@ -2,6 +2,17 @@
|
||||
|
||||
Notable changes to Mailpit will be documented in this file.
|
||||
|
||||
## [v1.20.1]
|
||||
|
||||
### Chore
|
||||
- Shift inbox pagination to inbox component
|
||||
- Live load up to 100 new messages in sidebar ([#336](https://github.com/axllent/mailpit/issues/336))
|
||||
- Show icon attachment in new side navigation message listing ([#345](https://github.com/axllent/mailpit/issues/345))
|
||||
|
||||
### Fix
|
||||
- Correctly decode X-Tags message headers (RFC 2047) ([#344](https://github.com/axllent/mailpit/issues/344))
|
||||
|
||||
|
||||
## [v1.20.0]
|
||||
|
||||
### Feature
|
||||
|
@@ -50,7 +50,7 @@ func Store(body *[]byte) (string, error) {
|
||||
ReplyTo: addressToSlice(env, "Reply-To"),
|
||||
}
|
||||
|
||||
messageID := strings.Trim(env.Root.Header.Get("Message-ID"), "<>")
|
||||
messageID := strings.Trim(env.GetHeader("Message-ID"), "<>")
|
||||
created := time.Now()
|
||||
|
||||
// use message date instead of created date
|
||||
@@ -116,7 +116,7 @@ func Store(body *[]byte) (string, error) {
|
||||
tags := findTagsInRawMessage(body)
|
||||
|
||||
if !config.TagsDisableXTags {
|
||||
xTagsHdr := env.Root.Header.Get("X-Tags")
|
||||
xTagsHdr := env.GetHeader("X-Tags")
|
||||
if xTagsHdr != "" {
|
||||
// extract tags from X-Tags header
|
||||
tags = append(tags, tools.SetTagCasing(strings.Split(strings.TrimSpace(xTagsHdr), ","))...)
|
||||
|
@@ -21,7 +21,6 @@ export default {
|
||||
socketBreaks: 0, // to track sockets that continually connect & disconnect, reset every 15s
|
||||
pauseNotifications: false, // prevent spamming
|
||||
version: false,
|
||||
paginationDelayed: false, // for delayed pagination URL changes
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,20 +55,7 @@ export default {
|
||||
|
||||
// new messages
|
||||
if (response.Type == "new" && response.Data) {
|
||||
if (!mailbox.searching) {
|
||||
if (pagination.start < 1) {
|
||||
// push results directly into first page
|
||||
mailbox.messages.unshift(response.Data)
|
||||
if (mailbox.messages.length > pagination.limit) {
|
||||
mailbox.messages.pop()
|
||||
}
|
||||
} else {
|
||||
// update pagination offset
|
||||
pagination.start++
|
||||
// prevent "Too many calls to Location or History APIs within a short time frame"
|
||||
this.delayedPaginationUpdate()
|
||||
}
|
||||
}
|
||||
this.eventBus.emit("new", response.Data)
|
||||
|
||||
for (let i in response.Data.Tags) {
|
||||
if (mailbox.tags.findIndex(e => { return e.toLowerCase() === response.Data.Tags[i].toLowerCase() }) < 0) {
|
||||
@@ -106,10 +92,10 @@ export default {
|
||||
}
|
||||
} else if (response.Type == "delete" && response.Data) {
|
||||
// broadcast for components
|
||||
this.eventBus.emit("delete", response.Data);
|
||||
this.eventBus.emit("delete", response.Data)
|
||||
} else if (response.Type == "update" && response.Data) {
|
||||
// broadcast for components
|
||||
this.eventBus.emit("update", response.Data);
|
||||
this.eventBus.emit("update", response.Data)
|
||||
} else if (response.Type == "truncate") {
|
||||
// broadcast for components
|
||||
this.eventBus.emit("truncate")
|
||||
@@ -171,39 +157,6 @@ export default {
|
||||
}, 15000)
|
||||
},
|
||||
|
||||
// This will only update the pagination offset at a maximum of 2x per second
|
||||
// when viewing the inbox on > page 1, while receiving an influx of new messages.
|
||||
delayedPaginationUpdate() {
|
||||
if (this.paginationDelayed) {
|
||||
return
|
||||
}
|
||||
|
||||
this.paginationDelayed = true
|
||||
|
||||
window.setTimeout(() => {
|
||||
const path = this.$route.path
|
||||
const p = {
|
||||
...this.$route.query
|
||||
}
|
||||
if (pagination.start > 0) {
|
||||
p.start = pagination.start.toString()
|
||||
} else {
|
||||
delete p.start
|
||||
}
|
||||
if (pagination.limit != pagination.defaultLimit) {
|
||||
p.limit = pagination.limit.toString()
|
||||
} else {
|
||||
delete p.limit
|
||||
}
|
||||
|
||||
mailbox.autoPaginating = false // prevent reload of messages when URL changes
|
||||
const params = new URLSearchParams(p)
|
||||
this.$router.replace(path + '?' + params.toString())
|
||||
|
||||
this.paginationDelayed = false
|
||||
}, 500)
|
||||
},
|
||||
|
||||
browserNotify(title, message) {
|
||||
if (!("Notification" in window)) {
|
||||
return
|
||||
|
@@ -275,11 +275,6 @@ export default {
|
||||
return 'bi-file-arrow-down-fill'
|
||||
},
|
||||
|
||||
// wrapper to update one or more messages with
|
||||
updateMessages(messages, updates) {
|
||||
|
||||
},
|
||||
|
||||
// Returns a hex color based on a string.
|
||||
// Values are stored in an array for faster lookup / processing.
|
||||
colorHash(s) {
|
||||
|
@@ -31,6 +31,7 @@ export default {
|
||||
return {
|
||||
mailbox,
|
||||
delayedRefresh: false,
|
||||
paginationDelayed: false, // for delayed pagination URL changes
|
||||
}
|
||||
},
|
||||
|
||||
@@ -46,6 +47,7 @@ export default {
|
||||
this.loadMailbox()
|
||||
|
||||
// subscribe to events
|
||||
this.eventBus.on("new", this.handleWSNew)
|
||||
this.eventBus.on("update", this.handleWSUpdate)
|
||||
this.eventBus.on("delete", this.handleWSDelete)
|
||||
this.eventBus.on("truncate", this.handleWSTruncate)
|
||||
@@ -53,6 +55,7 @@ export default {
|
||||
|
||||
unmounted() {
|
||||
// unsubscribe from events
|
||||
this.eventBus.off("new", this.handleWSNew)
|
||||
this.eventBus.off("update", this.handleWSUpdate)
|
||||
this.eventBus.off("delete", this.handleWSDelete)
|
||||
this.eventBus.off("truncate", this.handleWSTruncate)
|
||||
@@ -73,6 +76,55 @@ export default {
|
||||
this.loadMessages()
|
||||
},
|
||||
|
||||
// This will only update the pagination offset at a maximum of 2x per second
|
||||
// when viewing the inbox on > page 1, while receiving an influx of new messages.
|
||||
delayedPaginationUpdate() {
|
||||
if (this.paginationDelayed) {
|
||||
return
|
||||
}
|
||||
|
||||
this.paginationDelayed = true
|
||||
|
||||
window.setTimeout(() => {
|
||||
const path = this.$route.path
|
||||
const p = {
|
||||
...this.$route.query
|
||||
}
|
||||
if (pagination.start > 0) {
|
||||
p.start = pagination.start.toString()
|
||||
} else {
|
||||
delete p.start
|
||||
}
|
||||
if (pagination.limit != pagination.defaultLimit) {
|
||||
p.limit = pagination.limit.toString()
|
||||
} else {
|
||||
delete p.limit
|
||||
}
|
||||
|
||||
mailbox.autoPaginating = false // prevent reload of messages when URL changes
|
||||
const params = new URLSearchParams(p)
|
||||
this.$router.replace(path + '?' + params.toString())
|
||||
|
||||
this.paginationDelayed = false
|
||||
}, 500)
|
||||
},
|
||||
|
||||
// handler for websocket new messages
|
||||
handleWSNew(data) {
|
||||
if (pagination.start < 1) {
|
||||
// push results directly into first page
|
||||
mailbox.messages.unshift(data)
|
||||
if (mailbox.messages.length > pagination.limit) {
|
||||
mailbox.messages.pop()
|
||||
}
|
||||
} else {
|
||||
// update pagination offset
|
||||
pagination.start++
|
||||
// prevent "Too many calls to Location or History APIs within a short time frame"
|
||||
this.delayedPaginationUpdate()
|
||||
}
|
||||
},
|
||||
|
||||
// handler for websocket message updates
|
||||
handleWSUpdate(data) {
|
||||
for (let x = 0; x < this.mailbox.messages.length; x++) {
|
||||
|
@@ -33,6 +33,7 @@ export default {
|
||||
apiSideNavParams: URLSearchParams,
|
||||
apiIsMore: true,
|
||||
messagesList: [],
|
||||
liveLoaded: 0, // the number new messages prepended tp messageList
|
||||
scrollLoading: false,
|
||||
canLoadMore: true,
|
||||
}
|
||||
@@ -62,6 +63,7 @@ export default {
|
||||
this.refreshUI()
|
||||
|
||||
// subscribe to events
|
||||
this.eventBus.on("new", this.handleWSNew)
|
||||
this.eventBus.on("update", this.handleWSUpdate)
|
||||
this.eventBus.on("delete", this.handleWSDelete)
|
||||
this.eventBus.on("truncate", this.handleWSTruncate)
|
||||
@@ -69,6 +71,7 @@ export default {
|
||||
|
||||
unmounted() {
|
||||
// unsubscribe from events
|
||||
this.eventBus.off("new", this.handleWSNew)
|
||||
this.eventBus.off("update", this.handleWSUpdate)
|
||||
this.eventBus.off("delete", this.handleWSDelete)
|
||||
this.eventBus.off("truncate", this.handleWSTruncate)
|
||||
@@ -212,6 +215,18 @@ export default {
|
||||
}, 30000)
|
||||
},
|
||||
|
||||
// handler for websocket new messages
|
||||
handleWSNew(data) {
|
||||
// do not add when searching or >= 100 new messages have been received
|
||||
if (this.mailbox.searching || this.liveLoaded >= 100) {
|
||||
return
|
||||
}
|
||||
|
||||
this.liveLoaded++
|
||||
this.messagesList.unshift(data)
|
||||
this.scrollSidebarToCurrent()
|
||||
},
|
||||
|
||||
// handler for websocket message updates
|
||||
handleWSUpdate(data) {
|
||||
for (let x = 0; x < this.messagesList.length; x++) {
|
||||
@@ -419,6 +434,10 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
reloadWindow() {
|
||||
location.reload()
|
||||
},
|
||||
|
||||
initReleaseModal() {
|
||||
this.modal('ReleaseModal').show()
|
||||
window.setTimeout(() => {
|
||||
@@ -537,7 +556,7 @@ export default {
|
||||
<span class="ms-1">
|
||||
Return to
|
||||
<template v-if="mailbox.searching">search</template>
|
||||
<template v-else>mailbox</template>
|
||||
<template v-else>inbox</template>
|
||||
</span>
|
||||
<span class="badge rounded-pill ms-1 float-end text-bg-secondary" title="Unread messages"
|
||||
v-if="mailbox.unread && !errorMessage">
|
||||
@@ -548,6 +567,9 @@ export default {
|
||||
|
||||
<div class="flex-grow-1 overflow-y-auto px-1 me-n1" id="MessageList" ref="MessageList"
|
||||
@scroll="scrollHandler">
|
||||
<button v-if="liveLoaded >= 100" class="w-100 alert alert-warning small" @click="reloadWindow()">
|
||||
Reload to see newer messages
|
||||
</button>
|
||||
<template v-if="messagesList && messagesList.length">
|
||||
<div class="list-group">
|
||||
<RouterLink v-for="message in messagesList" :to="'/view/' + message.ID" :key="message.ID"
|
||||
@@ -566,6 +588,7 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto small">
|
||||
<i class="bi bi-paperclip h6" v-if="message.Attachments"></i>
|
||||
{{ getRelativeCreated(message) }}
|
||||
</div>
|
||||
<div v-if="message.Tags.length" class="col-12">
|
||||
|
Reference in New Issue
Block a user