Skip to content

Commit 61e8cad

Browse files
committed
Merge branch 'release/v1.19.0'
2 parents 9a3d0ca + 1f0f9ef commit 61e8cad

File tree

22 files changed

+665
-186
lines changed

22 files changed

+665
-186
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
Notable changes to Mailpit will be documented in this file.
44

5+
## [v1.19.0]
6+
7+
### Feature
8+
- Add ability to rename and delete tags globally
9+
- Add option to disable auto-tagging for plus-addresses & X-Tags ([#323](https://github.com/axllent/mailpit/issues/323))
10+
11+
### Chore
12+
- Update node dependencies
13+
- Update Go dependencies
14+
15+
516
## [v1.18.7]
617

718
### Feature

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:alpine as builder
1+
FROM golang:alpine AS builder
22

33
ARG VERSION=dev
44

cmd/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ func init() {
131131
rootCmd.Flags().StringVarP(&config.CLITagsArg, "tag", "t", config.CLITagsArg, "Tag new messages matching filters")
132132
rootCmd.Flags().StringVar(&config.TagsConfig, "tags-config", config.TagsConfig, "Load tags filters from yaml configuration file")
133133
rootCmd.Flags().BoolVar(&tools.TagsTitleCase, "tags-title-case", tools.TagsTitleCase, "TitleCase new tags generated from plus-addresses and X-Tags")
134+
rootCmd.Flags().StringVar(&config.TagsDisable, "tags-disable", config.TagsDisable, "Disable auto-tagging, comma separated (eg: plus-addresses,x-tags)")
134135

135136
// Webhook
136137
rootCmd.Flags().StringVar(&config.WebhookURL, "webhook-url", config.WebhookURL, "Send a webhook request for new messages")
@@ -290,6 +291,7 @@ func initConfigFromEnv() {
290291
config.CLITagsArg = os.Getenv("MP_TAG")
291292
config.TagsConfig = os.Getenv("MP_TAGS_CONFIG")
292293
tools.TagsTitleCase = getEnabledFromEnv("MP_TAGS_TITLE_CASE")
294+
config.TagsDisable = os.Getenv("MP_TAGS_DISABLE")
293295

294296
// Webhook
295297
if len(os.Getenv("MP_WEBHOOK_URL")) > 0 {

config/config.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ var (
102102
// TagFilters are used to apply tags to new mail
103103
TagFilters []autoTag
104104

105+
// TagsDisable accepts a comma-separated list of tag types to disable
106+
// including x-tags & plus-addresses
107+
TagsDisable string
108+
105109
// SMTPRelayConfigFile to parse a yaml file and store config of relay SMTP server
106110
SMTPRelayConfigFile string
107111

@@ -390,14 +394,17 @@ func VerifyConfig() error {
390394
}
391395
}
392396

393-
// load tag filters
397+
// load tag filters & options
394398
TagFilters = []autoTag{}
395399
if err := loadTagsFromArgs(CLITagsArg); err != nil {
396400
return err
397401
}
398402
if err := loadTagsFromConfig(TagsConfig); err != nil {
399403
return err
400404
}
405+
if err := parseTagsDisable(TagsDisable); err != nil {
406+
return err
407+
}
401408

402409
if SMTPAllowedRecipients != "" {
403410
restrictRegexp, err := regexp.Compile(SMTPAllowedRecipients)

config/tags.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ import (
1111
"gopkg.in/yaml.v3"
1212
)
1313

14+
var (
15+
// TagsDisablePlus disables message tagging using plus-addresses ([email protected]) - set via verifyConfig()
16+
TagsDisablePlus bool
17+
18+
// TagsDisableXTags disables message tagging via the X-Tags header - set via verifyConfig()
19+
TagsDisableXTags bool
20+
)
21+
1422
type yamlTags struct {
1523
Filters []yamlTag `yaml:"filters"`
1624
}
@@ -79,3 +87,25 @@ func loadTagsFromArgs(c string) error {
7987

8088
return nil
8189
}
90+
91+
func parseTagsDisable(s string) error {
92+
s = strings.TrimSpace(s)
93+
if s == "" {
94+
return nil
95+
}
96+
97+
parts := strings.Split(strings.ToLower(s), ",")
98+
99+
for _, p := range parts {
100+
switch strings.TrimSpace(p) {
101+
case "x-tags", "xtags":
102+
TagsDisableXTags = true
103+
case "plus-addresses", "plus-addressing":
104+
TagsDisablePlus = true
105+
default:
106+
return fmt.Errorf("[tags] invalid --tags-disable option: %s", p)
107+
}
108+
}
109+
110+
return nil
111+
}

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
github.com/PuerkitoBio/goquery v1.9.2
99
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
1010
github.com/axllent/semver v0.0.1
11-
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2
11+
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024
1212
github.com/gorilla/mux v1.8.1
1313
github.com/gorilla/websocket v1.5.3
1414
github.com/jhillyerd/enmime v1.2.0
@@ -55,11 +55,11 @@ require (
5555
github.com/valyala/bytebufferpool v1.0.0 // indirect
5656
github.com/vanng822/css v1.0.1 // indirect
5757
golang.org/x/crypto v0.24.0 // indirect
58-
golang.org/x/image v0.17.0 // indirect
58+
golang.org/x/image v0.18.0 // indirect
5959
golang.org/x/sys v0.21.0 // indirect
6060
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
6161
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
62-
modernc.org/libc v1.53.3 // indirect
62+
modernc.org/libc v1.53.4 // indirect
6363
modernc.org/mathutil v1.6.0 // indirect
6464
modernc.org/memory v1.8.0 // indirect
6565
modernc.org/strutil v1.2.0 // indirect

go.sum

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
2323
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
2424
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
2525
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
26-
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 h1:yEt5djSYb4iNtmV9iJGVday+i4e9u6Mrn5iP64HH5QM=
27-
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
26+
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024 h1:saBP362Qm7zDdDXqv61kI4rzhmLFq3Z1gx34xpl6cWE=
27+
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
2828
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
2929
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
3030
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -128,8 +128,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
128128
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
129129
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
130130
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
131-
golang.org/x/image v0.17.0 h1:nTRVVdajgB8zCMZVsViyzhnMKPwYeroEERRC64JuLco=
132-
golang.org/x/image v0.17.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
131+
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
132+
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
133133
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
134134
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
135135
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
@@ -197,16 +197,16 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
197197
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
198198
modernc.org/cc/v4 v4.21.3 h1:2mhBdWKtivdFlLR1ecKXTljPG1mfvbByX7QKztAIJl8=
199199
modernc.org/cc/v4 v4.21.3/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
200-
modernc.org/ccgo/v4 v4.18.1 h1:1zF5kPBFq/ZVTulBOKgQPQITdOzzyBUfC51gVYP62E4=
201-
modernc.org/ccgo/v4 v4.18.1/go.mod h1:ao1fAxf9a2KEOL15WY8+yP3wnpaOpP/QuyFOZ9HJolM=
200+
modernc.org/ccgo/v4 v4.18.2 h1:PUQPShG4HwghpOekNujL0sFavdkRvmxzTbI4rGJ5mg0=
201+
modernc.org/ccgo/v4 v4.18.2/go.mod h1:ao1fAxf9a2KEOL15WY8+yP3wnpaOpP/QuyFOZ9HJolM=
202202
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
203203
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
204204
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
205205
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
206206
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8=
207207
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
208-
modernc.org/libc v1.53.3 h1:9O0aSLZuHPgp49we24NoFFteRgXNLGBAQ3TODrW3XLg=
209-
modernc.org/libc v1.53.3/go.mod h1:kb+Erju4FfHNE59xd2fNpv5CBeAeej6fHbx8p8xaiyI=
208+
modernc.org/libc v1.53.4 h1:YAgFS7tGIFBfqje2UOqiXtIwuDUCF8AUonYw0seup34=
209+
modernc.org/libc v1.53.4/go.mod h1:aGsLofnkcct8lTJnKQnCqJO37ERAXSHamSuWLFoF2Cw=
210210
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
211211
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
212212
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=

internal/storage/messages.go

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -112,23 +112,29 @@ func Store(body *[]byte) (string, error) {
112112
return "", err
113113
}
114114

115-
// extract tags from body matches
116-
rawTags := findTagsInRawMessage(body)
117-
// extract plus addresses tags from enmime.Envelope
118-
plusTags := obj.tagsFromPlusAddresses()
119-
// extract tags from X-Tags header
120-
xTags := tools.SetTagCasing(strings.Split(strings.TrimSpace(env.Root.Header.Get("X-Tags")), ","))
121-
// extract tags from search matches
122-
searchTags := tagFilterMatches(id)
123-
124-
// combine all tags into one slice
125-
tags := append(rawTags, plusTags...)
126-
tags = append(tags, xTags...)
127-
// sort and extract only unique tags
128-
tags = sortedUniqueTags(append(tags, searchTags...))
115+
// extract tags using pre-set tag filters, empty slice if not set
116+
tags := findTagsInRawMessage(body)
117+
118+
if !config.TagsDisableXTags {
119+
xTagsHdr := env.Root.Header.Get("X-Tags")
120+
if xTagsHdr != "" {
121+
// extract tags from X-Tags header
122+
tags = append(tags, tools.SetTagCasing(strings.Split(strings.TrimSpace(xTagsHdr), ","))...)
123+
}
124+
}
125+
126+
if !config.TagsDisablePlus {
127+
// get tags from plus-addresses
128+
tags = append(tags, obj.tagsFromPlusAddresses()...)
129+
}
130+
131+
// extract tags from search matches, and sort and extract unique tags
132+
tags = sortedUniqueTags(append(tags, tagFilterMatches(id)...))
129133

134+
setTags := []string{}
130135
if len(tags) > 0 {
131-
if err := SetMessageTags(id, tags); err != nil {
136+
setTags, err = SetMessageTags(id, tags)
137+
if err != nil {
132138
return "", err
133139
}
134140
}
@@ -144,7 +150,7 @@ func Store(body *[]byte) (string, error) {
144150
c.Attachments = attachments
145151
c.Subject = subject
146152
c.Size = size
147-
c.Tags = tags
153+
c.Tags = setTags
148154
c.Snippet = snippet
149155

150156
websockets.Broadcast("new", c)
@@ -593,7 +599,9 @@ func DeleteMessages(ids []string) error {
593599
}
594600
}
595601

596-
err = tx.Commit()
602+
if err := tx.Commit(); err != nil {
603+
return err
604+
}
597605

598606
dbLastAction = time.Now()
599607
addDeletedSize(int64(totalSize))

internal/storage/schemas.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ func dbApplySchemas() error {
137137

138138
buf := new(bytes.Buffer)
139139

140-
err = t1.Execute(buf, nil)
140+
if err := t1.Execute(buf, nil); err != nil {
141+
return err
142+
}
141143

142144
if _, err := db.Exec(buf.String()); err != nil {
143145
return err
@@ -197,7 +199,7 @@ func migrateTagsToManyMany() {
197199
if len(toConvert) > 0 {
198200
logger.Log().Infof("[migration] converting %d message tags", len(toConvert))
199201
for id, tags := range toConvert {
200-
if err := SetMessageTags(id, tags); err != nil {
202+
if _, err := SetMessageTags(id, tags); err != nil {
201203
logger.Log().Errorf("[migration] %s", err.Error())
202204
} else {
203205
if _, err := sqlf.Update(tenant("mailbox")).

0 commit comments

Comments
 (0)