1package smtp
2
3import (
4 "errors"
5 "testing"
6)
7
8func TestParseLocalpart(t *testing.T) {
9 good := func(s string) {
10 t.Helper()
11 _, err := ParseLocalpart(s)
12 if err != nil {
13 t.Fatalf("unexpected error for localpart %q: %v", s, err)
14 }
15 }
16
17 bad := func(s string) {
18 t.Helper()
19 _, err := ParseLocalpart(s)
20 if err == nil {
21 t.Fatalf("did not see expected error for localpart %q", s)
22 }
23 if !errors.Is(err, ErrBadLocalpart) {
24 t.Fatalf("expected ErrBadLocalpart, got %v", err)
25 }
26 }
27
28 good("user")
29 good("a")
30 good("a.b.c")
31 good(`""`)
32 good(`"ok"`)
33 good(`"a.bc"`)
34 bad("")
35 bad(`"`) // missing ending dquot
36 bad("\x00") // control not allowed
37 bad("\"\\") // ending with backslash
38 bad("\"\x01") // control not allowed in dquote
39 bad(`""leftover`) // leftover data after close dquote
40}
41
42func TestParseAddress(t *testing.T) {
43 good := func(s string) {
44 t.Helper()
45 _, err := ParseAddress(s)
46 if err != nil {
47 t.Fatalf("unexpected error for localpart %q: %v", s, err)
48 }
49 }
50
51 bad := func(s string) {
52 t.Helper()
53 _, err := ParseAddress(s)
54 if err == nil {
55 t.Fatalf("did not see expected error for localpart %q", s)
56 }
57 if !errors.Is(err, ErrBadAddress) {
58 t.Fatalf("expected ErrBadAddress, got %v", err)
59 }
60 }
61
62 good("user@example.com")
63 bad("user@@example.com")
64 bad("user") // missing @domain
65 bad("@example.com") // missing localpart
66 bad(`"@example.com`) // missing ending dquot or domain
67 bad("\x00@example.com") // control not allowed
68 bad("\"\\@example.com") // missing @domain
69 bad("\"\x01@example.com") // control not allowed in dquote
70 bad(`""leftover@example.com`) // leftover data after close dquot
71}
72
73func TestPackLocalpart(t *testing.T) {
74 var l = []struct {
75 input, expect string
76 }{
77 {``, `""`}, // No atom.
78 {`a.`, `"a."`}, // Empty atom not allowed.
79 {`a.b`, `a.b`}, // Fine.
80 {"azAZ09!#$%&'*+-/=?^_`{|}~", "azAZ09!#$%&'*+-/=?^_`{|}~"}, // All ascii that are fine as atom.
81 {` `, `" "`},
82 {"\x01", "\"\x01\""}, // todo: should probably return an error for control characters.
83 {"<>", `"<>"`},
84 }
85
86 for _, e := range l {
87 r := Localpart(e.input).String()
88 if r != e.expect {
89 t.Fatalf("PackLocalpart for %q, expect %q, got %q", e.input, e.expect, r)
90 }
91 }
92}
93