Skip to content

Commit

Permalink
Feature: Add option to disable auto-tagging for plus-addressing & X-T…
Browse files Browse the repository at this point in the history
…ags (#323)
  • Loading branch information
axllent committed Jun 28, 2024
1 parent c7e0455 commit 414b935
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 15 deletions.
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ func init() {
rootCmd.Flags().StringVarP(&config.CLITagsArg, "tag", "t", config.CLITagsArg, "Tag new messages matching filters")
rootCmd.Flags().StringVar(&config.TagsConfig, "tags-config", config.TagsConfig, "Load tags filters from yaml configuration file")
rootCmd.Flags().BoolVar(&tools.TagsTitleCase, "tags-title-case", tools.TagsTitleCase, "TitleCase new tags generated from plus-addresses and X-Tags")
rootCmd.Flags().StringVar(&config.TagsDisable, "tags-disable", config.TagsDisable, "Disable auto-tagging, comma separated (eg: x-tags,plus-addressing)")

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

// Webhook
if len(os.Getenv("MP_WEBHOOK_URL")) > 0 {
Expand Down
9 changes: 8 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ var (
// TagFilters are used to apply tags to new mail
TagFilters []autoTag

// TagsDisable accepts a comma-separated list of tag types to disable
// including x-tags & plus-addressing
TagsDisable string

// SMTPRelayConfigFile to parse a yaml file and store config of relay SMTP server
SMTPRelayConfigFile string

Expand Down Expand Up @@ -390,14 +394,17 @@ func VerifyConfig() error {
}
}

// load tag filters
// load tag filters & options
TagFilters = []autoTag{}
if err := loadTagsFromArgs(CLITagsArg); err != nil {
return err
}
if err := loadTagsFromConfig(TagsConfig); err != nil {
return err
}
if err := parseTagsDisable(TagsDisable); err != nil {
return err
}

if SMTPAllowedRecipients != "" {
restrictRegexp, err := regexp.Compile(SMTPAllowedRecipients)
Expand Down
30 changes: 30 additions & 0 deletions config/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ import (
"gopkg.in/yaml.v3"
)

var (
// TagsDisablePlus disables message tagging using plus addressing ([email protected]) - set via verifyConfig()
TagsDisablePlus bool

// TagsDisableXTags disables message tagging via the X-Tags header - set via verifyConfig()
TagsDisableXTags bool
)

type yamlTags struct {
Filters []yamlTag `yaml:"filters"`
}
Expand Down Expand Up @@ -79,3 +87,25 @@ func loadTagsFromArgs(c string) error {

return nil
}

func parseTagsDisable(s string) error {
s = strings.TrimSpace(s)
if s == "" {
return nil
}

parts := strings.Split(strings.ToLower(s), ",")

for _, p := range parts {
switch strings.TrimSpace(p) {
case "x-tags", "xtags":
TagsDisableXTags = true
case "plus-addressing", "plus-addresses":
TagsDisablePlus = true
default:
return fmt.Errorf("[tags] invalid --tags-disable option: %s", p)
}
}

return nil
}
32 changes: 18 additions & 14 deletions internal/storage/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,20 +112,24 @@ func Store(body *[]byte) (string, error) {
return "", err
}

// extract tags from body matches
rawTags := findTagsInRawMessage(body)
// extract plus addresses tags from enmime.Envelope
plusTags := obj.tagsFromPlusAddresses()
// extract tags from X-Tags header
xTags := tools.SetTagCasing(strings.Split(strings.TrimSpace(env.Root.Header.Get("X-Tags")), ","))
// extract tags from search matches
searchTags := tagFilterMatches(id)

// combine all tags into one slice
tags := append(rawTags, plusTags...)
tags = append(tags, xTags...)
// sort and extract only unique tags
tags = sortedUniqueTags(append(tags, searchTags...))
// extract tags using pre-set tag filters, empty slice if not set
tags := findTagsInRawMessage(body)

if !config.TagsDisableXTags {
xTagsHdr := env.Root.Header.Get("X-Tags")
if xTagsHdr != "" {
// extract tags from X-Tags header
tags = append(tags, tools.SetTagCasing(strings.Split(strings.TrimSpace(xTagsHdr), ","))...)
}
}

if !config.TagsDisablePlus {
// get tags from plus addressing
tags = append(tags, obj.tagsFromPlusAddresses()...)
}

// extract tags from search matches, and sort and extract unique tags
tags = sortedUniqueTags(append(tags, tagFilterMatches(id)...))

if len(tags) > 0 {
if err := SetMessageTags(id, tags); err != nil {
Expand Down

0 comments on commit 414b935

Please sign in to comment.