1
0
mirror of https://github.com/axllent/mailpit.git synced 2025-08-15 20:13:16 +02:00

Feature: Set message tags using plus addressing (#253)

This commit is contained in:
Ralph Slooten
2024-03-01 17:21:21 +13:00
parent bfd5837710
commit 0353520aeb
5 changed files with 113 additions and 9 deletions

View File

@@ -69,14 +69,10 @@ func Store(body *[]byte) (string, error) {
return "", err
}
// extract tags from body matches based on --tag
tagStr := findTagsInRawMessage(body)
// extract tags from X-Tags header
headerTags := strings.TrimSpace(env.Root.Header.Get("X-Tags"))
if headerTags != "" {
tagStr += "," + headerTags
}
// extract tags from body matches based on --tag, plus addresses & X-Tags header
tagStr := findTagsInRawMessage(body) + "," +
obj.tagsFromPlusAddresses() + "," +
strings.TrimSpace(env.Root.Header.Get("X-Tags"))
tagData := uniqueTagsFromString(tagStr)

View File

@@ -2,6 +2,7 @@ package storage
import (
"database/sql"
"regexp"
"sort"
"strings"
@@ -11,6 +12,10 @@ import (
"github.com/leporo/sqlf"
)
var (
addressPlusRe = regexp.MustCompile(`^(.*){1,}\+(.*)@`)
)
// SetMessageTags will set the tags for a given database ID
func SetMessageTags(id string, tags []string) error {
applyTags := []string{}
@@ -236,6 +241,35 @@ func findTagsInRawMessage(message *[]byte) string {
return tagStr
}
// Returns tags found in email plus addresses (eg: test+tagname@example.com)
func (d DBMailSummary) tagsFromPlusAddresses() string {
tags := []string{}
for _, c := range d.To {
matches := addressPlusRe.FindAllStringSubmatch(c.String(), 1)
if len(matches) == 1 && config.ValidTagRegexp.MatchString(matches[0][2]) {
tags = append(tags, matches[0][2])
}
}
for _, c := range d.Cc {
matches := addressPlusRe.FindAllStringSubmatch(c.String(), 1)
if len(matches) == 1 && config.ValidTagRegexp.MatchString(matches[0][2]) {
tags = append(tags, matches[0][2])
}
}
for _, c := range d.Bcc {
matches := addressPlusRe.FindAllStringSubmatch(c.String(), 1)
if len(matches) == 1 && config.ValidTagRegexp.MatchString(matches[0][2]) {
tags = append(tags, matches[0][2])
}
}
matches := addressPlusRe.FindAllStringSubmatch(d.From.String(), 1)
if len(matches) == 1 && config.ValidTagRegexp.MatchString(matches[0][2]) {
tags = append(tags, matches[0][2])
}
return strings.Join(tags, ",")
}
// Get message tags from the database for a given database ID
// Used when parsing a raw email.
func getMessageTags(id string) []string {

View File

@@ -107,5 +107,24 @@ func TestTags(t *testing.T) {
// Check deleted message tags also prune the tags database
allTags := GetAllTags()
assertEqual(t, "", strings.Join(allTags, "|"), "Dirty message tag did not clean as expected")
assertEqual(t, "", strings.Join(allTags, "|"), "Tags did not delete as expected")
if err := DeleteAllMessages(); err != nil {
t.Log("error ", err)
t.Fail()
}
// test 20 tags
id, err = Store(&testTagEmail)
if err != nil {
t.Log("error ", err)
t.Fail()
}
returnedTags = getMessageTags(id)
assertEqual(t, "BccTag|CcTag|FromFag|ToTag|X-tag1|X-tag2", strings.Join(returnedTags, "|"), "Tags not detected correctly")
if err := DeleteAllMessageTags(id); err != nil {
t.Log("error ", err)
t.Fail()
}
}

49
internal/storage/testdata/tags.eml vendored Normal file
View File

@@ -0,0 +1,49 @@
Date: Wed, 27 Jul 2022 15:44:41 +1200
From: Sender Smith <sender+FromFag@example.com>
To: Recipient Ross <recipient+ToTag@example.com>
Cc: Recipient Ross <cc+CcTag@example.com>
Bcc: <bcc+BccTag@example.com>
Subject: Plain text message
X-Tags: X-tag1, X-tag2
Message-ID: <20220727034441.7za34h6ljuzfpmj3@localhost.localhost>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras non massa lacinia,
fringilla ex vel, ornare nulla. Suspendisse dapibus commodo sapien, non
hendrerit diam feugiat sit amet. Nulla lorem quam, laoreet vitae nisl volutpat,
mollis bibendum felis. In eget ultricies justo. Donec vitae hendrerit tortor, at
posuere libero. Fusce a gravida nibh. Nulla ac odio ex.
Aliquam sem turpis, cursus vitae condimentum at, scelerisque pulvinar lectus.
Cras tempor nisl ut arcu interdum, et luctus arcu cursus. Maecenas mollis
sagittis commodo. Mauris ac lorem nec ex interdum consequat. Morbi congue
ultrices ullamcorper. Aenean ex tortor, dapibus quis dapibus iaculis, iaculis
eget felis. Vestibulum purus ante, efficitur in turpis ac, tristique laoreet
orci. Nulla facilisi. Praesent mollis orci posuere elementum laoreet.
Pellentesque enim nibh, varius at ante id, consequat posuere ante.
Cras maximus venenatis nulla nec cursus. Morbi convallis, enim eget viverra
vulputate, ipsum arcu tincidunt tortor, ut cursus dui enim commodo quam. Donec
et vulputate quam. Vivamus non posuere erat. Nam commodo pellentesque
condimentum. Vivamus condimentum eros at odio dictum feugiat. Ut imperdiet
tempor luctus. Aenean varius libero ac faucibus dictum. Aliquam sed finibus
massa. Morbi dolor lorem, feugiat quis neque et, suscipit posuere ex. Sed auctor
et augue at finibus. Vestibulum interdum mi ac justo porta aliquam. Curabitur
nec enim sit amet enim aliquet accumsan. Etiam accumsan tellus tortor, interdum
sodales odio finibus eu. Integer eget ante eu nisi lobortis pulvinar et vel
ipsum. Cras condimentum posuere vulputate.
Cras nulla felis, blandit vitae egestas quis, fringilla ut dolor. Phasellus est
augue, feugiat eu risus quis, posuere ultrices libero. Phasellus non nunc eget
justo sollicitudin tincidunt. Praesent pretium dui id felis bibendum sodales.
Phasellus eget dictum libero, auctor tempor nibh. Suspendisse posuere libero
venenatis elit imperdiet porttitor. In condimentum dictum luctus. Nullam in
nulla vitae augue blandit posuere. Vestibulum consectetur ultricies tincidunt.
Vivamus dolor quam, pharetra sed eros sed, hendrerit ultrices diam. Vestibulum
vulputate tellus eget tellus lacinia, a pulvinar velit vulputate. Suspendisse
mauris odio, scelerisque eget turpis sed, tincidunt ultrices magna. Nunc arcu
arcu, commodo et porttitor quis, accumsan viverra purus. Fusce id libero iaculis
lorem tristique commodo porttitor id ipsum. Vestibulum odio dui, tincidunt eget
lectus vel, tristique lacinia libero. Aliquam dapibus ac felis vitae cursus.

View File

@@ -11,6 +11,7 @@ import (
var (
testTextEmail []byte
testTagEmail []byte
testMimeEmail []byte
testRuns = 100
)
@@ -31,6 +32,11 @@ func setup() {
panic(err)
}
testTagEmail, err = os.ReadFile("testdata/tags.eml")
if err != nil {
panic(err)
}
testMimeEmail, err = os.ReadFile("testdata/mime-attachment.eml")
if err != nil {
panic(err)