@@ -5,6 +5,7 @@ package integration
55import (
66 "fmt"
77 "os"
8+ "strings"
89 "testing"
910
1011 "github.com/eggsampler/acme/v3"
@@ -33,3 +34,129 @@ func TestTooBigOrderError(t *testing.T) {
3334 test .AssertEquals (t , prob .Detail , "Error creating new order :: Order cannot contain more than 100 DNS names" )
3435 }
3536}
37+
38+ // TestAccountEmailError tests that registering a new account, or updating an
39+ // account, with invalid contact information produces the expected problem
40+ // result to ACME clients.
41+ func TestAccountEmailError (t * testing.T ) {
42+ t .Parallel ()
43+ os .Setenv ("DIRECTORY" , "http://boulder:4001/directory" )
44+
45+ /*
46+ // TODO(@cpu): Uncomment this when the too-long test case is re-added.
47+ var longStringBuf strings.Builder
48+ for i := 0; i < 254; i++ {
49+ longStringBuf.WriteRune('a')
50+ }
51+ */
52+
53+ createErrorPrefix := "Error creating new account :: "
54+ updateErrorPrefix := "Unable to update account :: "
55+
56+ testCases := []struct {
57+ name string
58+ contacts []string
59+ expectedProbType string
60+ expectedProbDetail string
61+ }{
62+ {
63+ name : "empty contact" ,
64+ contacts : []string {"mailto:valid@valid.com" , "" },
65+ expectedProbType : "urn:ietf:params:acme:error:invalidEmail" ,
66+ expectedProbDetail : `empty contact` ,
67+ },
68+ {
69+ name : "empty proto" ,
70+ contacts : []string {"mailto:valid@valid.com" , " " },
71+ expectedProbType : "urn:ietf:params:acme:error:invalidEmail" ,
72+ expectedProbDetail : `contact method "" is not supported` ,
73+ },
74+ {
75+ name : "empty mailto" ,
76+ contacts : []string {"mailto:valid@valid.com" , "mailto:" },
77+ expectedProbType : "urn:ietf:params:acme:error:invalidEmail" ,
78+ expectedProbDetail : `"" is not a valid e-mail address` ,
79+ },
80+ {
81+ name : "non-ascii mailto" ,
82+ contacts : []string {"mailto:valid@valid.com" , "mailto:cpu@l̴etsencrypt.org" },
83+ expectedProbType : "urn:ietf:params:acme:error:invalidEmail" ,
84+ expectedProbDetail : `contact email ["mailto:cpu@l̴etsencrypt.org"] contains non-ASCII characters` ,
85+ },
86+ {
87+ name : "too many contacts" ,
88+ contacts : []string {"a" , "b" , "c" , "d" },
89+ expectedProbType : "urn:ietf:params:acme:error:malformed" ,
90+ expectedProbDetail : `too many contacts provided: 4 > 3` ,
91+ },
92+ {
93+ name : "invalid contact" ,
94+ contacts : []string {"mailto:valid@valid.com" , "mailto:a@" },
95+ expectedProbType : "urn:ietf:params:acme:error:invalidEmail" ,
96+ expectedProbDetail : `"a@" is not a valid e-mail address` ,
97+ },
98+ {
99+ name : "forbidden contact domain" ,
100+ contacts : []string {"mailto:valid@valid.com" , "mailto:a@example.com" },
101+ expectedProbType : "urn:ietf:params:acme:error:invalidEmail" ,
102+ expectedProbDetail : "invalid contact domain. Contact emails @example.com are forbidden" ,
103+ },
104+ {
105+ name : "contact domain invalid TLD" ,
106+ contacts : []string {"mailto:valid@valid.com" , "mailto:a@example.cpu" },
107+ expectedProbType : "urn:ietf:params:acme:error:invalidEmail" ,
108+ expectedProbDetail : `contact email "a@example.cpu" has invalid domain : Domain name does not end with a valid public suffix (TLD)` ,
109+ },
110+ {
111+ name : "contact domain invalid" ,
112+ contacts : []string {"mailto:valid@valid.com" , "mailto:a@example./.com" },
113+ expectedProbType : "urn:ietf:params:acme:error:invalidEmail" ,
114+ expectedProbDetail : "contact email \" a@example./.com\" has invalid domain : Domain name contains an invalid character" ,
115+ },
116+ /*
117+ // NOTE(@cpu): Disabled for now - causes serverInternal err when SA saves
118+ // contacts.
119+ {
120+ name: "too long contact",
121+ contacts: []string{
122+ fmt.Sprintf("mailto:%s@a.com", longStringBuf.String()),
123+ },
124+ expectedProbType: "urn:ietf:params:acme:error:invalidEmail",
125+ expectedProbDetail: "??????",
126+ },
127+ */
128+ }
129+
130+ for _ , tc := range testCases {
131+ t .Run (tc .name , func (t * testing.T ) {
132+ // First try registering a new account and ensuring the expected problem occurs
133+ if _ , err := makeClient (tc .contacts ... ); err != nil {
134+ if prob , ok := err .(acme.Problem ); ! ok {
135+ t .Fatalf ("expected acme.Problem error got %#v" , err )
136+ } else {
137+ test .AssertEquals (t , prob .Type , tc .expectedProbType )
138+ test .AssertEquals (t , prob .Detail , createErrorPrefix + tc .expectedProbDetail )
139+ }
140+ } else if err == nil {
141+ t .Errorf ("expected %s type problem for %q, got nil" ,
142+ tc .expectedProbType , strings .Join (tc .contacts , "," ))
143+ }
144+
145+ // Next try making a client with a good contact and updating with the test
146+ // case contact info. The same problem should occur.
147+ c , err := makeClient ("mailto:valid@valid.com" )
148+ test .AssertNotError (t , err , "failed to create account with valid contact" )
149+ if _ , err := c .UpdateAccount (c .Account , tc .contacts ... ); err != nil {
150+ if prob , ok := err .(acme.Problem ); ! ok {
151+ t .Fatalf ("expected acme.Problem error after updating account got %#v" , err )
152+ } else {
153+ test .AssertEquals (t , prob .Type , tc .expectedProbType )
154+ test .AssertEquals (t , prob .Detail , updateErrorPrefix + tc .expectedProbDetail )
155+ }
156+ } else if err == nil {
157+ t .Errorf ("expected %s type problem after updating account to %q, got nil" ,
158+ tc .expectedProbType , strings .Join (tc .contacts , "," ))
159+ }
160+ })
161+ }
162+ }
0 commit comments