You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by "Matthieu Baechler (JIRA)" <se...@james.apache.org> on 2018/04/19 14:57:00 UTC

[jira] [Created] (JAMES-2380) RRT design discussion

Matthieu Baechler created JAMES-2380:
----------------------------------------

             Summary: RRT design discussion
                 Key: JAMES-2380
                 URL: https://issues.apache.org/jira/browse/JAMES-2380
             Project: James Server
          Issue Type: Improvement
            Reporter: Matthieu Baechler


We worked a lot on RecipientRewriteTable lately and everything is very complicated right now.

There are several interleaved concepts right now, that I'll try to explain here.

The goal of RecipientRewriteTable is to allow rewrite a Recipient to another one (or generate and error).

Such rewrite is done with so-called Mapping(s) : a Mapping is a rule that given a User (== recipient), generates either an error or new User(s).

At start, there were simple rule types :
* address mapping that allows to go from (for example) bob@foo to bob@bar
* regex mapping that allows to match a regex against the recipient mail address and output a new one, optionally using matching groups
* domain mapping that allows to rewrite all users of a domain into users of another one
* error mapping that would prevent delivery to an given user

We recently added :
* group, like address mapping but allows to register several rewrite outputs
* forward, like group but using a different type allows to filter on the wanted type for administrative purpose

Here are a list of design problems I see :

1. Error has probably nothing to do in the rewrite feature

It's very likely that error mapping is in fact the job of another mailet (and should be stored elsewhere).

2. we mix how we rewrite something with the original intent of the rule writer.

We could argue that every types of rewrite rules can be expressed by a matching regex and a list of output expression.

If performance is a problem here, we could specialize rewriter like that :

{code}
Type: Domain Alias
Sample config: foo -> bar (could also be written *@foo -> *@bar)
Cases:
bob@foo -> bob@bar
joe@foo -> joe@bar
john@poney -> john@poney

Type: Wildcard
Sample config: * -> foo@bar
Cases:
bob@foo -> foo@bar
joe@foo -> foo@bar
john@poney -> foo@bar 

Type: UserWildcard
Sample config: bob@* -> joe@*
Cases:
bob@foo -> joe@foo
bob@bar -> joe@bar
joe@foo -> joe@foo

Type: UserWildcard
Sample config: joe@* -> joe@bar
Cases:
bob@foo -> bob@foo
joe@bar -> joe@bar
joe@foo -> joe@bar
john@poney -> john@poney 

Type: DomainWildcard
Sample config: *@foo -> joe@bar
Cases:
bob@foo -> joe@bar
joe@foo -> joe@bar
john@poney -> john@poney 

Type: User Alias
Sample config: bob@foo -> joe@bar
Cases:
bob@foo -> joe@bar
joe@bar -> joe@bar
john@poney -> john@poney
{code}

A good way to keep the user intent next to the rule definition would be to store such a structure :

Mapping {
  intent: {
    type: "group",
    definition: {
      //type specific definition
    }
  }
  rule: {
    type: "Address",
    definition: {
      //type specific definition
    }
  }
}

Once we have such a structure, admin commands would very well add/modify/delete mappings based on "intent" and the rewrite engine would only care about applying rewrite rules.

3. The process should be as simple as (pseudo-code) :

Input : Recipient

{code}
Stream<MailAddress> rewrite(MailAddress input, limitLoop = 10) {
  if (limitLoop <= 0) {
    throw new loopDetectedException();
  }
  Rule rule = RRT.findFirstRuleFor(input);
  Stream<MailAddress> rewrittenRecipients = rule.rewrite(input);
  return rewrittenRecipients.flatMap(recipient -> rewrite(recipient, limitLoop - 1));
}
{code}



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org