1

I'm looking for a Regex that matches all addresses of a specific domain "domain.tld", except with a specific local part "fritzbox" (as an example). Unfortunately, the Sieve engine of the mail server I'm using does not support any lookarounds.

I've been here and elsewhere for hours and days, but still can't find the solution. Although there is quite a helpful example such as…

^(([^f].{2}|.[^o].|.{2}[^o]).*|.{0,2})$

…which works for any string starting with "foo", I wasn't able to adapt it to the string "fritzbox", followed by the domain "domain.tld". I'm simply not sure what these tokens "{2}" and "{0,2}" are doing exactly (must have to do with the number of characters of the string to be tested?) and why they are needed (also because the logic of this example is not being explained in the thread above).

As a sort of blind guessing, I tried…

^(([^f].{7}|.[^r].|.[^i].|.[^t].|.[^z].|.[^b].|.[^o].|.{7}[^x]).*|.{0,7})@domain\.tld$

…but that doesn't work.

I do of course know that I can do something like…

if allof (address :domain :matches "from" "domain.tld", not address :localpart :is "from" "fritzbox")
{
    do something;
}

…in Sieve without Regex, but this needs to be an extra Sieve rule for this specific purpose then. I'd rather would like to be able to combine it with a bunch of other "anyof" conditions, that's why I would prefer a Regex that I can include in the same rule that contains all other conditions.

Any idea (with explanation)…?

myfxp
  • 25
  • 1
  • 8
  • 1
    You need to add all the options. If you use the dot for the local part (any character which even includes e.g. space or `@`) the options are: 1.) any substrings < 8 char length: `.{1,7}` 2.) any substrings >= 9 char length: `.{9,}` 3.) For eight length list all options that don't have an `f` on the first positon OR don't have an `r` on the second OR... All together something like [`^(?:.{0,7}|[^f].{7}|.[^r].{6}|..[^i].{5}|...[^t].{4}|.{4}[^z]...|.{5}[^b]..|.{6}[^o].|.{7}[^x]|.{9,})@domain\.tld$`](https://regex101.com/r/SBxJgr/2) (it's late, maybe there is mistake). – bobble bubble Aug 21 '23 at 00:54
  • `.{2}` matches the `.` twice. `.{0,2}` matches the `.` either 0, 1 or 2 times. – Jerry Jeremiah Aug 21 '23 at 01:07
  • @bobblebubble Thanks a lot, this seems to work, but I’m still trying to figure out why. I believe to understand that `[^f].{7}` means "no `f` on the first position, followed by any 7 characters". And `.[^r].{6}` means "any character on the first position, no `r` on the second, followed by any 6 characters". Am I correct that `.{5}[^b]..` could also be written as `.....[^b].{2}` and that your version is just the shorter one? If so, I believe to get closer to a better understanding. But what I still don’t get is that this OR logic is a working one, shouldn’t it be AND? – myfxp Aug 22 '23 at 01:31
  • @JerryJeremiah Thanks, I know that (regex101 is telling me). But I didn’t catch the logic at that time. – myfxp Aug 22 '23 at 01:38
  • @bobblebubble I do of course know that there is no AND operator in Regex, but that doesn’t cancel my surprise that OR is working here. – myfxp Aug 22 '23 at 01:48
  • @bobblebubble Damn. When I just tried to save this rule in Sieve, I get a server error. Apparently Sieve doesn’t like the `^(?:.{0,7}|` at the beginning. If I delete it, then Sieve accepts the rule, but then it doesn’t work anymore (in regex101, respectively I get a pattern error there). Hmpf. – myfxp Aug 22 '23 at 02:55
  • 1
    @myfxp Yes, it could also be written as `.....[^b].{2}` I just tried to keep it short like you have noticed! Regarding the `^(?:.{0,7}|` at the beginning, maybe *non-capturing groups* are not supported. Just try `(` instead of `(?:` making this part `^(.{0,7}|`... The logic is indeed confusing, also to me. [A shorter example `^(?:[^a].|.[^b])$`](https://regex101.com/r/bp3oWq/1) to disallow `ab`. Match two characters not starting with `a` or not ending with `b`. It's a workaround, with lookahead you'd just use [`^(?!ab)..$`](https://regex101.com/r/nLyQpz/1). – bobble bubble Aug 22 '23 at 10:45
  • @bobblebubble Just to confirm that `^(.{0,7}|` is working with Sieve. – myfxp Aug 26 '23 at 15:18
  • @myfxp Great you got it working, I added my comment as an answer. – bobble bubble Aug 26 '23 at 17:02

1 Answers1

2

You need to alternate between all possible options:

  1. Any substrings <= 7 charcters length: .{0,7}
  2. Any substrings >= 9 characters length: .{9,}
  3. For the disallowed substring of eight characters length list all options that don't have an f on the first positon OR don't have an r on the second OR don't have an i on the third position...
^(.{0,7}|[^f].{7}|.[^r].{6}|..[^i].{5}|...[^t].{4}|.{4}[^z]...|.{5}[^b]..|.{6}[^o].|.{7}[^x]|.{9,})@domain\.tld$

Here is the demo at regex101 (I used either dots or {n} quantifier to reduce the pattern length)

bobble bubble
  • 16,888
  • 3
  • 27
  • 46