2

When I register on websites I use their domain in my email, for example serverfault.com@example.com. I'd like to file each domain into a separate IMAP folder using sieve and I've created the script below:

if envelope :regex "to" ["^(.*\\.uk)@", "^(.*\\.com)@", "^(.*\\.org)@"] {
  set :lower "fromdomain" "${1}";
  if string :is "${fromdomain}" "" {
    keep;
  } else {
    fileinto "domains.${fromdomain}";
  }
}

However, my server is configured to use '.' as the folder separator so this email would go into:

domains
  serverfault
    com      <<<

instead of:

domains
  serverfault.com      <<<

As I'd be happy with "serverfault com" I've tried looking for a string replacement function, but sieve doesn't appear to have one. Straight concatenation i.e. serverfaultcom would get confusing.

I'd need all parts of the domain so that test.serverfault.com and serverfault.co.uk are filed separately.

Is there another trick that could do this, or something close?

The mail server is hosted on debian-jessie using Bytemark's Symbiosis admin tools.

2 Answers2

0

I've managed it with this rule:

if envelope :regex "to" "([^.]*)\\.?([^.]*)\\.?([^.]*)\\.?([^.]*)\\.?([^.]*)\\.?([^.]*)@.*$" {
  if string :is "${1}" "" {} else { set :lower "part1" "${1} "; }
  if string :is "${2}" "" {} else { set :lower "part2" "${2} "; }
  if string :is "${3}" "" {} else { set :lower "part3" "${3} "; }
  if string :is "${4}" "" {} else { set :lower "part4" "${4} "; }
  if string :is "${5}" "" {} else { set :lower "part5" "${5} "; }
  if string :is "${6}" "" {} else { set :lower "part6" "${6} "; }

  set "targetfolder" "${part1}${part2}${part3}${part4}${part5}${part6}";

  if string :is "${targetfolder}" "" {} else {
    fileinto "domains.${targetfolder}";
  }
}

The regex is a repeating ([^.]*)\.? until the last one. This captures non-dots until there is a dot. The last just omits the last dot and matches from an @ to the end of the address.

Then for each captured string if it isn't empty I add a space after it. If it is empty it won't get a space and that part stays empty. You need "part" as you can't assign to match variables.

I then concatenate all the strings with spaces or empties to get the folder name I want.

0

I know this is quite the old post but I just stumbled across the same issue and came to a similar yet from my perspective a little more efficient solution. Maybe this helps somebody else looking for something similar :)

if header :regex "X-Delivered-to" "domain[\\+|\\.]([^.]*)\\.?([^.]*)@.*$" {
  if string :is "${1}" "" {} else { set :lower "part1" "${1}"; }
  if string :is "${2}" "" {} else { set :lower "part2" "${2}"; }

  set "domain" "${part1}^${part2}";

  if string :is "${domain}" "" {} else {
    fileinto :create "INBOX.INBOX.Journal.${domain}";
    stop;
  }
}

Instead of allowing endless levels of subdirectories I decided for one only (INBOX.Journal.*) where all domain directories are located.

I also changed the regex to match the suffix domain[+|.]. This alows me to use both subdomain-mapping (domain.serverfault.com@user.domain.com) as well as plus addressing (domain+serverfault@domain.com). I did this as I looked for a possibility to not reveal my name for some email-adresses.

Last but not least please note the ^ sign in the set domain line. This instructs the mailserver to create a directory with a . in its name instead of creating another sublevel.