1package config
2
3import (
4 "errors"
5 "fmt"
6 "strings"
7
8 "golang.org/x/text/unicode/norm"
9)
10
11// CheckMailboxName checks if name is valid, returning an INBOX-normalized name.
12func CheckMailboxName(name string, allowInbox bool) (normalizedName string, isInbox bool, rerr error) {
13 t := strings.Split(name, "/")
14 if strings.EqualFold(t[0], "inbox") {
15 if len(name) == len("inbox") && !allowInbox {
16 return "", true, fmt.Errorf("special mailbox name Inbox not allowed")
17 }
18 name = "Inbox" + name[len("Inbox"):]
19 }
20
21 if norm.NFC.String(name) != name {
22 return "", false, errors.New("non-unicode-normalized mailbox names not allowed")
23 }
24
25 for _, e := range t {
26 switch e {
27 case "":
28 return "", false, errors.New("empty mailbox name")
29 case ".":
30 return "", false, errors.New(`"." not allowed`)
31 case "..":
32 return "", false, errors.New(`".." not allowed`)
33 }
34 }
35 if strings.HasPrefix(name, "/") || strings.HasSuffix(name, "/") || strings.Contains(name, "//") {
36 return "", false, errors.New("bad slashes in mailbox name")
37 }
38
39 // "%" and "*" are difficult to use with the IMAP LIST command, but we allow mostly
40 // allow them. ../rfc/3501:1002 ../rfc/9051:983
41 if strings.HasPrefix(name, "#") {
42 return "", false, errors.New("mailbox name cannot start with hash due to conflict with imap namespaces")
43 }
44
45 // "#" and "&" are special in IMAP mailbox names. "#" for namespaces, "&" for
46 // IMAP-UTF-7 encoding. We do allow them. ../rfc/3501:1018 ../rfc/9051:991
47
48 for _, c := range name {
49 // ../rfc/3501:999 ../rfc/6855:192 ../rfc/9051:979
50 if c <= 0x1f || c >= 0x7f && c <= 0x9f || c == 0x2028 || c == 0x2029 {
51 return "", false, errors.New("control characters not allowed in mailbox name")
52 }
53 }
54 return name, false, nil
55}
56