diff --git a/cmd/root.go b/cmd/root.go index ccdc950..a17d16c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -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: plus-addresses,x-tags)") // Webhook rootCmd.Flags().StringVar(&config.WebhookURL, "webhook-url", config.WebhookURL, "Send a webhook request for new messages") @@ -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 { diff --git a/config/config.go b/config/config.go index ceb80bf..c5c914b 100644 --- a/config/config.go +++ b/config/config.go @@ -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-addresses + TagsDisable string + // SMTPRelayConfigFile to parse a yaml file and store config of relay SMTP server SMTPRelayConfigFile string @@ -390,7 +394,7 @@ func VerifyConfig() error { } } - // load tag filters + // load tag filters & options TagFilters = []autoTag{} if err := loadTagsFromArgs(CLITagsArg); err != nil { return err @@ -398,6 +402,9 @@ func VerifyConfig() error { if err := loadTagsFromConfig(TagsConfig); err != nil { return err } + if err := parseTagsDisable(TagsDisable); err != nil { + return err + } if SMTPAllowedRecipients != "" { restrictRegexp, err := regexp.Compile(SMTPAllowedRecipients) diff --git a/config/tags.go b/config/tags.go index cb46f25..c11ec26 100644 --- a/config/tags.go +++ b/config/tags.go @@ -11,6 +11,14 @@ import ( "gopkg.in/yaml.v3" ) +var ( + // TagsDisablePlus disables message tagging using plus-addresses (user+tag@example.com) - 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"` } @@ -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-addresses", "plus-addressing": + TagsDisablePlus = true + default: + return fmt.Errorf("[tags] invalid --tags-disable option: %s", p) + } + } + + return nil +} diff --git a/internal/storage/messages.go b/internal/storage/messages.go index 9af7b5f..a703f08 100644 --- a/internal/storage/messages.go +++ b/internal/storage/messages.go @@ -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) + // extract tags using pre-set tag filters, empty slice if not set + tags := findTagsInRawMessage(body) - // 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...)) + 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-addresses + 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 {