github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/net/mail/message_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package mail 6 7 import ( 8 "bytes" 9 "io/ioutil" 10 "reflect" 11 "strings" 12 "testing" 13 "time" 14 ) 15 16 var parseTests = []struct { 17 in string 18 header Header 19 body string 20 }{ 21 { 22 // RFC 5322, Appendix A.1.1 23 in: `From: John Doe <jdoe@machine.example> 24 To: Mary Smith <mary@example.net> 25 Subject: Saying Hello 26 Date: Fri, 21 Nov 1997 09:55:06 -0600 27 Message-ID: <1234@local.machine.example> 28 29 This is a message just to say hello. 30 So, "Hello". 31 `, 32 header: Header{ 33 "From": []string{"John Doe <jdoe@machine.example>"}, 34 "To": []string{"Mary Smith <mary@example.net>"}, 35 "Subject": []string{"Saying Hello"}, 36 "Date": []string{"Fri, 21 Nov 1997 09:55:06 -0600"}, 37 "Message-Id": []string{"<1234@local.machine.example>"}, 38 }, 39 body: "This is a message just to say hello.\nSo, \"Hello\".\n", 40 }, 41 } 42 43 func TestParsing(t *testing.T) { 44 for i, test := range parseTests { 45 msg, err := ReadMessage(bytes.NewBuffer([]byte(test.in))) 46 if err != nil { 47 t.Errorf("test #%d: Failed parsing message: %v", i, err) 48 continue 49 } 50 if !headerEq(msg.Header, test.header) { 51 t.Errorf("test #%d: Incorrectly parsed message header.\nGot:\n%+v\nWant:\n%+v", 52 i, msg.Header, test.header) 53 } 54 body, err := ioutil.ReadAll(msg.Body) 55 if err != nil { 56 t.Errorf("test #%d: Failed reading body: %v", i, err) 57 continue 58 } 59 bodyStr := string(body) 60 if bodyStr != test.body { 61 t.Errorf("test #%d: Incorrectly parsed message body.\nGot:\n%+v\nWant:\n%+v", 62 i, bodyStr, test.body) 63 } 64 } 65 } 66 67 func headerEq(a, b Header) bool { 68 if len(a) != len(b) { 69 return false 70 } 71 for k, as := range a { 72 bs, ok := b[k] 73 if !ok { 74 return false 75 } 76 if !reflect.DeepEqual(as, bs) { 77 return false 78 } 79 } 80 return true 81 } 82 83 func TestDateParsing(t *testing.T) { 84 tests := []struct { 85 dateStr string 86 exp time.Time 87 }{ 88 // RFC 5322, Appendix A.1.1 89 { 90 "Fri, 21 Nov 1997 09:55:06 -0600", 91 time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)), 92 }, 93 // RFC5322, Appendix A.6.2 94 // Obsolete date. 95 { 96 "21 Nov 97 09:55:06 GMT", 97 time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("GMT", 0)), 98 }, 99 // Commonly found format not specified by RFC 5322. 100 { 101 "Fri, 21 Nov 1997 09:55:06 -0600 (MDT)", 102 time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)), 103 }, 104 } 105 for _, test := range tests { 106 hdr := Header{ 107 "Date": []string{test.dateStr}, 108 } 109 date, err := hdr.Date() 110 if err != nil { 111 t.Errorf("Failed parsing %q: %v", test.dateStr, err) 112 continue 113 } 114 if !date.Equal(test.exp) { 115 t.Errorf("Parse of %q: got %+v, want %+v", test.dateStr, date, test.exp) 116 } 117 } 118 } 119 120 func TestAddressParsingError(t *testing.T) { 121 const txt = "=?iso-8859-2?Q?Bogl=E1rka_Tak=E1cs?= <unknown@gmail.com>" 122 _, err := ParseAddress(txt) 123 if err == nil || !strings.Contains(err.Error(), "charset not supported") { 124 t.Errorf(`mail.ParseAddress(%q) err: %q, want ".*charset not supported.*"`, txt, err) 125 } 126 } 127 128 func TestAddressParsing(t *testing.T) { 129 tests := []struct { 130 addrsStr string 131 exp []*Address 132 }{ 133 // Bare address 134 { 135 `jdoe@machine.example`, 136 []*Address{{ 137 Address: "jdoe@machine.example", 138 }}, 139 }, 140 // RFC 5322, Appendix A.1.1 141 { 142 `John Doe <jdoe@machine.example>`, 143 []*Address{{ 144 Name: "John Doe", 145 Address: "jdoe@machine.example", 146 }}, 147 }, 148 // RFC 5322, Appendix A.1.2 149 { 150 `"Joe Q. Public" <john.q.public@example.com>`, 151 []*Address{{ 152 Name: "Joe Q. Public", 153 Address: "john.q.public@example.com", 154 }}, 155 }, 156 { 157 `Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>`, 158 []*Address{ 159 { 160 Name: "Mary Smith", 161 Address: "mary@x.test", 162 }, 163 { 164 Address: "jdoe@example.org", 165 }, 166 { 167 Name: "Who?", 168 Address: "one@y.test", 169 }, 170 }, 171 }, 172 { 173 `<boss@nil.test>, "Giant; \"Big\" Box" <sysservices@example.net>`, 174 []*Address{ 175 { 176 Address: "boss@nil.test", 177 }, 178 { 179 Name: `Giant; "Big" Box`, 180 Address: "sysservices@example.net", 181 }, 182 }, 183 }, 184 // RFC 5322, Appendix A.1.3 185 // TODO(dsymonds): Group addresses. 186 187 // RFC 2047 "Q"-encoded ISO-8859-1 address. 188 { 189 `=?iso-8859-1?q?J=F6rg_Doe?= <joerg@example.com>`, 190 []*Address{ 191 { 192 Name: `Jörg Doe`, 193 Address: "joerg@example.com", 194 }, 195 }, 196 }, 197 // RFC 2047 "Q"-encoded US-ASCII address. Dumb but legal. 198 { 199 `=?us-ascii?q?J=6Frg_Doe?= <joerg@example.com>`, 200 []*Address{ 201 { 202 Name: `Jorg Doe`, 203 Address: "joerg@example.com", 204 }, 205 }, 206 }, 207 // RFC 2047 "Q"-encoded UTF-8 address. 208 { 209 `=?utf-8?q?J=C3=B6rg_Doe?= <joerg@example.com>`, 210 []*Address{ 211 { 212 Name: `Jörg Doe`, 213 Address: "joerg@example.com", 214 }, 215 }, 216 }, 217 // RFC 2047, Section 8. 218 { 219 `=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>`, 220 []*Address{ 221 { 222 Name: `André Pirard`, 223 Address: "PIRARD@vm1.ulg.ac.be", 224 }, 225 }, 226 }, 227 // Custom example of RFC 2047 "B"-encoded ISO-8859-1 address. 228 { 229 `=?ISO-8859-1?B?SvZyZw==?= <joerg@example.com>`, 230 []*Address{ 231 { 232 Name: `Jörg`, 233 Address: "joerg@example.com", 234 }, 235 }, 236 }, 237 // Custom example of RFC 2047 "B"-encoded UTF-8 address. 238 { 239 `=?UTF-8?B?SsO2cmc=?= <joerg@example.com>`, 240 []*Address{ 241 { 242 Name: `Jörg`, 243 Address: "joerg@example.com", 244 }, 245 }, 246 }, 247 // Custom example with "." in name. For issue 4938 248 { 249 `Asem H. <noreply@example.com>`, 250 []*Address{ 251 { 252 Name: `Asem H.`, 253 Address: "noreply@example.com", 254 }, 255 }, 256 }, 257 } 258 for _, test := range tests { 259 if len(test.exp) == 1 { 260 addr, err := ParseAddress(test.addrsStr) 261 if err != nil { 262 t.Errorf("Failed parsing (single) %q: %v", test.addrsStr, err) 263 continue 264 } 265 if !reflect.DeepEqual([]*Address{addr}, test.exp) { 266 t.Errorf("Parse (single) of %q: got %+v, want %+v", test.addrsStr, addr, test.exp) 267 } 268 } 269 270 addrs, err := ParseAddressList(test.addrsStr) 271 if err != nil { 272 t.Errorf("Failed parsing (list) %q: %v", test.addrsStr, err) 273 continue 274 } 275 if !reflect.DeepEqual(addrs, test.exp) { 276 t.Errorf("Parse (list) of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp) 277 } 278 } 279 } 280 281 func TestAddressFormatting(t *testing.T) { 282 tests := []struct { 283 addr *Address 284 exp string 285 }{ 286 { 287 &Address{Address: "bob@example.com"}, 288 "<bob@example.com>", 289 }, 290 { 291 &Address{Name: "Bob", Address: "bob@example.com"}, 292 `"Bob" <bob@example.com>`, 293 }, 294 { 295 // note the ö (o with an umlaut) 296 &Address{Name: "Böb", Address: "bob@example.com"}, 297 `=?utf-8?q?B=C3=B6b?= <bob@example.com>`, 298 }, 299 { 300 &Address{Name: "Bob Jane", Address: "bob@example.com"}, 301 `"Bob Jane" <bob@example.com>`, 302 }, 303 { 304 &Address{Name: "Böb Jacöb", Address: "bob@example.com"}, 305 `=?utf-8?q?B=C3=B6b_Jac=C3=B6b?= <bob@example.com>`, 306 }, 307 } 308 for _, test := range tests { 309 s := test.addr.String() 310 if s != test.exp { 311 t.Errorf("Address%+v.String() = %v, want %v", *test.addr, s, test.exp) 312 } 313 } 314 }