github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/pkg/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 UTF-8 address. 198 { 199 `=?utf-8?q?J=C3=B6rg_Doe?= <joerg@example.com>`, 200 []*Address{ 201 { 202 Name: `Jörg Doe`, 203 Address: "joerg@example.com", 204 }, 205 }, 206 }, 207 // RFC 2047, Section 8. 208 { 209 `=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>`, 210 []*Address{ 211 { 212 Name: `André Pirard`, 213 Address: "PIRARD@vm1.ulg.ac.be", 214 }, 215 }, 216 }, 217 // Custom example of RFC 2047 "B"-encoded ISO-8859-1 address. 218 { 219 `=?ISO-8859-1?B?SvZyZw==?= <joerg@example.com>`, 220 []*Address{ 221 { 222 Name: `Jörg`, 223 Address: "joerg@example.com", 224 }, 225 }, 226 }, 227 // Custom example of RFC 2047 "B"-encoded UTF-8 address. 228 { 229 `=?UTF-8?B?SsO2cmc=?= <joerg@example.com>`, 230 []*Address{ 231 { 232 Name: `Jörg`, 233 Address: "joerg@example.com", 234 }, 235 }, 236 }, 237 // Custom example with "." in name. For issue 4938 238 { 239 `Asem H. <noreply@example.com>`, 240 []*Address{ 241 { 242 Name: `Asem H.`, 243 Address: "noreply@example.com", 244 }, 245 }, 246 }, 247 } 248 for _, test := range tests { 249 if len(test.exp) == 1 { 250 addr, err := ParseAddress(test.addrsStr) 251 if err != nil { 252 t.Errorf("Failed parsing (single) %q: %v", test.addrsStr, err) 253 continue 254 } 255 if !reflect.DeepEqual([]*Address{addr}, test.exp) { 256 t.Errorf("Parse (single) of %q: got %+v, want %+v", test.addrsStr, addr, test.exp) 257 } 258 } 259 260 addrs, err := ParseAddressList(test.addrsStr) 261 if err != nil { 262 t.Errorf("Failed parsing (list) %q: %v", test.addrsStr, err) 263 continue 264 } 265 if !reflect.DeepEqual(addrs, test.exp) { 266 t.Errorf("Parse (list) of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp) 267 } 268 } 269 } 270 271 func TestAddressFormatting(t *testing.T) { 272 tests := []struct { 273 addr *Address 274 exp string 275 }{ 276 { 277 &Address{Address: "bob@example.com"}, 278 "<bob@example.com>", 279 }, 280 { 281 &Address{Name: "Bob", Address: "bob@example.com"}, 282 `"Bob" <bob@example.com>`, 283 }, 284 { 285 // note the ö (o with an umlaut) 286 &Address{Name: "Böb", Address: "bob@example.com"}, 287 `=?utf-8?q?B=C3=B6b?= <bob@example.com>`, 288 }, 289 { 290 &Address{Name: "Bob Jane", Address: "bob@example.com"}, 291 `"Bob Jane" <bob@example.com>`, 292 }, 293 { 294 &Address{Name: "Böb Jacöb", Address: "bob@example.com"}, 295 `=?utf-8?q?B=C3=B6b_Jac=C3=B6b?= <bob@example.com>`, 296 }, 297 } 298 for _, test := range tests { 299 s := test.addr.String() 300 if s != test.exp { 301 t.Errorf("Address%+v.String() = %v, want %v", *test.addr, s, test.exp) 302 } 303 } 304 }