mirror of
https://github.com/axllent/mailpit.git
synced 2025-01-08 00:39:22 +02:00
95 lines
2.5 KiB
Go
95 lines
2.5 KiB
Go
package storage
|
|
|
|
import (
|
|
"net/mail"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/axllent/mailpit/config"
|
|
"github.com/axllent/mailpit/logger"
|
|
"github.com/axllent/mailpit/server/websockets"
|
|
"github.com/jhillyerd/enmime"
|
|
"github.com/k3a/html2text"
|
|
"github.com/ostafen/clover/v2"
|
|
)
|
|
|
|
// Return a header field as a []*mail.Address, or "null" is not found/empty
|
|
func addressToSlice(env *enmime.Envelope, key string) []*mail.Address {
|
|
data, _ := env.AddressList(key)
|
|
|
|
return data
|
|
}
|
|
|
|
// Generate the search text based on some header fields (to, from, subject etc)
|
|
// and either the stripped HTML body (if exists) or text body
|
|
func createSearchText(env *enmime.Envelope) string {
|
|
var b strings.Builder
|
|
|
|
b.WriteString(env.GetHeader("From") + " ")
|
|
b.WriteString(env.GetHeader("Subject") + " ")
|
|
b.WriteString(env.GetHeader("To") + " ")
|
|
b.WriteString(env.GetHeader("Cc") + " ")
|
|
b.WriteString(env.GetHeader("Bcc") + " ")
|
|
h := strings.TrimSpace(html2text.HTML2Text(env.HTML))
|
|
if h != "" {
|
|
b.WriteString(h + " ")
|
|
} else {
|
|
b.WriteString(env.Text + " ")
|
|
}
|
|
// add attachment filenames
|
|
for _, a := range env.Attachments {
|
|
b.WriteString(a.FileName + " ")
|
|
}
|
|
|
|
d := cleanString(b.String())
|
|
|
|
return d
|
|
}
|
|
|
|
// cleanString removed unwanted characters from stored search text and search queries
|
|
func cleanString(str string) string {
|
|
// remove/replace new lines
|
|
re := regexp.MustCompile(`(\r?\n|\t|>|<|"|:|\,|;)`)
|
|
str = re.ReplaceAllString(str, " ")
|
|
// remove duplicate whitespace and trim
|
|
return strings.ToLower(strings.Join(strings.Fields(strings.TrimSpace(str)), " "))
|
|
}
|
|
|
|
// Auto-prune runs every 5 minutes to automatically delete oldest messages
|
|
// if total is greater than the threshold
|
|
func pruneCron() {
|
|
for {
|
|
// time.Sleep(5 * 60 * time.Second)
|
|
time.Sleep(60 * time.Second)
|
|
mailboxes, err := db.ListCollections()
|
|
if err != nil {
|
|
logger.Log().Errorf("[db] %s", err)
|
|
continue
|
|
}
|
|
|
|
for _, m := range mailboxes {
|
|
total, _ := db.Count(clover.NewQuery(m))
|
|
if total > config.MaxMessages {
|
|
limit := total - config.MaxMessages
|
|
if limit > 5000 {
|
|
limit = 5000
|
|
}
|
|
start := time.Now()
|
|
if err := db.Delete(clover.NewQuery(m).
|
|
Sort(clover.SortOption{Field: "Created", Direction: 1}).
|
|
Limit(limit)); err != nil {
|
|
logger.Log().Warnf("Error pruning %s: %s", m, err.Error())
|
|
continue
|
|
}
|
|
elapsed := time.Since(start)
|
|
logger.Log().Infof("Pruned %d messages from %s in %s", limit, m, elapsed)
|
|
statsRefresh(m)
|
|
if !strings.HasSuffix(m, "_data") {
|
|
websockets.Broadcast("prune", nil)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|