guerrilla_test.go 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148
  1. // integration / smokeless
  2. // =======================
  3. // Tests are in a different package so we can test as a consumer of the guerrilla package
  4. // The following are integration / smokeless, that test the overall server.
  5. // (Please put unit tests to go in a different file)
  6. // How it works:
  7. // Server's log output is redirected to the logBuffer which is then used by the tests to look for expected behaviour
  8. // the package sets up the logBuffer & redirection by the use of package init()
  9. // (self signed certs are also generated on each run)
  10. // server's responses from a connection are also used to check for expected behaviour
  11. // to run:
  12. // $ go test
  13. package test
  14. import (
  15. "encoding/json"
  16. "testing"
  17. log "github.com/Sirupsen/logrus"
  18. "time"
  19. "github.com/flashmob/go-guerrilla"
  20. "github.com/flashmob/go-guerrilla/backends"
  21. "bufio"
  22. "bytes"
  23. "crypto/tls"
  24. "errors"
  25. "fmt"
  26. "io/ioutil"
  27. "net"
  28. "strings"
  29. "github.com/flashmob/go-guerrilla/tests/testcert"
  30. )
  31. type TestConfig struct {
  32. guerrilla.AppConfig
  33. BackendName string `json:"backend_name"`
  34. BackendConfig map[string]interface{} `json:"backend_config"`
  35. }
  36. var (
  37. // hold the output of logs
  38. logBuffer bytes.Buffer
  39. // logs redirected to this writer
  40. logOut *bufio.Writer
  41. // read the logs
  42. logIn *bufio.Reader
  43. // app config loaded here
  44. config *TestConfig
  45. app guerrilla.Guerrilla
  46. initErr error
  47. )
  48. func init() {
  49. logOut = bufio.NewWriter(&logBuffer)
  50. logIn = bufio.NewReader(&logBuffer)
  51. log.SetLevel(log.DebugLevel)
  52. log.SetOutput(logOut)
  53. config = &TestConfig{}
  54. if err := json.Unmarshal([]byte(configJson), config); err != nil {
  55. initErr = errors.New("Could not unmartial config," + err.Error())
  56. } else {
  57. setupCerts(config)
  58. backend, _ := getBackend("dummy", config.BackendConfig)
  59. app, _ = guerrilla.New(&config.AppConfig, backend)
  60. }
  61. }
  62. // a configuration file with a dummy backend
  63. var configJson = `
  64. {
  65. "pid_file" : "/var/run/go-guerrilla.pid",
  66. "allowed_hosts": ["spam4.me","grr.la"],
  67. "backend_name" : "dummy",
  68. "backend_config" :
  69. {
  70. "log_received_mails" : true
  71. },
  72. "servers" : [
  73. {
  74. "is_enabled" : true,
  75. "host_name":"mail.guerrillamail.com",
  76. "max_size": 100017,
  77. "private_key_file":"/vagrant/projects/htdocs/guerrilla/config/ssl/guerrillamail.com.key",
  78. "public_key_file":"/vagrant/projects/htdocs/guerrilla/config/ssl/guerrillamail.com.crt",
  79. "timeout":160,
  80. "listen_interface":"127.0.0.1:2526",
  81. "start_tls_on":true,
  82. "tls_always_on":false,
  83. "max_clients": 2,
  84. "log_file":"/dev/stdout"
  85. },
  86. {
  87. "is_enabled" : true,
  88. "host_name":"mail.guerrillamail.com",
  89. "max_size":1000001,
  90. "private_key_file":"/vagrant/projects/htdocs/guerrilla/config/ssl/guerrillamail.com.key",
  91. "public_key_file":"/vagrant/projects/htdocs/guerrilla/config/ssl/guerrillamail.com.crt",
  92. "timeout":180,
  93. "listen_interface":"127.0.0.1:4654",
  94. "start_tls_on":false,
  95. "tls_always_on":true,
  96. "max_clients":1,
  97. "log_file":"/dev/stdout"
  98. }
  99. ]
  100. }
  101. `
  102. func getBackend(backendName string, backendConfig map[string]interface{}) (backends.Backend, error) {
  103. return backends.New(backendName, backendConfig)
  104. }
  105. func setupCerts(c *TestConfig) {
  106. for i := range c.Servers {
  107. testcert.GenerateCert(c.Servers[i].Hostname, "", 365*24*time.Hour, false, 2048, "P256", "./")
  108. c.Servers[i].PrivateKeyFile = c.Servers[i].Hostname + ".key.pem"
  109. c.Servers[i].PublicKeyFile = c.Servers[i].Hostname + ".cert.pem"
  110. }
  111. }
  112. // Testing start and stop of server
  113. func TestStart(t *testing.T) {
  114. if initErr != nil {
  115. t.Error(initErr)
  116. t.FailNow()
  117. }
  118. if startErrors := app.Start(); startErrors != nil {
  119. t.Error(startErrors)
  120. t.FailNow()
  121. }
  122. time.Sleep(time.Second)
  123. app.Shutdown()
  124. logOut.Flush()
  125. if read, err := ioutil.ReadAll(logIn); err == nil {
  126. logOutput := string(read)
  127. if i := strings.Index(logOutput, "Listening on TCP 127.0.0.1:4654"); i < 0 {
  128. t.Error("Server did not listen on 127.0.0.1:4654")
  129. }
  130. if i := strings.Index(logOutput, "Listening on TCP 127.0.0.1:2526"); i < 0 {
  131. t.Error("Server did not listen on 127.0.0.1:2526")
  132. }
  133. if i := strings.Index(logOutput, "[127.0.0.1:4654] Waiting for a new client"); i < 0 {
  134. t.Error("Server did not wait on 127.0.0.1:4654")
  135. }
  136. if i := strings.Index(logOutput, "[127.0.0.1:2526] Waiting for a new client"); i < 0 {
  137. t.Error("Server did not wait on 127.0.0.1:2526")
  138. }
  139. if i := strings.Index(logOutput, "Server [127.0.0.1:4654] has stopped accepting new clients"); i < 0 {
  140. t.Error("Server did not stop on 127.0.0.1:4654")
  141. }
  142. if i := strings.Index(logOutput, "Server [127.0.0.1:2526] has stopped accepting new clients"); i < 0 {
  143. t.Error("Server did not stop on 127.0.0.1:2526")
  144. }
  145. if i := strings.Index(logOutput, "shutdown completed for [127.0.0.1:4654]"); i < 0 {
  146. t.Error("Server did not complete shutdown on 127.0.0.1:4654")
  147. }
  148. if i := strings.Index(logOutput, "shutdown completed for [127.0.0.1:2526]"); i < 0 {
  149. t.Error("Server did not complete shutdown on 127.0.0.1:2526")
  150. }
  151. if i := strings.Index(logOutput, "shutting down pool [127.0.0.1:4654]"); i < 0 {
  152. t.Error("Server did not shutdown pool on 127.0.0.1:4654")
  153. }
  154. if i := strings.Index(logOutput, "shutting down pool [127.0.0.1:2526]"); i < 0 {
  155. t.Error("Server did not shutdown pool on 127.0.0.1:2526")
  156. }
  157. if i := strings.Index(logOutput, "Backend shutdown completed"); i < 0 {
  158. t.Error("Backend didn't shut down")
  159. }
  160. }
  161. // don't forget to reset
  162. logBuffer.Reset()
  163. logIn.Reset(&logBuffer)
  164. }
  165. // Simple smoke-test to see if the server can listen & issues a greeting on connect
  166. func TestGreeting(t *testing.T) {
  167. //log.SetOutput(os.Stdout)
  168. if initErr != nil {
  169. t.Error(initErr)
  170. t.FailNow()
  171. }
  172. if startErrors := app.Start(); startErrors == nil {
  173. // 1. plaintext connection
  174. conn, err := net.Dial("tcp", config.Servers[0].ListenInterface)
  175. if err != nil {
  176. // handle error
  177. t.Error("Cannot dial server", config.Servers[0].ListenInterface)
  178. }
  179. conn.SetReadDeadline(time.Now().Add(time.Duration(time.Millisecond * 500)))
  180. greeting, err := bufio.NewReader(conn).ReadString('\n')
  181. //fmt.Println(greeting)
  182. if err != nil {
  183. t.Error(err)
  184. t.FailNow()
  185. } else {
  186. expected := "220 mail.guerrillamail.com SMTP Guerrilla"
  187. if strings.Index(greeting, expected) != 0 {
  188. t.Error("Server[1] did not have the expected greeting prefix", expected)
  189. }
  190. }
  191. conn.Close()
  192. // 2. tls connection
  193. // roots, err := x509.SystemCertPool()
  194. conn, err = tls.Dial("tcp", config.Servers[1].ListenInterface, &tls.Config{
  195. InsecureSkipVerify: true,
  196. ServerName: "127.0.0.1",
  197. })
  198. if err != nil {
  199. // handle error
  200. t.Error(err, "Cannot dial server (TLS)", config.Servers[1].ListenInterface)
  201. t.FailNow()
  202. }
  203. conn.SetReadDeadline(time.Now().Add(time.Duration(time.Millisecond * 500)))
  204. greeting, err = bufio.NewReader(conn).ReadString('\n')
  205. //fmt.Println(greeting)
  206. if err != nil {
  207. t.Error(err)
  208. t.FailNow()
  209. } else {
  210. expected := "220 mail.guerrillamail.com SMTP Guerrilla"
  211. if strings.Index(greeting, expected) != 0 {
  212. t.Error("Server[2] (TLS) did not have the expected greeting prefix", expected)
  213. }
  214. }
  215. conn.Close()
  216. } else {
  217. if startErrors := app.Start(); startErrors != nil {
  218. t.Error(startErrors)
  219. t.FailNow()
  220. }
  221. }
  222. app.Shutdown()
  223. logOut.Flush()
  224. if read, err := ioutil.ReadAll(logIn); err == nil {
  225. logOutput := string(read)
  226. //fmt.Println(logOutput)
  227. if i := strings.Index(logOutput, "Handle client [127.0.0.1:"); i < 0 {
  228. t.Error("Server did not handle any clients")
  229. }
  230. }
  231. // don't forget to reset
  232. logBuffer.Reset()
  233. logIn.Reset(&logBuffer)
  234. }
  235. // start up a server, connect a client, greet, then shutdown, then client sends a command
  236. // expecting: 421 Server is shutting down. Please try again later. Sayonara!
  237. // server should close connection after that
  238. func TestShutDown(t *testing.T) {
  239. if initErr != nil {
  240. t.Error(initErr)
  241. t.FailNow()
  242. }
  243. if startErrors := app.Start(); startErrors == nil {
  244. conn, bufin, err := Connect(config.Servers[0], 20)
  245. if err != nil {
  246. // handle error
  247. t.Error(err.Error(), config.Servers[0].ListenInterface)
  248. t.FailNow()
  249. } else {
  250. // client goes into command state
  251. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  252. t.Error("Hello command failed", err.Error())
  253. }
  254. // do a shutdown while the client is connected & in client state
  255. go app.Shutdown()
  256. time.Sleep(time.Millisecond * 150) // let server to Shutdown
  257. // issue a command while shutting down
  258. response, err := Command(conn, bufin, "HELP")
  259. if err != nil {
  260. t.Error("Help command failed", err.Error())
  261. }
  262. expected := "421 4.3.0 Server is shutting down. Please try again later. Sayonara!"
  263. if strings.Index(response, expected) != 0 {
  264. t.Error("Server did not shut down with", expected, ", it said:"+response)
  265. }
  266. time.Sleep(time.Millisecond * 250) // let server to close
  267. }
  268. conn.Close()
  269. } else {
  270. if startErrors := app.Start(); startErrors != nil {
  271. t.Error(startErrors)
  272. app.Shutdown()
  273. t.FailNow()
  274. }
  275. }
  276. // assuming server has shutdown by now
  277. logOut.Flush()
  278. if read, err := ioutil.ReadAll(logIn); err == nil {
  279. logOutput := string(read)
  280. // fmt.Println(logOutput)
  281. if i := strings.Index(logOutput, "Handle client [127.0.0.1:"); i < 0 {
  282. t.Error("Server did not handle any clients")
  283. }
  284. }
  285. // don't forget to reset
  286. logBuffer.Reset()
  287. logIn.Reset(&logBuffer)
  288. }
  289. // add more than 100 recipients, it should fail at 101
  290. func TestRFC2821LimitRecipients(t *testing.T) {
  291. if initErr != nil {
  292. t.Error(initErr)
  293. t.FailNow()
  294. }
  295. if startErrors := app.Start(); startErrors == nil {
  296. conn, bufin, err := Connect(config.Servers[0], 20)
  297. if err != nil {
  298. // handle error
  299. t.Error(err.Error(), config.Servers[0].ListenInterface)
  300. t.FailNow()
  301. } else {
  302. // client goes into command state
  303. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  304. t.Error("Hello command failed", err.Error())
  305. }
  306. for i := 0; i < 101; i++ {
  307. if _, err := Command(conn, bufin, fmt.Sprintf("RCPT TO:test%[email protected]", i)); err != nil {
  308. t.Error("RCPT TO", err.Error())
  309. break
  310. }
  311. }
  312. response, err := Command(conn, bufin, "RCPT TO:[email protected]")
  313. if err != nil {
  314. t.Error("rcpt command failed", err.Error())
  315. }
  316. expected := "452 4.5.3 Too many recipients"
  317. if strings.Index(response, expected) != 0 {
  318. t.Error("Server did not respond with", expected, ", it said:"+response)
  319. }
  320. }
  321. conn.Close()
  322. app.Shutdown()
  323. } else {
  324. if startErrors := app.Start(); startErrors != nil {
  325. t.Error(startErrors)
  326. app.Shutdown()
  327. t.FailNow()
  328. }
  329. }
  330. logOut.Flush()
  331. // don't forget to reset
  332. logBuffer.Reset()
  333. logIn.Reset(&logBuffer)
  334. }
  335. // RCPT TO & MAIL FROM with 64 chars in local part, it should fail at 65
  336. func TestRFC2832LimitLocalPart(t *testing.T) {
  337. if initErr != nil {
  338. t.Error(initErr)
  339. t.FailNow()
  340. }
  341. if startErrors := app.Start(); startErrors == nil {
  342. conn, bufin, err := Connect(config.Servers[0], 20)
  343. if err != nil {
  344. // handle error
  345. t.Error(err.Error(), config.Servers[0].ListenInterface)
  346. t.FailNow()
  347. } else {
  348. // client goes into command state
  349. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  350. t.Error("Hello command failed", err.Error())
  351. }
  352. // repeat > 64 characters in local part
  353. response, err := Command(conn, bufin, fmt.Sprintf("RCPT TO:%[email protected]", strings.Repeat("a", 65)))
  354. if err != nil {
  355. t.Error("rcpt command failed", err.Error())
  356. }
  357. expected := "550 5.5.4 Local part too long"
  358. if strings.Index(response, expected) != 0 {
  359. t.Error("Server did not respond with", expected, ", it said:"+response)
  360. }
  361. // what about if it's exactly 64?
  362. // repeat > 64 characters in local part
  363. response, err = Command(conn, bufin, fmt.Sprintf("RCPT TO:%[email protected]", strings.Repeat("a", 64)))
  364. if err != nil {
  365. t.Error("rcpt command failed", err.Error())
  366. }
  367. expected = "250 2.1.5 OK"
  368. if strings.Index(response, expected) != 0 {
  369. t.Error("Server did not respond with", expected, ", it said:"+response)
  370. }
  371. }
  372. conn.Close()
  373. app.Shutdown()
  374. } else {
  375. if startErrors := app.Start(); startErrors != nil {
  376. t.Error(startErrors)
  377. app.Shutdown()
  378. t.FailNow()
  379. }
  380. }
  381. logOut.Flush()
  382. // don't forget to reset
  383. logBuffer.Reset()
  384. logIn.Reset(&logBuffer)
  385. }
  386. //RFC2821LimitPath fail if path > 256 but different error if below
  387. func TestRFC2821LimitPath(t *testing.T) {
  388. if initErr != nil {
  389. t.Error(initErr)
  390. t.FailNow()
  391. }
  392. if startErrors := app.Start(); startErrors == nil {
  393. conn, bufin, err := Connect(config.Servers[0], 20)
  394. if err != nil {
  395. // handle error
  396. t.Error(err.Error(), config.Servers[0].ListenInterface)
  397. t.FailNow()
  398. } else {
  399. // client goes into command state
  400. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  401. t.Error("Hello command failed", err.Error())
  402. }
  403. // repeat > 256 characters in local part
  404. response, err := Command(conn, bufin, fmt.Sprintf("RCPT TO:%[email protected]", strings.Repeat("a", 257-7)))
  405. if err != nil {
  406. t.Error("rcpt command failed", err.Error())
  407. }
  408. expected := "550 5.5.4 Path too long"
  409. if strings.Index(response, expected) != 0 {
  410. t.Error("Server did not respond with", expected, ", it said:"+response)
  411. }
  412. // what about if it's exactly 256?
  413. response, err = Command(conn, bufin,
  414. fmt.Sprintf("RCPT TO:%s@%s.la", strings.Repeat("a", 64), strings.Repeat("b", 257-5-64)))
  415. if err != nil {
  416. t.Error("rcpt command failed", err.Error())
  417. }
  418. expected = "454 4.1.1 Error: Relay access denied"
  419. if strings.Index(response, expected) != 0 {
  420. t.Error("Server did not respond with", expected, ", it said:"+response)
  421. }
  422. }
  423. conn.Close()
  424. app.Shutdown()
  425. } else {
  426. if startErrors := app.Start(); startErrors != nil {
  427. t.Error(startErrors)
  428. app.Shutdown()
  429. t.FailNow()
  430. }
  431. }
  432. logOut.Flush()
  433. // don't forget to reset
  434. logBuffer.Reset()
  435. logIn.Reset(&logBuffer)
  436. }
  437. // RFC2821LimitDomain 501 Domain cannot exceed 255 characters
  438. func TestRFC2821LimitDomain(t *testing.T) {
  439. if initErr != nil {
  440. t.Error(initErr)
  441. t.FailNow()
  442. }
  443. if startErrors := app.Start(); startErrors == nil {
  444. conn, bufin, err := Connect(config.Servers[0], 20)
  445. if err != nil {
  446. // handle error
  447. t.Error(err.Error(), config.Servers[0].ListenInterface)
  448. t.FailNow()
  449. } else {
  450. // client goes into command state
  451. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  452. t.Error("Hello command failed", err.Error())
  453. }
  454. // repeat > 64 characters in local part
  455. response, err := Command(conn, bufin, fmt.Sprintf("RCPT TO:a@%s.l", strings.Repeat("a", 255-2)))
  456. if err != nil {
  457. t.Error("command failed", err.Error())
  458. }
  459. expected := "550 5.5.4 Path too long"
  460. if strings.Index(response, expected) != 0 {
  461. t.Error("Server did not respond with", expected, ", it said:"+response)
  462. }
  463. // what about if it's exactly 255?
  464. response, err = Command(conn, bufin,
  465. fmt.Sprintf("RCPT TO:a@%s.la", strings.Repeat("b", 255-4)))
  466. if err != nil {
  467. t.Error("command failed", err.Error())
  468. }
  469. expected = "454 4.1.1 Error: Relay access denied"
  470. if strings.Index(response, expected) != 0 {
  471. t.Error("Server did not respond with", expected, ", it said:"+response)
  472. }
  473. }
  474. conn.Close()
  475. app.Shutdown()
  476. } else {
  477. if startErrors := app.Start(); startErrors != nil {
  478. t.Error(startErrors)
  479. app.Shutdown()
  480. t.FailNow()
  481. }
  482. }
  483. logOut.Flush()
  484. // don't forget to reset
  485. logBuffer.Reset()
  486. logIn.Reset(&logBuffer)
  487. }
  488. // Test several different inputs to MAIL FROM command
  489. func TestMailFromCmd(t *testing.T) {
  490. if initErr != nil {
  491. t.Error(initErr)
  492. t.FailNow()
  493. }
  494. if startErrors := app.Start(); startErrors == nil {
  495. conn, bufin, err := Connect(config.Servers[0], 20)
  496. if err != nil {
  497. // handle error
  498. t.Error(err.Error(), config.Servers[0].ListenInterface)
  499. t.FailNow()
  500. } else {
  501. // client goes into command state
  502. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  503. t.Error("Hello command failed", err.Error())
  504. }
  505. // Basic valid address
  506. response, err := Command(conn, bufin, "MAIL FROM:[email protected]")
  507. if err != nil {
  508. t.Error("command failed", err.Error())
  509. }
  510. expected := "250 2.1.0 OK"
  511. if strings.Index(response, expected) != 0 {
  512. t.Error("Server did not respond with", expected, ", it said:"+response)
  513. }
  514. // Reset
  515. response, err = Command(conn, bufin, "RSET")
  516. if err != nil {
  517. t.Error("command failed", err.Error())
  518. }
  519. expected = "250 2.1.0 OK"
  520. if strings.Index(response, expected) != 0 {
  521. t.Error("Server did not respond with", expected, ", it said:"+response)
  522. }
  523. // Basic valid address (RfC)
  524. response, err = Command(conn, bufin, "MAIL FROM:<[email protected]>")
  525. if err != nil {
  526. t.Error("command failed", err.Error())
  527. }
  528. expected = "250 2.1.0 OK"
  529. if strings.Index(response, expected) != 0 {
  530. t.Error("Server did not respond with", expected, ", it said:"+response)
  531. }
  532. // Reset
  533. response, err = Command(conn, bufin, "RSET")
  534. if err != nil {
  535. t.Error("command failed", err.Error())
  536. }
  537. expected = "250 2.1.0 OK"
  538. if strings.Index(response, expected) != 0 {
  539. t.Error("Server did not respond with", expected, ", it said:"+response)
  540. }
  541. // Bounce
  542. response, err = Command(conn, bufin, "MAIL FROM:<>")
  543. if err != nil {
  544. t.Error("command failed", err.Error())
  545. }
  546. expected = "250 2.1.0 OK"
  547. if strings.Index(response, expected) != 0 {
  548. t.Error("Server did not respond with", expected, ", it said:"+response)
  549. }
  550. // Reset
  551. response, err = Command(conn, bufin, "RSET")
  552. if err != nil {
  553. t.Error("command failed", err.Error())
  554. }
  555. expected = "250 2.1.0 OK"
  556. if strings.Index(response, expected) != 0 {
  557. t.Error("Server did not respond with", expected, ", it said:"+response)
  558. }
  559. // No mail from content
  560. response, err = Command(conn, bufin, "MAIL FROM:")
  561. if err != nil {
  562. t.Error("command failed", err.Error())
  563. }
  564. expected = "501 5.5.4 Invalid address"
  565. if strings.Index(response, expected) != 0 {
  566. t.Error("Server did not respond with", expected, ", it said:"+response)
  567. }
  568. // Reset
  569. response, err = Command(conn, bufin, "RSET")
  570. if err != nil {
  571. t.Error("command failed", err.Error())
  572. }
  573. expected = "250 2.1.0 OK"
  574. if strings.Index(response, expected) != 0 {
  575. t.Error("Server did not respond with", expected, ", it said:"+response)
  576. }
  577. // Short mail from content
  578. response, err = Command(conn, bufin, "MAIL FROM:<")
  579. if err != nil {
  580. t.Error("command failed", err.Error())
  581. }
  582. expected = "501 5.5.4 Invalid address"
  583. if strings.Index(response, expected) != 0 {
  584. t.Error("Server did not respond with", expected, ", it said:"+response)
  585. }
  586. // Reset
  587. response, err = Command(conn, bufin, "RSET")
  588. if err != nil {
  589. t.Error("command failed", err.Error())
  590. }
  591. expected = "250 2.1.0 OK"
  592. if strings.Index(response, expected) != 0 {
  593. t.Error("Server did not respond with", expected, ", it said:"+response)
  594. }
  595. // Short mail from content 2
  596. response, err = Command(conn, bufin, "MAIL FROM:x")
  597. if err != nil {
  598. t.Error("command failed", err.Error())
  599. }
  600. expected = "501 5.5.4 Invalid address"
  601. if strings.Index(response, expected) != 0 {
  602. t.Error("Server did not respond with", expected, ", it said:"+response)
  603. }
  604. // Reset
  605. response, err = Command(conn, bufin, "RSET")
  606. if err != nil {
  607. t.Error("command failed", err.Error())
  608. }
  609. expected = "250 2.1.0 OK"
  610. if strings.Index(response, expected) != 0 {
  611. t.Error("Server did not respond with", expected, ", it said:"+response)
  612. }
  613. // What?
  614. response, err = Command(conn, bufin, "MAIL FROM:<<>>")
  615. if err != nil {
  616. t.Error("command failed", err.Error())
  617. }
  618. expected = "501 5.5.4 Invalid address"
  619. if strings.Index(response, expected) != 0 {
  620. t.Error("Server did not respond with", expected, ", it said:"+response)
  621. }
  622. // Reset
  623. response, err = Command(conn, bufin, "RSET")
  624. if err != nil {
  625. t.Error("command failed", err.Error())
  626. }
  627. expected = "250 2.1.0 OK"
  628. if strings.Index(response, expected) != 0 {
  629. t.Error("Server did not respond with", expected, ", it said:"+response)
  630. }
  631. // Invalid address?
  632. response, err = Command(conn, bufin, "MAIL FROM:<justatest>")
  633. if err != nil {
  634. t.Error("command failed", err.Error())
  635. }
  636. expected = "501 5.5.4 Invalid address"
  637. if strings.Index(response, expected) != 0 {
  638. t.Error("Server did not respond with", expected, ", it said:"+response)
  639. }
  640. // Reset
  641. response, err = Command(conn, bufin, "RSET")
  642. if err != nil {
  643. t.Error("command failed", err.Error())
  644. }
  645. expected = "250 2.1.0 OK"
  646. if strings.Index(response, expected) != 0 {
  647. t.Error("Server did not respond with", expected, ", it said:"+response)
  648. }
  649. // SMTPUTF8 not implemented for now, currently still accepted
  650. response, err = Command(conn, bufin, "MAIL FROM:<anö[email protected]>")
  651. if err != nil {
  652. t.Error("command failed", err.Error())
  653. }
  654. expected = "250 2.1.0 OK"
  655. if strings.Index(response, expected) != 0 {
  656. t.Error("Server did not respond with", expected, ", it said:"+response)
  657. }
  658. // Reset
  659. response, err = Command(conn, bufin, "RSET")
  660. if err != nil {
  661. t.Error("command failed", err.Error())
  662. }
  663. expected = "250 2.1.0 OK"
  664. if strings.Index(response, expected) != 0 {
  665. t.Error("Server did not respond with", expected, ", it said:"+response)
  666. }
  667. // 8BITMIME (RfC 6152)
  668. response, err = Command(conn, bufin, "MAIL FROM:<[email protected]> BODY=8BITMIME")
  669. if err != nil {
  670. t.Error("command failed", err.Error())
  671. }
  672. expected = "250 2.1.0 OK"
  673. if strings.Index(response, expected) != 0 {
  674. t.Error("Server did not respond with", expected, ", it said:"+response)
  675. }
  676. // Reset
  677. response, err = Command(conn, bufin, "RSET")
  678. if err != nil {
  679. t.Error("command failed", err.Error())
  680. }
  681. expected = "250 2.1.0 OK"
  682. if strings.Index(response, expected) != 0 {
  683. t.Error("Server did not respond with", expected, ", it said:"+response)
  684. }
  685. // 8BITMIME (RfC 6152) Bounce
  686. response, err = Command(conn, bufin, "MAIL FROM:<> BODY=8BITMIME")
  687. if err != nil {
  688. t.Error("command failed", err.Error())
  689. }
  690. expected = "250 2.1.0 OK"
  691. if strings.Index(response, expected) != 0 {
  692. t.Error("Server did not respond with", expected, ", it said:"+response)
  693. }
  694. // Reset
  695. response, err = Command(conn, bufin, "RSET")
  696. if err != nil {
  697. t.Error("command failed", err.Error())
  698. }
  699. expected = "250 2.1.0 OK"
  700. if strings.Index(response, expected) != 0 {
  701. t.Error("Server did not respond with", expected, ", it said:"+response)
  702. }
  703. }
  704. conn.Close()
  705. app.Shutdown()
  706. } else {
  707. if startErrors := app.Start(); startErrors != nil {
  708. t.Error(startErrors)
  709. app.Shutdown()
  710. t.FailNow()
  711. }
  712. }
  713. logOut.Flush()
  714. // don't forget to reset
  715. logBuffer.Reset()
  716. logIn.Reset(&logBuffer)
  717. }
  718. // Test several different inputs to MAIL FROM command
  719. func TestHeloEhlo(t *testing.T) {
  720. if initErr != nil {
  721. t.Error(initErr)
  722. t.FailNow()
  723. }
  724. if startErrors := app.Start(); startErrors == nil {
  725. conn, bufin, err := Connect(config.Servers[0], 20)
  726. hostname := config.Servers[0].Hostname
  727. if err != nil {
  728. // handle error
  729. t.Error(err.Error(), config.Servers[0].ListenInterface)
  730. t.FailNow()
  731. } else {
  732. // Test HELO
  733. response, err := Command(conn, bufin, "HELO localtester")
  734. if err != nil {
  735. t.Error("command failed", err.Error())
  736. }
  737. expected := fmt.Sprintf("250 %s Hello", hostname)
  738. if strings.Index(response, expected) != 0 {
  739. t.Error("Server did not respond with", expected, ", it said:"+response)
  740. }
  741. // Reset
  742. response, err = Command(conn, bufin, "RSET")
  743. if err != nil {
  744. t.Error("command failed", err.Error())
  745. }
  746. expected = "250 2.1.0 OK"
  747. if strings.Index(response, expected) != 0 {
  748. t.Error("Server did not respond with", expected, ", it said:"+response)
  749. }
  750. // Test EHLO
  751. // This is tricky as it is a multiline response
  752. var fullresp string
  753. response, err = Command(conn, bufin, "EHLO localtester")
  754. fullresp = fullresp + response
  755. if err != nil {
  756. t.Error("command failed", err.Error())
  757. }
  758. for err == nil {
  759. response, err = bufin.ReadString('\n')
  760. fullresp = fullresp + response
  761. if strings.HasPrefix(response, "250 ") { // Last response has a whitespace and no "-"
  762. break // bail
  763. }
  764. }
  765. expected = fmt.Sprintf("250-%s Hello\r\n250-SIZE 100017\r\n250-PIPELINING\r\n250-STARTTLS\r\n250-ENHANCEDSTATUSCODES\r\n250 HELP\r\n", hostname)
  766. if fullresp != expected {
  767. t.Error("Server did not respond with [" + expected + "], it said [" + fullresp + "]")
  768. }
  769. // be kind, QUIT. And we are sure that bufin does not contain fragments from the EHLO command.
  770. response, err = Command(conn, bufin, "QUIT")
  771. if err != nil {
  772. t.Error("command failed", err.Error())
  773. }
  774. expected = "221 2.0.0 Bye"
  775. if strings.Index(response, expected) != 0 {
  776. t.Error("Server did not respond with", expected, ", it said:"+response)
  777. }
  778. }
  779. conn.Close()
  780. app.Shutdown()
  781. } else {
  782. if startErrors := app.Start(); startErrors != nil {
  783. t.Error(startErrors)
  784. app.Shutdown()
  785. t.FailNow()
  786. }
  787. }
  788. logOut.Flush()
  789. // don't forget to reset
  790. logBuffer.Reset()
  791. logIn.Reset(&logBuffer)
  792. }
  793. // It should error when MAIL FROM was given twice
  794. func TestNestedMailCmd(t *testing.T) {
  795. if initErr != nil {
  796. t.Error(initErr)
  797. t.FailNow()
  798. }
  799. if startErrors := app.Start(); startErrors == nil {
  800. conn, bufin, err := Connect(config.Servers[0], 20)
  801. if err != nil {
  802. // handle error
  803. t.Error(err.Error(), config.Servers[0].ListenInterface)
  804. t.FailNow()
  805. } else {
  806. // client goes into command state
  807. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  808. t.Error("Hello command failed", err.Error())
  809. }
  810. // repeat > 64 characters in local part
  811. response, err := Command(conn, bufin, "MAIL FROM:[email protected]")
  812. if err != nil {
  813. t.Error("command failed", err.Error())
  814. }
  815. response, err = Command(conn, bufin, "MAIL FROM:[email protected]")
  816. if err != nil {
  817. t.Error("command failed", err.Error())
  818. }
  819. expected := "503 5.5.1 Error: nested MAIL command"
  820. if strings.Index(response, expected) != 0 {
  821. t.Error("Server did not respond with", expected, ", it said:"+response)
  822. }
  823. // Plot twist: if you EHLO , it should allow MAIL FROM again
  824. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  825. t.Error("Hello command failed", err.Error())
  826. }
  827. response, err = Command(conn, bufin, "MAIL FROM:[email protected]")
  828. if err != nil {
  829. t.Error("command failed", err.Error())
  830. }
  831. expected = "250 2.1.0 OK"
  832. if strings.Index(response, expected) != 0 {
  833. t.Error("Server did not respond with", expected, ", it said:"+response)
  834. }
  835. // Plot twist: if you RSET , it should allow MAIL FROM again
  836. response, err = Command(conn, bufin, "RSET")
  837. if err != nil {
  838. t.Error("command failed", err.Error())
  839. }
  840. expected = "250 2.1.0 OK"
  841. if strings.Index(response, expected) != 0 {
  842. t.Error("Server did not respond with", expected, ", it said:"+response)
  843. }
  844. response, err = Command(conn, bufin, "MAIL FROM:[email protected]")
  845. if err != nil {
  846. t.Error("command failed", err.Error())
  847. }
  848. expected = "250 2.1.0 OK"
  849. if strings.Index(response, expected) != 0 {
  850. t.Error("Server did not respond with", expected, ", it said:"+response)
  851. }
  852. }
  853. conn.Close()
  854. app.Shutdown()
  855. } else {
  856. if startErrors := app.Start(); startErrors != nil {
  857. t.Error(startErrors)
  858. app.Shutdown()
  859. t.FailNow()
  860. }
  861. }
  862. logOut.Flush()
  863. // don't forget to reset
  864. logBuffer.Reset()
  865. logIn.Reset(&logBuffer)
  866. }
  867. // It should error on a very long command line, exceeding CommandLineMaxLength 1024
  868. func TestCommandLineMaxLength(t *testing.T) {
  869. if initErr != nil {
  870. t.Error(initErr)
  871. t.FailNow()
  872. }
  873. if startErrors := app.Start(); startErrors == nil {
  874. conn, bufin, err := Connect(config.Servers[0], 20)
  875. if err != nil {
  876. // handle error
  877. t.Error(err.Error(), config.Servers[0].ListenInterface)
  878. t.FailNow()
  879. } else {
  880. // client goes into command state
  881. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  882. t.Error("Hello command failed", err.Error())
  883. }
  884. // repeat > 1024 characters
  885. response, err := Command(conn, bufin, strings.Repeat("s", guerrilla.CommandLineMaxLength+1))
  886. if err != nil {
  887. t.Error("command failed", err.Error())
  888. }
  889. expected := "554 5.5.1 Line too long"
  890. if strings.Index(response, expected) != 0 {
  891. t.Error("Server did not respond with", expected, ", it said:"+response)
  892. }
  893. }
  894. conn.Close()
  895. app.Shutdown()
  896. } else {
  897. if startErrors := app.Start(); startErrors != nil {
  898. t.Error(startErrors)
  899. app.Shutdown()
  900. t.FailNow()
  901. }
  902. }
  903. logOut.Flush()
  904. // don't forget to reset
  905. logBuffer.Reset()
  906. logIn.Reset(&logBuffer)
  907. }
  908. // It should error on a very long message, exceeding servers config value
  909. func TestDataMaxLength(t *testing.T) {
  910. if initErr != nil {
  911. t.Error(initErr)
  912. t.FailNow()
  913. }
  914. if startErrors := app.Start(); startErrors == nil {
  915. conn, bufin, err := Connect(config.Servers[0], 20)
  916. if err != nil {
  917. // handle error
  918. t.Error(err.Error(), config.Servers[0].ListenInterface)
  919. t.FailNow()
  920. } else {
  921. // client goes into command state
  922. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  923. t.Error("Hello command failed", err.Error())
  924. }
  925. response, err := Command(conn, bufin, "MAIL FROM:[email protected]")
  926. if err != nil {
  927. t.Error("command failed", err.Error())
  928. }
  929. //fmt.Println(response)
  930. response, err = Command(conn, bufin, "RCPT TO:[email protected]")
  931. if err != nil {
  932. t.Error("command failed", err.Error())
  933. }
  934. //fmt.Println(response)
  935. response, err = Command(conn, bufin, "DATA")
  936. if err != nil {
  937. t.Error("command failed", err.Error())
  938. }
  939. response, err = Command(
  940. conn,
  941. bufin,
  942. fmt.Sprintf("Subject:test\r\n\r\nHello %s\r\n.\r\n",
  943. strings.Repeat("n", int(config.Servers[0].MaxSize-20))))
  944. //expected := "500 Line too long"
  945. expected := "451 4.3.0 Error: Maximum DATA size exceeded"
  946. if strings.Index(response, expected) != 0 {
  947. t.Error("Server did not respond with", expected, ", it said:"+response, err)
  948. }
  949. }
  950. conn.Close()
  951. app.Shutdown()
  952. } else {
  953. if startErrors := app.Start(); startErrors != nil {
  954. t.Error(startErrors)
  955. app.Shutdown()
  956. t.FailNow()
  957. }
  958. }
  959. logOut.Flush()
  960. // don't forget to reset
  961. logBuffer.Reset()
  962. logIn.Reset(&logBuffer)
  963. }
  964. func TestDataCommand(t *testing.T) {
  965. if initErr != nil {
  966. t.Error(initErr)
  967. t.FailNow()
  968. }
  969. testHeader :=
  970. "Subject: =?Shift_JIS?B?W4NYg06DRYNGg0GBRYNHg2qDYoNOg1ggg0GDSoNFg5ODZ12DQYNKg0WDk4Nn?=\r\n" +
  971. "\t=?Shift_JIS?B?k2+YXoqul7mCzIKokm2C54K5?=\r\n"
  972. email :=
  973. "Delivered-To: [email protected]\r\n" +
  974. "\tReceived: from mail.guerrillamail.com (mail.guerrillamail.com [104.218.55.28:44246])\r\n" +
  975. "\tby grr.la with SMTP id [email protected];\r\n" +
  976. "\tWed, 18 Jan 2017 15:43:29 +0000\r\n" +
  977. "Received: by 192.99.19.220 with HTTP; Wed, 18 Jan 2017 15:43:29 +0000\r\n" +
  978. "MIME-Version: 1.0\r\n" +
  979. "Message-ID: <[email protected]>\r\n" +
  980. "Date: Wed, 18 Jan 2017 15:43:29 +0000\r\n" +
  981. "To: \"[email protected]\" <[email protected]>\r\n" +
  982. "From: <[email protected]>\r\n" +
  983. "Subject: test\r\n" +
  984. "X-Originating-IP: [60.241.160.150]\r\n" +
  985. "Content-Type: text/plain; charset=\"utf-8\"\r\n" +
  986. "Content-Transfer-Encoding: quoted-printable\r\n" +
  987. "X-Domain-Signer: PHP mailDomainSigner 0.2-20110415 <http://code.google.com/p/php-mail-domain-signer/>\r\n" +
  988. "DKIM-Signature: v=1; a=rsa-sha256; s=highgrade; d=guerrillamail.com; l=182;\r\n" +
  989. "\tt=1484754209; c=relaxed/relaxed; h=to:from:subject;\r\n" +
  990. "\tbh=GHSgjHpBp5QjNn9tzfug681+RcWMOUgpwAuTzppM5wY=;\r\n" +
  991. "\tb=R7FxWgACnT+pKXqEg15qgzH4ywMFRx5pDlIFCnSt1BfwmLvZPZK7oOLrbiRoGGR2OJnSfyCxeASH\r\n" +
  992. "\t019LNeLB/B8o+fMRX87m/tBpqIZ2vgXdT9rUCIbSDJnYoCHXakGcF+zGtTE3SEksMbeJQ76aGj6M\r\n" +
  993. "\tG80p76IT2Xu3iDJLYYWxcAeX+7z4M/bbYNeqxMQcXYZp1wNYlSlHahL6RDUYdcqikDqKoXmzMNVd\r\n" +
  994. "\tDr0EbH9iiu1DQtfUDzVE5LLus1yn36WU/2KJvEak45gJvm9s9J+Xrcb882CaYkxlAbgQDz1KeQLf\r\n" +
  995. "\teUyNspyAabkh2yTg7kOvNZSOJtbMSQS6/GMxsg==\r\n" +
  996. "\r\n" +
  997. "test=0A.mooo=0A..mooo=0Atest=0A.=0A=0A=0A=0A=0A=0A----=0ASent using Guerril=\r\n" +
  998. "lamail.com=0ABlock or report abuse: https://www.guerrillamail.com//abuse/?a=\r\n" +
  999. "=3DVURnES0HUaZbhA8%3D=0A\r\n.\r\n"
  1000. if startErrors := app.Start(); startErrors == nil {
  1001. conn, bufin, err := Connect(config.Servers[0], 20)
  1002. if err != nil {
  1003. // handle error
  1004. t.Error(err.Error(), config.Servers[0].ListenInterface)
  1005. t.FailNow()
  1006. } else {
  1007. // client goes into command state
  1008. if _, err := Command(conn, bufin, "HELO localtester"); err != nil {
  1009. t.Error("Hello command failed", err.Error())
  1010. }
  1011. response, err := Command(conn, bufin, "MAIL FROM:[email protected]")
  1012. if err != nil {
  1013. t.Error("command failed", err.Error())
  1014. }
  1015. //fmt.Println(response)
  1016. response, err = Command(conn, bufin, "RCPT TO:[email protected]")
  1017. if err != nil {
  1018. t.Error("command failed", err.Error())
  1019. }
  1020. //fmt.Println(response)
  1021. response, err = Command(conn, bufin, "DATA")
  1022. if err != nil {
  1023. t.Error("command failed", err.Error())
  1024. }
  1025. /*
  1026. response, err = Command(
  1027. conn,
  1028. bufin,
  1029. testHeader+"\r\nHello World\r\n.\r\n")
  1030. */
  1031. _ = testHeader
  1032. response, err = Command(
  1033. conn,
  1034. bufin,
  1035. email+"\r\n.\r\n")
  1036. //expected := "500 Line too long"
  1037. expected := "250 2.0.0 OK : queued as s0m3l337Ha5hva1u3LOL"
  1038. if strings.Index(response, expected) != 0 {
  1039. t.Error("Server did not respond with", expected, ", it said:"+response, err)
  1040. }
  1041. }
  1042. conn.Close()
  1043. app.Shutdown()
  1044. } else {
  1045. if startErrors := app.Start(); startErrors != nil {
  1046. t.Error(startErrors)
  1047. app.Shutdown()
  1048. t.FailNow()
  1049. }
  1050. }
  1051. logOut.Flush()
  1052. // don't forget to reset
  1053. logBuffer.Reset()
  1054. logIn.Reset(&logBuffer)
  1055. }