/libgo/go/net/mail/message_test.go

https://code.google.com/p/gofrontend/ · Go · 295 lines · 265 code · 10 blank · 20 comment · 29 complexity · 7520cb25b1cbb703450091c97b926933 MD5 · raw file

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