mirror of
https://github.com/mjl-/mox.git
synced 2025-07-12 17:44:35 +03:00
webmail: when moving a single message out of/to the inbox, ask if user wants to create a rule to automatically do that server-side for future deliveries
if the message has a list-id header, we assume this is a (mailing) list message, and we require a dkim/spf-verified domain (we prefer the shortest that is a suffix of the list-id value). the rule we would add will mark such messages as from a mailing list, changing filtering rules on incoming messages (not enforcing dmarc policies). messages will be matched on list-id header and will only match if they have the same dkim/spf-verified domain. if the message doesn't have a list-id header, we'll ask to match based on "message from" address. we don't ask the user in several cases: - if the destination/source mailbox is a special-use mailbox (e.g. trash,archive,sent,junk; inbox isn't included) - if the rule already exist (no point in adding it again). - if the user said "no, not for this list-id/from-address" in the past. - if the user said "no, not for messages moved to this mailbox" in the past. we'll add the rule if the message was moved out of the inbox. if the message was moved to the inbox, we check if there is a matching rule that we can remove. we now remember the "no" answers (for list-id, msg-from-addr and mailbox) in the account database. to implement the msgfrom rules, this adds support to rulesets for matching on message "from" address. before, we could match on smtp from address (and other fields). rulesets now also have a field for comments. webmail adds a note that it created the rule, with the date. manual editing of the rulesets is still in the webaccount page. this webmail functionality is just a convenient way to add/remove common rules.
This commit is contained in:
@ -757,6 +757,37 @@ type FromAddressSettings struct {
|
||||
ViewMode ViewMode
|
||||
}
|
||||
|
||||
// RulesetNoListID records a user "no" response to the question of
|
||||
// creating/removing a ruleset after moving a message with list-id header from/to
|
||||
// the inbox.
|
||||
type RulesetNoListID struct {
|
||||
ID int64
|
||||
RcptToAddress string `bstore:"nonzero"`
|
||||
ListID string `bstore:"nonzero"`
|
||||
ToInbox bool // Otherwise from Inbox to other mailbox.
|
||||
}
|
||||
|
||||
// RulesetNoMsgFrom records a user "no" response to the question of
|
||||
// creating/moveing a ruleset after moving a mesage with message "from" address
|
||||
// from/to the inbox.
|
||||
type RulesetNoMsgFrom struct {
|
||||
ID int64
|
||||
RcptToAddress string `bstore:"nonzero"`
|
||||
MsgFromAddress string `bstore:"nonzero"` // Unicode.
|
||||
ToInbox bool // Otherwise from Inbox to other mailbox.
|
||||
}
|
||||
|
||||
// RulesetNoMailbox represents a "never from/to this mailbox" response to the
|
||||
// question of adding/removing a ruleset after moving a message.
|
||||
type RulesetNoMailbox struct {
|
||||
ID int64
|
||||
|
||||
// The mailbox from/to which the move has happened.
|
||||
// Not a references, if mailbox is deleted, an entry becomes ineffective.
|
||||
MailboxID int64 `bstore:"nonzero"`
|
||||
ToMailbox bool // Whether MailboxID is the destination of the move (instead of source).
|
||||
}
|
||||
|
||||
// Types stored in DB.
|
||||
var DBTypes = []any{
|
||||
NextUIDValidity{},
|
||||
@ -774,6 +805,9 @@ var DBTypes = []any{
|
||||
LoginSession{},
|
||||
Settings{},
|
||||
FromAddressSettings{},
|
||||
RulesetNoListID{},
|
||||
RulesetNoMsgFrom{},
|
||||
RulesetNoMailbox{},
|
||||
}
|
||||
|
||||
// Account holds the information about a user, includings mailboxes, messages, imap subscriptions.
|
||||
@ -1758,7 +1792,7 @@ func (a *Account) SubscriptionEnsure(tx *bstore.Tx, name string) ([]Change, erro
|
||||
return []Change{ChangeAddSubscription{name, []string{`\NonExistent`}}}, nil
|
||||
}
|
||||
|
||||
// MessageRuleset returns the first ruleset (if any) that message the message
|
||||
// MessageRuleset returns the first ruleset (if any) that matches the message
|
||||
// represented by msgPrefix and msgFile, with smtp and validation fields from m.
|
||||
func MessageRuleset(log mlog.Log, dest config.Destination, m *Message, msgPrefix []byte, msgFile *os.File) *config.Ruleset {
|
||||
if len(dest.Rulesets) == 0 {
|
||||
@ -1786,6 +1820,11 @@ ruleset:
|
||||
continue ruleset
|
||||
}
|
||||
}
|
||||
if rs.MsgFromRegexpCompiled != nil {
|
||||
if m.MsgFromLocalpart == "" && m.MsgFromDomain == "" || !rs.MsgFromRegexpCompiled.MatchString(m.MsgFromLocalpart.String()+"@"+m.MsgFromDomain) {
|
||||
continue ruleset
|
||||
}
|
||||
}
|
||||
|
||||
if !rs.VerifiedDNSDomain.IsZero() {
|
||||
d := rs.VerifiedDNSDomain.Name()
|
||||
|
Reference in New Issue
Block a user