(t *testing.T)
| 29 | } |
| 30 | |
| 31 | func TestValidateRecipients(t *testing.T) { |
| 32 | cases := []struct { |
| 33 | name string |
| 34 | groups [][]string |
| 35 | wantErr bool |
| 36 | }{ |
| 37 | {"empty groups", [][]string{}, false}, |
| 38 | {"empty slice", [][]string{{}}, false}, |
| 39 | {"single valid", [][]string{{"alice@example.com"}}, false}, |
| 40 | {"multiple groups, all valid", [][]string{{"a@x.com", "b@x.com"}, {"c@x.com"}, {"d@x.com"}}, false}, |
| 41 | {"display-name form", [][]string{{"Alice Smith <alice@example.com>"}}, false}, |
| 42 | {"IDN domain (Unicode)", [][]string{{"alice@пример.рф"}}, false}, |
| 43 | {"single invalid — no @", [][]string{{"not an email"}}, true}, |
| 44 | {"valid then invalid", [][]string{{"alice@x.com", "garbage"}}, true}, |
| 45 | {"invalid in CC group", [][]string{{"alice@x.com"}, {"oops"}, {"bob@x.com"}}, true}, |
| 46 | {"empty string in slice", [][]string{{"alice@x.com", ""}}, true}, |
| 47 | {"whitespace garbage", [][]string{{" "}}, true}, |
| 48 | // Typos that LOOK valid pass — SMTP layer handles those (this |
| 49 | // is the layering we explicitly want; see validateRecipients |
| 50 | // comment in api.go). |
| 51 | {"typo but syntactically valid", [][]string{{"bob@gmial.com"}}, false}, |
| 52 | } |
| 53 | for _, tc := range cases { |
| 54 | t.Run(tc.name, func(t *testing.T) { |
| 55 | err := validateRecipients(tc.groups...) |
| 56 | if (err != nil) != tc.wantErr { |
| 57 | t.Errorf("validateRecipients(%v) err=%v, wantErr=%v", tc.groups, err, tc.wantErr) |
| 58 | } |
| 59 | }) |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | func TestValidateDomain(t *testing.T) { |
| 64 | cases := []struct { |
nothing calls this directly
no test coverage detected