parse_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. package smtp
  2. import (
  3. "strings"
  4. "testing"
  5. )
  6. func TestParseParam(t *testing.T) {
  7. s := NewParser([]byte("SIZE=2000"))
  8. params, err := s.param()
  9. if strings.Compare(params[0], "SIZE") != 0 {
  10. t.Error("SIZE ecpected")
  11. }
  12. if strings.Compare(params[1], "2000") != 0 {
  13. t.Error("2000 ecpected")
  14. }
  15. if err != nil {
  16. t.Error("error not expected ", err)
  17. }
  18. s = NewParser([]byte("SI--ZE=2000 BODY=8BITMIME"))
  19. tup, err := s.parameters()
  20. if strings.Compare(tup[0][0], "SI--ZE") != 0 {
  21. t.Error("SI--ZE ecpected")
  22. }
  23. if strings.Compare(tup[0][1], "2000") != 0 {
  24. t.Error("2000 ecpected")
  25. }
  26. if strings.Compare(tup[1][0], "BODY") != 0 {
  27. t.Error("BODY expected", err)
  28. }
  29. if strings.Compare(tup[1][1], "8BITMIME") != 0 {
  30. t.Error("8BITMIME expected", err)
  31. }
  32. s = NewParser([]byte("SI--ZE-=2000 BODY=8BITMIME")) // illegal - after ZE
  33. tup, err = s.parameters()
  34. if err == nil {
  35. t.Error("error was expected ")
  36. }
  37. }
  38. func TestParseRcptTo(t *testing.T) {
  39. var s Parser
  40. err := s.RcptTo([]byte("<Postmaster>"))
  41. if err != nil {
  42. t.Error("error not expected ", err)
  43. }
  44. err = s.RcptTo([]byte("<[email protected]>"))
  45. if err != nil {
  46. t.Error("error not expected ", err)
  47. }
  48. if s.LocalPart != "postmaster" {
  49. t.Error("s.LocalPart should be: postmaster")
  50. }
  51. err = s.RcptTo([]byte("<[email protected]> NOTIFY=SUCCESS,FAILURE"))
  52. if err != nil {
  53. t.Error("error not expected ", err)
  54. }
  55. err = s.RcptTo([]byte("<\"Postmaster\">"))
  56. if err != nil {
  57. t.Error("error not expected ", err)
  58. }
  59. }
  60. func TestParseForwardPath(t *testing.T) {
  61. s := NewParser([]byte("<@a,@b:user@[227.0.0.1>")) // missing ]
  62. err := s.forwardPath()
  63. if err == nil {
  64. t.Error("error expected ", err)
  65. }
  66. s = NewParser([]byte("<@a,@b:user@[527.0.0.1>")) // ip out of range
  67. err = s.forwardPath()
  68. if err == nil {
  69. t.Error("error expected ", err)
  70. }
  71. // with a 'size' estmp param
  72. s = NewParser([]byte("<[email protected]> NOTIFY=FAILURE ORCPT=rfc822;[email protected]"))
  73. err = s.forwardPath()
  74. if err != nil {
  75. t.Error("error not expected ", err)
  76. }
  77. // tolerate a space at the front
  78. s = NewParser([]byte(" <[email protected]>"))
  79. err = s.forwardPath()
  80. if err != nil {
  81. t.Error("error not expected ", err)
  82. }
  83. // tolerate a space at the front, invalid
  84. s = NewParser([]byte(" <"))
  85. err = s.forwardPath()
  86. if err == nil {
  87. t.Error("error expected ", err)
  88. }
  89. // tolerate a space at the front, invalid
  90. s = NewParser([]byte(" "))
  91. err = s.forwardPath()
  92. if err == nil {
  93. t.Error("error expected ", err)
  94. }
  95. // empty
  96. s = NewParser([]byte(""))
  97. err = s.forwardPath()
  98. if err == nil {
  99. t.Error("error expected ", err)
  100. }
  101. }
  102. func TestParseReversePath(t *testing.T) {
  103. s := NewParser([]byte("<@a,@b:user@d>"))
  104. err := s.reversePath()
  105. if err != nil {
  106. t.Error("error not expected ", err)
  107. }
  108. s = NewParser([]byte("<@a,@b:user@d> param=some-value")) // includes a mail parameter
  109. err = s.reversePath()
  110. if err != nil {
  111. t.Error("error not expected ", err)
  112. }
  113. s = NewParser([]byte("<@a,@b:user@[227.0.0.1]>"))
  114. err = s.reversePath()
  115. if err != nil {
  116. t.Error("error not expected ", err)
  117. }
  118. s = NewParser([]byte("<>"))
  119. err = s.reversePath()
  120. if err != nil {
  121. t.Error("error not expected ", err)
  122. }
  123. s = NewParser([]byte(""))
  124. err = s.reversePath()
  125. if err == nil {
  126. t.Error("error expected ", err)
  127. }
  128. s = NewParser([]byte("[email protected]"))
  129. err = s.reversePath()
  130. if err == nil {
  131. t.Error("error expected ", err)
  132. }
  133. s = NewParser([]byte("<@ghg;$7@65"))
  134. err = s.reversePath()
  135. if err == nil {
  136. t.Error("error expected ", err)
  137. }
  138. // tolerate a space at the front
  139. s = NewParser([]byte(" <>"))
  140. err = s.reversePath()
  141. if err != nil {
  142. t.Error("error not expected ", err)
  143. }
  144. // tolerate a space at the front, invalid
  145. s = NewParser([]byte(" <"))
  146. err = s.reversePath()
  147. if err == nil {
  148. t.Error("error expected ", err)
  149. }
  150. // tolerate a space at the front, invalid
  151. s = NewParser([]byte(" "))
  152. err = s.reversePath()
  153. if err == nil {
  154. t.Error("error expected ", err)
  155. }
  156. // empty
  157. s = NewParser([]byte(" "))
  158. err = s.reversePath()
  159. if err == nil {
  160. t.Error("error expected ", err)
  161. }
  162. }
  163. func TestParseIpv6Address(t *testing.T) {
  164. s := NewParser([]byte("2001:0000:3238:DFE1:0063:0000:0000:FEFB"))
  165. err := s.ipv6AddressLiteral()
  166. if s.accept.String() != "2001:0:3238:dfe1:63::fefb" {
  167. t.Error("expected 2001:0:3238:dfe1:63::fefb, got:", s.accept.String())
  168. }
  169. if err != nil {
  170. t.Error("error not expected ", err)
  171. }
  172. s = NewParser([]byte("2001:3238:DFE1:6323:FEFB:2536:1.2.3.2"))
  173. err = s.ipv6AddressLiteral()
  174. if s.accept.String() != "2001:3238:dfe1:6323:fefb:2536:102:302" {
  175. t.Error("expected 2001:3238:dfe1:6323:fefb:2536:102:302, got:", s.accept.String())
  176. }
  177. if err != nil {
  178. t.Error("error not expected ", err)
  179. }
  180. s = NewParser([]byte("2001:0000:3238:DFE1:63:0000:0000:FEFB"))
  181. err = s.ipv6AddressLiteral()
  182. if s.accept.String() != "2001:0:3238:dfe1:63::fefb" {
  183. t.Error("expected 2001:0:3238:dfe1:63::fefb, got:", s.accept.String())
  184. }
  185. if err != nil {
  186. t.Error("error not expected ", err)
  187. }
  188. s = NewParser([]byte("2001:0000:3238:DFE1:63::FEFB"))
  189. err = s.ipv6AddressLiteral()
  190. if s.accept.String() != "2001:0:3238:dfe1:63::fefb" {
  191. t.Error("expected 2001:0:3238:dfe1:63::fefb, got:", s.accept.String())
  192. }
  193. if err != nil {
  194. t.Error("error not expected ", err)
  195. }
  196. s = NewParser([]byte("2001:0:3238:DFE1:63::FEFB"))
  197. err = s.ipv6AddressLiteral()
  198. if s.accept.String() != "2001:0:3238:dfe1:63::fefb" {
  199. t.Error("expected 2001:0:3238:dfe1:63::fefb, got:", s.accept.String())
  200. }
  201. if err != nil {
  202. t.Error("error not expected ", err)
  203. }
  204. s = NewParser([]byte("g001:0:3238:DFE1:63::FEFB"))
  205. err = s.ipv6AddressLiteral()
  206. if s.accept.String() != "" {
  207. t.Error("expected \"\", got:", s.accept.String())
  208. }
  209. if err == nil {
  210. t.Error("error expected ", err)
  211. }
  212. s = NewParser([]byte("g001:0:3238:DFE1::63::FEFB"))
  213. err = s.ipv6AddressLiteral()
  214. if s.accept.String() != "" {
  215. t.Error("expected \"\", got:", s.accept.String())
  216. }
  217. if err == nil {
  218. t.Error("error expected ", err)
  219. }
  220. }
  221. func TestParseIpv4Address(t *testing.T) {
  222. s := NewParser([]byte("0.0.0.255"))
  223. err := s.ipv4AddressLiteral()
  224. if s.accept.String() != "0.0.0.255" {
  225. t.Error("expected 0.0.0.255, got:", s.accept.String())
  226. }
  227. if err != nil {
  228. t.Error("error not expected ", err)
  229. }
  230. s = NewParser([]byte("0.0.0.256"))
  231. err = s.ipv4AddressLiteral()
  232. if s.accept.String() != "0.0.0.256" {
  233. t.Error("expected 0.0.0.256, got:", s.accept.String())
  234. }
  235. if err == nil {
  236. t.Error("error expected ", err)
  237. }
  238. }
  239. func TestParseMailBoxBad(t *testing.T) {
  240. // must be quoted
  241. s := NewParser([]byte("Abc\\@[email protected]"))
  242. err := s.mailbox()
  243. if err == nil {
  244. t.Error("error expected")
  245. }
  246. // must be quoted
  247. s = NewParser([]byte("Fred\\ [email protected]"))
  248. err = s.mailbox()
  249. if err == nil {
  250. t.Error("error expected")
  251. }
  252. }
  253. func TestParseMailbox(t *testing.T) {
  254. s := NewParser([]byte("jsmith@[IPv6:2001:db8::1]"))
  255. err := s.mailbox()
  256. if s.Domain != "2001:db8::1" {
  257. t.Error("expected domain: 2001:db8::1, got:", s.Domain)
  258. }
  259. if err != nil {
  260. t.Error("error not expected ")
  261. }
  262. s = NewParser([]byte("\"qu\\{oted\"@test.com"))
  263. err = s.mailbox()
  264. if err != nil {
  265. t.Error("error not expected ")
  266. }
  267. s = NewParser([]byte("\"qu\\{oted\"@[127.0.0.1]"))
  268. err = s.mailbox()
  269. if err != nil {
  270. t.Error("error not expected ")
  271. }
  272. s = NewParser([]byte("jsmith@[IPv6:2001:db8::1]"))
  273. err = s.mailbox()
  274. if err != nil {
  275. t.Error("error not expected ")
  276. }
  277. s = NewParser([]byte("Joe.\\[email protected]"))
  278. err = s.mailbox()
  279. if err == nil {
  280. t.Error("error expected ")
  281. }
  282. s = NewParser([]byte("\"Abc@def\"@example.com"))
  283. err = s.mailbox()
  284. if err != nil {
  285. t.Error("error not expected ")
  286. }
  287. s = NewParser([]byte("\"Fred Bloggs\"@example.com"))
  288. err = s.mailbox()
  289. if err != nil {
  290. t.Error("error not expected ")
  291. }
  292. s = NewParser([]byte("customer/[email protected]"))
  293. err = s.mailbox()
  294. if err != nil {
  295. t.Error("error not expected ")
  296. }
  297. s = NewParser([]byte("[email protected]"))
  298. err = s.mailbox()
  299. if err != nil {
  300. t.Error("error not expected ")
  301. }
  302. s = NewParser([]byte("!def!xyz%[email protected]"))
  303. err = s.mailbox()
  304. if err != nil {
  305. t.Error("error not expected ")
  306. }
  307. s = NewParser([]byte("[email protected]"))
  308. err = s.mailbox()
  309. if err != nil {
  310. t.Error("error not expected ")
  311. }
  312. }
  313. func TestParseLocalPart(t *testing.T) {
  314. s := NewParser([]byte("\"qu\\{oted\""))
  315. err := s.localPart()
  316. if s.LocalPart != "qu{oted" {
  317. t.Error("expected qu\\{oted, got:", s.LocalPart)
  318. }
  319. if s.LocalPartQuotes == true {
  320. t.Error("local part does not need to be quoted")
  321. }
  322. if err != nil {
  323. t.Error("error not expected ")
  324. }
  325. s = NewParser([]byte("dot.string"))
  326. err = s.localPart()
  327. if s.LocalPart != "dot.string" {
  328. t.Error("expected dot.string, got:", s.LocalPart)
  329. }
  330. if err != nil {
  331. t.Error("error not expected ")
  332. }
  333. s = NewParser([]byte("dot.st!ring"))
  334. err = s.localPart()
  335. if s.LocalPart != "dot.st!ring" {
  336. t.Error("expected dot.st!ring, got:", s.LocalPart)
  337. }
  338. if err != nil {
  339. t.Error("error not expected ")
  340. }
  341. s = NewParser([]byte("dot..st!ring")) // fail
  342. err = s.localPart()
  343. if err == nil {
  344. t.Error("error expected ")
  345. }
  346. }
  347. func TestParseQuotedString(t *testing.T) {
  348. s := NewParser([]byte("\"qu\\ oted\""))
  349. err := s.quotedString()
  350. if s.accept.String() != "qu oted" {
  351. t.Error("Expected qu oted, got:", s.accept.String())
  352. }
  353. if err != nil {
  354. t.Error("error not expected ")
  355. }
  356. s = NewParser([]byte("\"@\""))
  357. err = s.quotedString()
  358. if s.accept.String() != "@" {
  359. t.Error("Expected @, got:", s.accept.String())
  360. }
  361. if err != nil {
  362. t.Error("error not expected ")
  363. }
  364. }
  365. func TestParseDotString(t *testing.T) {
  366. s := NewParser([]byte("Joe..Blow"))
  367. err := s.dotString()
  368. if err == nil {
  369. t.Error("error expected ")
  370. }
  371. s = NewParser([]byte("Joe.Blow"))
  372. err = s.dotString()
  373. if s.accept.String() != "Joe.Blow" {
  374. t.Error("Expected Joe.Blow, got:", s.accept.String())
  375. }
  376. if err != nil {
  377. t.Error("error not expected ")
  378. }
  379. }
  380. func TestParsePath(t *testing.T) {
  381. s := NewParser([]byte("<foo>")) // requires @
  382. err := s.path()
  383. if err == nil {
  384. t.Error("error expected ")
  385. }
  386. s = NewParser([]byte("<@example.com,@test.com:[email protected]>"))
  387. err = s.path()
  388. if err != nil {
  389. t.Error("error not expected ")
  390. }
  391. s = NewParser([]byte("<@example.com>")) // no mailbox
  392. err = s.path()
  393. if err == nil {
  394. t.Error("error expected ")
  395. }
  396. s = NewParser([]byte("<[email protected] 1")) // no closing >
  397. err = s.path()
  398. if err == nil {
  399. t.Error("error expected ")
  400. }
  401. }
  402. func TestParseADL(t *testing.T) {
  403. s := NewParser([]byte("@example.com,@test.com"))
  404. err := s.adl()
  405. if err != nil {
  406. t.Error("error not expected ")
  407. }
  408. }
  409. func TestParseAtDomain(t *testing.T) {
  410. s := NewParser([]byte("@example.com"))
  411. err := s.atDomain()
  412. if err != nil {
  413. t.Error("error not expected ")
  414. }
  415. }
  416. func TestParseDomain(t *testing.T) {
  417. s := NewParser([]byte("a"))
  418. err := s.domain()
  419. if err != nil {
  420. t.Error("error not expected ")
  421. }
  422. s = NewParser([]byte("a^m.com"))
  423. err = s.domain()
  424. if err == nil {
  425. t.Error("error was expected ")
  426. }
  427. s = NewParser([]byte("a.com.gov"))
  428. err = s.domain()
  429. if err != nil {
  430. t.Error("error not expected ")
  431. }
  432. s = NewParser([]byte("wrong-.com"))
  433. err = s.domain()
  434. if err == nil {
  435. t.Error("error was expected ")
  436. }
  437. s = NewParser([]byte("wrong."))
  438. err = s.domain()
  439. if err == nil {
  440. t.Error("error was expected ")
  441. }
  442. }
  443. func TestParseSubDomain(t *testing.T) {
  444. s := NewParser([]byte("a"))
  445. err := s.subdomain()
  446. if err != nil {
  447. t.Error("error not expected ")
  448. }
  449. s = NewParser([]byte("-a"))
  450. err = s.subdomain()
  451. if err == nil {
  452. t.Error("error was expected ")
  453. }
  454. s = NewParser([]byte("a--"))
  455. err = s.subdomain()
  456. if err == nil {
  457. t.Error("error was expected ")
  458. }
  459. s = NewParser([]byte("a--"))
  460. err = s.subdomain()
  461. if err == nil {
  462. t.Error("error was expected ")
  463. }
  464. s = NewParser([]byte("a--b"))
  465. err = s.subdomain()
  466. if err != nil {
  467. t.Error("error was not expected ")
  468. }
  469. // although a---b looks like an illegal subdomain, it is rfc5321 grammar spec
  470. s = NewParser([]byte("a---b"))
  471. err = s.subdomain()
  472. if err != nil {
  473. t.Error("error was not expected ")
  474. }
  475. s = NewParser([]byte("abc"))
  476. err = s.subdomain()
  477. if err != nil {
  478. t.Error("error was not expected ")
  479. }
  480. s = NewParser([]byte("a-b-c"))
  481. err = s.subdomain()
  482. if err != nil {
  483. t.Error("error was not expected ")
  484. }
  485. }
  486. func TestPostmasterQuoted(t *testing.T) {
  487. var s Parser
  488. err := s.RcptTo([]byte("<\"Po\\stmas\\ter\">"))
  489. if err != nil {
  490. t.Error("error not expected ", err)
  491. }
  492. }
  493. func TestParse(t *testing.T) {
  494. s := NewParser([]byte("<"))
  495. err := s.reversePath()
  496. if err == nil {
  497. t.Error("< expected parse error")
  498. }
  499. // the @ needs to be quoted
  500. s = NewParser([]byte("<@[email protected]>"))
  501. err = s.reversePath()
  502. if err == nil {
  503. t.Error("expected parse error", err)
  504. }
  505. s = NewParser([]byte("<\"@m.conm\"@test.com>"))
  506. err = s.reversePath()
  507. if err != nil {
  508. t.Error("not expected parse error", err)
  509. }
  510. s = NewParser([]byte("<[email protected]>"))
  511. err = s.reversePath()
  512. if err != nil {
  513. t.Error("not expected parse error")
  514. }
  515. s = NewParser([]byte("<@test:[email protected]>"))
  516. err = s.reversePath()
  517. if err != nil {
  518. t.Error("not expected parse error")
  519. }
  520. s = NewParser([]byte("<@test,@test2:[email protected]>"))
  521. err = s.reversePath()
  522. if err != nil {
  523. t.Error("not expected parse error")
  524. }
  525. }
  526. func TestEhlo(t *testing.T) {
  527. var s Parser
  528. domain, ip, err := s.Ehlo([]byte(" hello.com"))
  529. if ip != nil {
  530. t.Error("ip should be nil")
  531. }
  532. if err != nil {
  533. t.Error(err)
  534. }
  535. if domain != "hello.com" {
  536. t.Error("domain not hello.com")
  537. }
  538. domain, ip, err = s.Ehlo([]byte(" [211.0.0.3]"))
  539. if err != nil {
  540. t.Error(err)
  541. }
  542. if ip == nil {
  543. t.Error("ip should not be nil")
  544. }
  545. if domain != "211.0.0.3" {
  546. t.Error("expecting domain to be 211.0.0.3")
  547. }
  548. }
  549. func TestHelo(t *testing.T) {
  550. var s Parser
  551. domain, err := s.Helo([]byte(" example.com"))
  552. if err != nil {
  553. t.Error(err)
  554. }
  555. if domain != "example.com" {
  556. t.Error("expecting domain = example.com")
  557. }
  558. domain, err = s.Helo([]byte(" exam_ple.com"))
  559. if err == nil {
  560. t.Error("expecting domain exam_ple.com to be invalid")
  561. }
  562. }
  563. func TestTransport(t *testing.T) {
  564. path := PathParam([]string{"BODY", "8bitmime"})
  565. transport := path.Transport()
  566. if transport != TransportType8bit {
  567. t.Error("transport was not 8bit")
  568. }
  569. path = []string{"BODY", "7bit"}
  570. transport = path.Transport()
  571. if transport != TransportType7bit {
  572. t.Error("transport was not 7bit")
  573. }
  574. path = []string{"BODY", "invalid"}
  575. transport = path.Transport()
  576. if transport != TransportTypeInvalid {
  577. t.Error("transport was not invalid")
  578. }
  579. path = []string{}
  580. transport = path.Transport()
  581. if transport != TransportTypeUnspecified {
  582. t.Error("transport was not unspecified")
  583. }
  584. }