api_test.go 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599
  1. package guerrilla
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "net"
  8. "os"
  9. "strings"
  10. "testing"
  11. "time"
  12. "github.com/flashmob/go-guerrilla/backends"
  13. _ "github.com/flashmob/go-guerrilla/chunk"
  14. "github.com/flashmob/go-guerrilla/log"
  15. "github.com/flashmob/go-guerrilla/mail"
  16. "github.com/flashmob/go-guerrilla/response"
  17. )
  18. // Test Starting smtp without setting up logger / backend
  19. func TestSMTP(t *testing.T) {
  20. done := make(chan bool)
  21. go func() {
  22. select {
  23. case <-time.After(time.Second * 40):
  24. t.Error("timeout")
  25. return
  26. case <-done:
  27. return
  28. }
  29. }()
  30. d := Daemon{}
  31. err := d.Start()
  32. if err != nil {
  33. t.Error(err)
  34. }
  35. // it should set to stderr automatically
  36. if d.Config.LogFile != log.OutputStderr.String() {
  37. t.Error("smtp.config.LogFile is not", log.OutputStderr.String())
  38. }
  39. if len(d.Config.AllowedHosts) == 0 {
  40. t.Error("smtp.config.AllowedHosts len should be 1, not 0", d.Config.AllowedHosts)
  41. }
  42. if d.Config.LogLevel != "debug" {
  43. t.Error("smtp.config.LogLevel expected'debug', it is", d.Config.LogLevel)
  44. }
  45. if len(d.Config.Servers) != 1 {
  46. t.Error("len(smtp.config.Servers) should be 1, got", len(d.Config.Servers))
  47. }
  48. time.Sleep(time.Second * 2)
  49. d.Shutdown()
  50. done <- true
  51. }
  52. // Suppressing log output
  53. func TestSMTPNoLog(t *testing.T) {
  54. // configure a default server with no log output
  55. cfg := &AppConfig{LogFile: log.OutputOff.String()}
  56. d := Daemon{Config: cfg}
  57. err := d.Start()
  58. if err != nil {
  59. t.Error(err)
  60. }
  61. time.Sleep(time.Second * 2)
  62. d.Shutdown()
  63. }
  64. // our custom server
  65. func TestSMTPCustomServer(t *testing.T) {
  66. cfg := &AppConfig{LogFile: log.OutputOff.String()}
  67. sc := ServerConfig{
  68. ListenInterface: "127.0.0.1:2526",
  69. IsEnabled: true,
  70. }
  71. cfg.Servers = append(cfg.Servers, sc)
  72. d := Daemon{Config: cfg}
  73. err := d.Start()
  74. if err != nil {
  75. t.Error("start error", err)
  76. } else {
  77. time.Sleep(time.Second * 2)
  78. d.Shutdown()
  79. }
  80. }
  81. // with a backend config
  82. func TestSMTPCustomBackend(t *testing.T) {
  83. cfg := &AppConfig{LogFile: log.OutputOff.String()}
  84. sc := ServerConfig{
  85. ListenInterface: "127.0.0.1:2526",
  86. IsEnabled: true,
  87. }
  88. cfg.Servers = append(cfg.Servers, sc)
  89. bcfg := backends.BackendConfig{
  90. backends.ConfigProcessors: {
  91. "debugger": {
  92. "log_received_mails": true,
  93. },
  94. "header": {
  95. "primary_mail_host": "example.com",
  96. },
  97. },
  98. backends.ConfigGateways: {
  99. "default": {
  100. "save_workers_size": 3,
  101. "save_process": "HeadersParser|Header|Hasher|Debugger",
  102. },
  103. },
  104. }
  105. cfg.BackendConfig = bcfg
  106. d := Daemon{Config: cfg}
  107. err := d.Start()
  108. if err != nil {
  109. t.Error("start error", err)
  110. } else {
  111. time.Sleep(time.Second * 2)
  112. d.Shutdown()
  113. }
  114. }
  115. // with a config from a json file
  116. func TestSMTPLoadFile(t *testing.T) {
  117. json := `{
  118. "log_file" : "./tests/testlog",
  119. "log_level" : "debug",
  120. "pid_file" : "tests/go-guerrilla.pid",
  121. "allowed_hosts": ["spam4.me","grr.la"],
  122. "backend" : {
  123. "processors" : {
  124. "debugger" : {
  125. "log_received_mails" : true
  126. }
  127. },
  128. "gateways" : {
  129. "default" : {
  130. "save_workers_size" : 3,
  131. "save_process": "HeadersParser|Header|Hasher|Debugger"
  132. }
  133. }
  134. },
  135. "servers" : [
  136. {
  137. "is_enabled" : true,
  138. "host_name":"mail.guerrillamail.com",
  139. "max_size": 100017,
  140. "timeout":160,
  141. "listen_interface":"127.0.0.1:2526",
  142. "max_clients": 2,
  143. "tls" : {
  144. "private_key_file":"config_test.go",
  145. "public_key_file":"config_test.go",
  146. "start_tls_on":false,
  147. "tls_always_on":false
  148. }
  149. }
  150. ]
  151. }
  152. `
  153. json2 := `{
  154. "log_file" : "./tests/testlog2",
  155. "log_level" : "debug",
  156. "pid_file" : "tests/go-guerrilla2.pid",
  157. "allowed_hosts": ["spam4.me","grr.la"],
  158. "backend" : {
  159. "processors" : {
  160. "debugger" : {
  161. "log_received_mails" : true
  162. }
  163. },
  164. "gateways" : {
  165. "default" : {
  166. "save_workers_size" : 3,
  167. "save_process": "HeadersParser|Header|Hasher|Debugger"
  168. }
  169. }
  170. },
  171. "servers" : [
  172. {
  173. "is_enabled" : true,
  174. "host_name":"mail.guerrillamail.com",
  175. "max_size": 100017,
  176. "timeout":160,
  177. "listen_interface":"127.0.0.1:2526",
  178. "max_clients": 2,
  179. "tls" : {
  180. "private_key_file":"config_test.go",
  181. "public_key_file":"config_test.go",
  182. "start_tls_on":false,
  183. "tls_always_on":false
  184. }
  185. }
  186. ]
  187. }
  188. `
  189. err := ioutil.WriteFile("goguerrilla.conf.api", []byte(json), 0644)
  190. if err != nil {
  191. t.Error("could not write guerrilla.conf.api", err)
  192. return
  193. }
  194. d := Daemon{}
  195. _, err = d.LoadConfig("goguerrilla.conf.api")
  196. if err != nil {
  197. t.Error("ReadConfig error", err)
  198. return
  199. }
  200. err = d.Start()
  201. if err != nil {
  202. t.Error("start error", err)
  203. return
  204. } else {
  205. time.Sleep(time.Second * 2)
  206. if d.Config.LogFile != "./tests/testlog" {
  207. t.Error("d.Config.LogFile != \"./tests/testlog\"")
  208. }
  209. if d.Config.PidFile != "tests/go-guerrilla.pid" {
  210. t.Error("d.Config.LogFile != tests/go-guerrilla.pid")
  211. }
  212. err := ioutil.WriteFile("goguerrilla.conf.api", []byte(json2), 0644)
  213. if err != nil {
  214. t.Error("could not write guerrilla.conf.api", err)
  215. return
  216. }
  217. if err = d.ReloadConfigFile("goguerrilla.conf.api"); err != nil {
  218. t.Error(err)
  219. }
  220. if d.Config.LogFile != "./tests/testlog2" {
  221. t.Error("d.Config.LogFile != \"./tests/testlog\"")
  222. }
  223. if d.Config.PidFile != "tests/go-guerrilla2.pid" {
  224. t.Error("d.Config.LogFile != \"go-guerrilla.pid\"")
  225. }
  226. d.Shutdown()
  227. }
  228. }
  229. // test re-opening the main log
  230. func TestReopenLog(t *testing.T) {
  231. if err := os.Truncate("tests/testlog", 0); err != nil {
  232. t.Error(err)
  233. }
  234. cfg := &AppConfig{LogFile: "tests/testlog"}
  235. sc := ServerConfig{
  236. ListenInterface: "127.0.0.1:2526",
  237. IsEnabled: true,
  238. }
  239. cfg.Servers = append(cfg.Servers, sc)
  240. d := Daemon{Config: cfg}
  241. err := d.Start()
  242. if err != nil {
  243. t.Error("start error", err)
  244. } else {
  245. if err = d.ReopenLogs(); err != nil {
  246. t.Error(err)
  247. }
  248. time.Sleep(time.Second * 2)
  249. d.Shutdown()
  250. }
  251. b, err := ioutil.ReadFile("tests/testlog")
  252. if err != nil {
  253. t.Error("could not read logfile")
  254. return
  255. }
  256. if !strings.Contains(string(b), "re-opened log file") {
  257. t.Error("Server log did not re-opened, expecting \"re-opened log file\"")
  258. }
  259. if !strings.Contains(string(b), "re-opened main log file") {
  260. t.Error("Main log did not re-opened, expecting \"re-opened main log file\"")
  261. }
  262. }
  263. const testServerLog = "tests/testlog-server.log"
  264. // test re-opening the individual server log
  265. func TestReopenServerLog(t *testing.T) {
  266. if err := os.Truncate("tests/testlog", 0); err != nil {
  267. t.Error(err)
  268. }
  269. defer func() {
  270. if _, err := os.Stat(testServerLog); err == nil {
  271. if err = os.Remove(testServerLog); err != nil {
  272. t.Error(err)
  273. }
  274. }
  275. }()
  276. cfg := &AppConfig{LogFile: "tests/testlog", LogLevel: log.DebugLevel.String(), AllowedHosts: []string{"grr.la"}}
  277. sc := ServerConfig{
  278. ListenInterface: "127.0.0.1:2526",
  279. IsEnabled: true,
  280. LogFile: testServerLog,
  281. }
  282. cfg.Servers = append(cfg.Servers, sc)
  283. d := Daemon{Config: cfg}
  284. err := d.Start()
  285. if err != nil {
  286. t.Error("start error", err)
  287. } else {
  288. if err := talkToServer("127.0.0.1:2526", ""); err != nil {
  289. t.Error(err)
  290. }
  291. if err = d.ReopenLogs(); err != nil {
  292. t.Error(err)
  293. }
  294. time.Sleep(time.Second * 2)
  295. if err := talkToServer("127.0.0.1:2526", ""); err != nil {
  296. t.Error(err)
  297. }
  298. d.Shutdown()
  299. }
  300. b, err := ioutil.ReadFile("tests/testlog")
  301. if err != nil {
  302. t.Error("could not read logfile")
  303. return
  304. }
  305. if !strings.Contains(string(b), "re-opened log file") {
  306. t.Error("Server log did not re-opened, expecting \"re-opened log file\"")
  307. }
  308. if !strings.Contains(string(b), "re-opened main log file") {
  309. t.Error("Main log did not re-opened, expecting \"re-opened main log file\"")
  310. }
  311. b, err = ioutil.ReadFile(testServerLog)
  312. if err != nil {
  313. t.Error("could not read logfile")
  314. return
  315. }
  316. if !strings.Contains(string(b), "handle client") {
  317. t.Error("server log does not contain \"handle client\"")
  318. }
  319. }
  320. func TestSetConfig(t *testing.T) {
  321. if err := os.Truncate("tests/testlog", 0); err != nil {
  322. t.Error(err)
  323. }
  324. cfg := AppConfig{LogFile: "tests/testlog"}
  325. sc := ServerConfig{
  326. ListenInterface: "127.0.0.1:2526",
  327. IsEnabled: true,
  328. }
  329. cfg.Servers = append(cfg.Servers, sc)
  330. d := Daemon{Config: &cfg}
  331. // lets add a new server
  332. sc.ListenInterface = "127.0.0.1:2527"
  333. cfg.Servers = append(cfg.Servers, sc)
  334. err := d.SetConfig(cfg)
  335. if err != nil {
  336. t.Error("SetConfig returned an error:", err)
  337. return
  338. }
  339. err = d.Start()
  340. if err != nil {
  341. t.Error("start error", err)
  342. } else {
  343. time.Sleep(time.Second * 2)
  344. d.Shutdown()
  345. }
  346. b, err := ioutil.ReadFile("tests/testlog")
  347. if err != nil {
  348. t.Error("could not read logfile")
  349. return
  350. }
  351. //fmt.Println(string(b))
  352. // has 127.0.0.1:2527 started?
  353. if !strings.Contains(string(b), "127.0.0.1:2527") {
  354. t.Error("expecting 127.0.0.1:2527 to start")
  355. }
  356. }
  357. func TestSetConfigError(t *testing.T) {
  358. if err := os.Truncate("tests/testlog", 0); err != nil {
  359. t.Error(err)
  360. }
  361. cfg := AppConfig{LogFile: "tests/testlog"}
  362. sc := ServerConfig{
  363. ListenInterface: "127.0.0.1:2526",
  364. IsEnabled: true,
  365. }
  366. cfg.Servers = append(cfg.Servers, sc)
  367. d := Daemon{Config: &cfg}
  368. // lets add a new server with bad TLS
  369. sc.ListenInterface = "127.0.0.1:2527"
  370. sc.TLS.StartTLSOn = true
  371. sc.TLS.PublicKeyFile = "tests/testlog" // totally wrong :->
  372. sc.TLS.PrivateKeyFile = "tests/testlog" // totally wrong :->
  373. cfg.Servers = append(cfg.Servers, sc)
  374. err := d.SetConfig(cfg)
  375. if err == nil {
  376. t.Error("SetConfig should have returned an error complaining about bad tls settings")
  377. return
  378. }
  379. }
  380. var funkyLogger = func() backends.Decorator {
  381. backends.Svc.AddInitializer(
  382. backends.InitializeWith(
  383. func(backendConfig backends.BackendConfig) error {
  384. backends.Log().Info("Funky logger is up & down to funk!")
  385. return nil
  386. }),
  387. )
  388. backends.Svc.AddShutdowner(
  389. backends.ShutdownWith(
  390. func() error {
  391. backends.Log().Info("The funk has been stopped!")
  392. return nil
  393. }),
  394. )
  395. return func(p backends.Processor) backends.Processor {
  396. return backends.ProcessWith(
  397. func(e *mail.Envelope, task backends.SelectTask) (backends.Result, error) {
  398. if task == backends.TaskValidateRcpt {
  399. // log the last recipient appended to e.Rcpt
  400. backends.Log().Infof(
  401. "another funky recipient [%s]",
  402. e.RcptTo[len(e.RcptTo)-1])
  403. // if valid then forward call to the next processor in the chain
  404. return p.Process(e, task)
  405. } else if task == backends.TaskSaveMail {
  406. backends.Log().Info("Another funky email!")
  407. }
  408. return p.Process(e, task)
  409. })
  410. }
  411. }
  412. // How about a custom processor?
  413. func TestSetAddProcessor(t *testing.T) {
  414. if err := os.Truncate("tests/testlog", 0); err != nil {
  415. t.Error(err)
  416. }
  417. cfg := &AppConfig{
  418. LogFile: "tests/testlog",
  419. AllowedHosts: []string{"grr.la"},
  420. BackendConfig: backends.BackendConfig{
  421. backends.ConfigGateways: {
  422. "default": {
  423. "save_process": "HeadersParser|Debugger|FunkyLogger",
  424. "validate_process": "FunkyLogger",
  425. },
  426. },
  427. },
  428. }
  429. d := Daemon{Config: cfg}
  430. d.AddProcessor("FunkyLogger", funkyLogger)
  431. if err := d.Start(); err != nil {
  432. t.Error(err)
  433. }
  434. // lets have a talk with the server
  435. if err := talkToServer("127.0.0.1:2525", ""); err != nil {
  436. t.Error(err)
  437. }
  438. d.Shutdown()
  439. b, err := ioutil.ReadFile("tests/testlog")
  440. if err != nil {
  441. t.Error("could not read logfile")
  442. return
  443. }
  444. // lets check for fingerprints
  445. if !strings.Contains(string(b), "another funky recipient") {
  446. t.Error("did not log: another funky recipient")
  447. }
  448. if !strings.Contains(string(b), "Another funky email!") {
  449. t.Error("Did not log: Another funky email!")
  450. }
  451. if !strings.Contains(string(b), "Funky logger is up & down to funk") {
  452. t.Error("Did not log: Funky logger is up & down to funk")
  453. }
  454. if !strings.Contains(string(b), "The funk has been stopped!") {
  455. t.Error("Did not log:The funk has been stopped!")
  456. }
  457. }
  458. func talkToServer(address string, body string) (err error) {
  459. conn, err := net.Dial("tcp", address)
  460. if err != nil {
  461. return
  462. }
  463. in := bufio.NewReader(conn)
  464. str, err := in.ReadString('\n')
  465. if err != nil {
  466. return err
  467. }
  468. _, err = fmt.Fprint(conn, "HELO maildiranasaurustester\r\n")
  469. if err != nil {
  470. return err
  471. }
  472. str, err = in.ReadString('\n')
  473. if err != nil {
  474. return err
  475. }
  476. _, err = fmt.Fprint(conn, "MAIL FROM:<[email protected]> BODY=8BITMIME\r\n")
  477. if err != nil {
  478. return err
  479. }
  480. str, err = in.ReadString('\n')
  481. if err != nil {
  482. return err
  483. }
  484. _, err = fmt.Fprint(conn, "RCPT TO:<[email protected]>\r\n")
  485. if err != nil {
  486. return err
  487. }
  488. str, err = in.ReadString('\n')
  489. if err != nil {
  490. return err
  491. }
  492. _, err = fmt.Fprint(conn, "DATA\r\n")
  493. if err != nil {
  494. return err
  495. }
  496. str, err = in.ReadString('\n')
  497. if err != nil {
  498. return err
  499. }
  500. if body == "" {
  501. _, err = fmt.Fprint(conn, "Subject: Test subject\r\n")
  502. if err != nil {
  503. return err
  504. }
  505. _, err = fmt.Fprint(conn, "\r\n")
  506. if err != nil {
  507. return err
  508. }
  509. _, err = fmt.Fprint(conn, "A an email body\r\n")
  510. if err != nil {
  511. return err
  512. }
  513. _, err = fmt.Fprint(conn, ".\r\n")
  514. if err != nil {
  515. return err
  516. }
  517. } else {
  518. _, err = fmt.Fprint(conn, body)
  519. if err != nil {
  520. return err
  521. }
  522. _, err = fmt.Fprint(conn, ".\r\n")
  523. if err != nil {
  524. return err
  525. }
  526. }
  527. str, err = in.ReadString('\n')
  528. if err != nil {
  529. return err
  530. }
  531. _, err = fmt.Fprint(conn, "QUIT\r\n")
  532. if err != nil {
  533. return err
  534. }
  535. _ = str
  536. return nil
  537. }
  538. // Test hot config reload
  539. // Here we forgot to add FunkyLogger so backend will fail to init
  540. // it will log to stderr at the beginning, but then change to tests/testlog
  541. func TestReloadConfig(t *testing.T) {
  542. if err := os.Truncate("tests/testlog", 0); err != nil {
  543. t.Error(err)
  544. }
  545. d := Daemon{}
  546. if err := d.Start(); err != nil {
  547. t.Error(err)
  548. }
  549. defer d.Shutdown()
  550. cfg := AppConfig{
  551. LogFile: "tests/testlog",
  552. AllowedHosts: []string{"grr.la"},
  553. BackendConfig: backends.BackendConfig{
  554. backends.ConfigGateways: {
  555. "default": {
  556. "save_process": "HeadersParser|Debugger|FunkyLogger",
  557. "validate_process": "FunkyLogger",
  558. },
  559. },
  560. },
  561. }
  562. // Look mom, reloading the config without shutting down!
  563. if err := d.ReloadConfig(cfg); err != nil {
  564. t.Error(err)
  565. }
  566. }
  567. func TestPubSubAPI(t *testing.T) {
  568. if err := truncateIfExists("tests/testlog"); err != nil {
  569. t.Error(err)
  570. }
  571. if err := truncateIfExists("tests/pidfilex.pid"); err != nil {
  572. t.Error(err)
  573. }
  574. d := Daemon{Config: &AppConfig{LogFile: "tests/testlog"}}
  575. if err := d.Start(); err != nil {
  576. t.Error(err)
  577. }
  578. defer d.Shutdown()
  579. // new config
  580. cfg := AppConfig{
  581. PidFile: "tests/pidfilex.pid",
  582. LogFile: "tests/testlog",
  583. AllowedHosts: []string{"grr.la"},
  584. BackendConfig: backends.BackendConfig{
  585. backends.ConfigGateways: {
  586. "default": {
  587. "save_process": "HeadersParser|Debugger|FunkyLogger",
  588. "validate_process": "FunkyLogger",
  589. },
  590. },
  591. },
  592. }
  593. var i = 0
  594. pidEvHandler := func(c *AppConfig) {
  595. i++
  596. if i > 1 {
  597. t.Error("number > 1, it means d.Unsubscribe didn't work")
  598. }
  599. d.Logger.Info("number", i)
  600. }
  601. if err := d.Subscribe(EventConfigPidFile, pidEvHandler); err != nil {
  602. t.Error(err)
  603. }
  604. if err := d.ReloadConfig(cfg); err != nil {
  605. t.Error(err)
  606. }
  607. if err := d.Unsubscribe(EventConfigPidFile, pidEvHandler); err != nil {
  608. t.Error(err)
  609. }
  610. cfg.PidFile = "tests/pidfile2.pid"
  611. d.Publish(EventConfigPidFile, &cfg)
  612. if err := d.ReloadConfig(cfg); err != nil {
  613. t.Error(err)
  614. }
  615. b, err := ioutil.ReadFile("tests/testlog")
  616. if err != nil {
  617. t.Error("could not read logfile")
  618. return
  619. }
  620. // lets interrogate the log
  621. if !strings.Contains(string(b), "number1") {
  622. t.Error("it lools like d.ReloadConfig(cfg) did not fire EventConfigPidFile, pidEvHandler not called")
  623. }
  624. }
  625. func TestAPILog(t *testing.T) {
  626. if err := os.Truncate("tests/testlog", 0); err != nil {
  627. t.Error(err)
  628. }
  629. d := Daemon{}
  630. l := d.Log()
  631. l.Info("logtest1") // to stderr
  632. if l.GetLevel() != log.InfoLevel.String() {
  633. t.Error("Log level does not eq info, it is ", l.GetLevel())
  634. }
  635. d.Logger = nil
  636. d.Config = &AppConfig{LogFile: "tests/testlog"}
  637. l = d.Log()
  638. l.Info("logtest1") // to tests/testlog
  639. //
  640. l = d.Log()
  641. if l.GetLogDest() != "tests/testlog" {
  642. t.Error("log dest is not tests/testlog, it was ", l.GetLogDest())
  643. }
  644. b, err := ioutil.ReadFile("tests/testlog")
  645. if err != nil {
  646. t.Error("could not read logfile")
  647. return
  648. }
  649. // lets interrogate the log
  650. if !strings.Contains(string(b), "logtest1") {
  651. t.Error("hai was not found in the log, it should have been in tests/testlog")
  652. }
  653. }
  654. // Test the allowed_hosts config option with a single entry of ".", which will allow all hosts.
  655. func TestSkipAllowsHost(t *testing.T) {
  656. d := Daemon{}
  657. defer d.Shutdown()
  658. // setting the allowed hosts to a single entry with a dot will let any host through
  659. d.Config = &AppConfig{AllowedHosts: []string{"."}, LogFile: "off"}
  660. if err := d.Start(); err != nil {
  661. t.Error(err)
  662. }
  663. conn, err := net.Dial("tcp", d.Config.Servers[0].ListenInterface)
  664. if err != nil {
  665. t.Error(t)
  666. return
  667. }
  668. in := bufio.NewReader(conn)
  669. if _, err := fmt.Fprint(conn, "HELO test\r\n"); err != nil {
  670. t.Error(err)
  671. }
  672. if _, err := fmt.Fprint(conn, "RCPT TO:<[email protected]>\r\n"); err != nil {
  673. t.Error(err)
  674. }
  675. if _, err := in.ReadString('\n'); err != nil {
  676. t.Error(err)
  677. }
  678. if _, err := in.ReadString('\n'); err != nil {
  679. t.Error(err)
  680. }
  681. str, _ := in.ReadString('\n')
  682. if strings.Index(str, "250") != 0 {
  683. t.Error("expected 250 reply, got:", str)
  684. }
  685. }
  686. var customBackend2 = func() backends.Decorator {
  687. return func(p backends.Processor) backends.Processor {
  688. return backends.ProcessWith(
  689. func(e *mail.Envelope, task backends.SelectTask) (backends.Result, error) {
  690. if task == backends.TaskValidateRcpt {
  691. return p.Process(e, task)
  692. } else if task == backends.TaskSaveMail {
  693. backends.Log().Info("Another funky email!")
  694. err := errors.New("system shock")
  695. return backends.NewResult(response.Canned.FailReadErrorDataCmd, response.SP, err), err
  696. }
  697. return p.Process(e, task)
  698. })
  699. }
  700. }
  701. // Test a custom backend response
  702. func TestCustomBackendResult(t *testing.T) {
  703. if err := os.Truncate("tests/testlog", 0); err != nil {
  704. t.Error(err)
  705. }
  706. cfg := &AppConfig{
  707. LogFile: "tests/testlog",
  708. AllowedHosts: []string{"grr.la"},
  709. BackendConfig: backends.BackendConfig{
  710. backends.ConfigGateways: {
  711. "default": {
  712. "save_process": "HeadersParser|Debugger|Custom",
  713. "validate_process": "Custom",
  714. },
  715. },
  716. },
  717. }
  718. d := Daemon{Config: cfg}
  719. d.AddProcessor("Custom", customBackend2)
  720. if err := d.Start(); err != nil {
  721. t.Error(err)
  722. return
  723. }
  724. // lets have a talk with the server
  725. if err := talkToServer("127.0.0.1:2525", ""); err != nil {
  726. t.Error(err)
  727. }
  728. d.Shutdown()
  729. b, err := ioutil.ReadFile("tests/testlog")
  730. if err != nil {
  731. t.Error("could not read logfile")
  732. return
  733. }
  734. // lets check for fingerprints
  735. if !strings.Contains(string(b), "451 4.3.0 Error") {
  736. t.Error("did not log: 451 4.3.0 Error")
  737. }
  738. if !strings.Contains(string(b), "system shock") {
  739. t.Error("did not log: system shock")
  740. }
  741. }
  742. // Test a backends removed, 2 new backends added added
  743. func TestBackendAddRemove(t *testing.T) {
  744. if err := os.Truncate("tests/testlog", 0); err != nil {
  745. t.Error(err)
  746. }
  747. servers := []ServerConfig{
  748. 0: {
  749. IsEnabled: true,
  750. Hostname: "mail.guerrillamail.com",
  751. MaxSize: 100017,
  752. Timeout: 160,
  753. ListenInterface: "127.0.0.1:2526",
  754. MaxClients: 2,
  755. TLS: ServerTLSConfig{
  756. PrivateKeyFile: "",
  757. PublicKeyFile: "",
  758. StartTLSOn: false,
  759. AlwaysOn: false,
  760. },
  761. },
  762. }
  763. cfg := &AppConfig{
  764. LogFile: "tests/testlog",
  765. PidFile: "tests/go-guerrilla.pid",
  766. AllowedHosts: []string{"grr.la", "spam4.me"},
  767. BackendConfig: backends.BackendConfig{
  768. backends.ConfigGateways: {
  769. "default": {
  770. "save_process": "HeadersParser|Debugger|Custom",
  771. "validate_process": "Custom",
  772. },
  773. "temp": {
  774. "save_process": "HeadersParser|Debugger|Custom",
  775. "validate_process": "Custom",
  776. },
  777. },
  778. },
  779. Servers: servers,
  780. }
  781. d := Daemon{Config: cfg}
  782. d.AddProcessor("Custom", customBackend2)
  783. if err := d.Start(); err != nil {
  784. t.Error(err)
  785. return
  786. }
  787. cfg2 := *cfg
  788. cfg2.BackendConfig = backends.BackendConfig{
  789. backends.ConfigGateways: {
  790. "client1": {
  791. "save_process": "HeadersParser|Debugger|Custom",
  792. "validate_process": "Custom",
  793. },
  794. "client2": {
  795. "save_process": "HeadersParser|Debugger",
  796. "validate_process": "Custom",
  797. },
  798. },
  799. }
  800. eventFiredAdded := false
  801. _ = d.Subscribe(EventConfigBackendConfigAdded, backendEvent(func(appConfig *AppConfig, name string) {
  802. eventFiredAdded = true
  803. }))
  804. eventFiredRemoved := false
  805. _ = d.Subscribe(EventConfigBackendConfigRemoved, backendEvent(func(appConfig *AppConfig, name string) {
  806. eventFiredRemoved = true
  807. }))
  808. // default changed, temp removed, client1 and client2 added
  809. if err := d.ReloadConfig(cfg2); err != nil {
  810. t.Error(err)
  811. return
  812. }
  813. d.Shutdown()
  814. if eventFiredAdded == false {
  815. t.Error("EventConfigBackendConfigAdded did not fired")
  816. }
  817. if eventFiredRemoved == false {
  818. t.Error("EventConfigBackendConfigRemoved did not get fired")
  819. }
  820. }
  821. func TestStreamProcessorConfig(t *testing.T) {
  822. if err := os.Truncate("tests/testlog", 0); err != nil {
  823. t.Error(err)
  824. }
  825. servers := []ServerConfig{
  826. 0: {
  827. IsEnabled: true,
  828. Hostname: "mail.guerrillamail.com",
  829. MaxSize: 100017,
  830. Timeout: 160,
  831. ListenInterface: "127.0.0.1:2526",
  832. MaxClients: 2,
  833. TLS: ServerTLSConfig{
  834. PrivateKeyFile: "",
  835. PublicKeyFile: "",
  836. StartTLSOn: false,
  837. AlwaysOn: false,
  838. },
  839. },
  840. }
  841. cfg := &AppConfig{
  842. LogFile: "tests/testlog",
  843. PidFile: "tests/go-guerrilla.pid",
  844. AllowedHosts: []string{"grr.la", "spam4.me"},
  845. BackendConfig: backends.BackendConfig{
  846. backends.ConfigStreamProcessors: {
  847. "chunkSaver": { // note mixed case
  848. "chunk_size": 8000,
  849. "storage_engine": "memory",
  850. "compress_level": 0,
  851. },
  852. "test:chunksaver": {
  853. "chunk_size": 8000,
  854. "storage_engine": "memory",
  855. "compress_level": 0,
  856. },
  857. "debug": {
  858. "sleep_seconds": 2,
  859. "log_reads": true,
  860. },
  861. },
  862. backends.ConfigGateways: {
  863. "default": {
  864. "save_stream": "mimeanalyzer|chunksaver|test|debug",
  865. },
  866. },
  867. },
  868. Servers: servers,
  869. }
  870. d := Daemon{Config: cfg}
  871. if err := d.Start(); err != nil {
  872. t.Error(err)
  873. return
  874. }
  875. d.Shutdown()
  876. }
  877. func TestStreamProcessor(t *testing.T) {
  878. if err := os.Truncate("tests/testlog", 0); err != nil {
  879. t.Error(err)
  880. }
  881. cfg := &AppConfig{
  882. LogFile: "tests/testlog",
  883. AllowedHosts: []string{"grr.la"},
  884. BackendConfig: backends.BackendConfig{
  885. backends.ConfigStreamProcessors: {
  886. "debug": {
  887. "log_reads": true,
  888. },
  889. },
  890. backends.ConfigGateways: {
  891. "default": {
  892. "save_process": "HeadersParser|Debugger",
  893. "save_stream": "Header|headersparser|compress|Decompress|debug",
  894. "post_process": "Header|headersparser|compress|Decompress|debug",
  895. },
  896. },
  897. },
  898. }
  899. d := Daemon{Config: cfg}
  900. if err := d.Start(); err != nil {
  901. t.Error(err)
  902. }
  903. body := "Subject: Test subject\r\n" +
  904. //"\r\n" +
  905. "A an email body.\r\n" +
  906. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  907. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  908. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  909. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  910. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  911. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  912. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  913. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  914. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  915. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  916. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  917. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n"
  918. // lets have a talk with the server
  919. if err := talkToServer("127.0.0.1:2525", body); err != nil {
  920. t.Error(err)
  921. }
  922. d.Shutdown()
  923. b, err := ioutil.ReadFile("tests/testlog")
  924. if err != nil {
  925. t.Error("could not read logfile")
  926. return
  927. }
  928. // lets check for fingerprints
  929. if strings.Index(string(b), "Debug stream") < 0 {
  930. t.Error("did not log: Debug stream")
  931. }
  932. if strings.Index(string(b), "Error") != -1 {
  933. t.Error("There was an error", string(b))
  934. }
  935. }
  936. func TestStreamProcessorBackground(t *testing.T) {
  937. if err := os.Truncate("tests/testlog", 0); err != nil {
  938. t.Error(err)
  939. }
  940. cfg := &AppConfig{
  941. LogFile: "tests/testlog",
  942. AllowedHosts: []string{"grr.la"},
  943. BackendConfig: backends.BackendConfig{
  944. backends.ConfigStreamProcessors: {
  945. "debug": {
  946. "log_reads": true,
  947. },
  948. "moo:chunksaver": {
  949. "chunk_size": 8000,
  950. "storage_engine": "memory",
  951. "compress_level": 0,
  952. },
  953. },
  954. backends.ConfigGateways: {
  955. "default": {
  956. "save_process": "",
  957. "save_stream": "mimeanalyzer|moo",
  958. "post_process_consumer": "Header|headersparser|compress|Decompress|debug",
  959. "post_process_producer": "moo",
  960. "post_process_size": 100,
  961. "stream_buffer_size": 1024,
  962. "save_workers_size": 8,
  963. "save_timeout": "1s",
  964. "val_rcpt_timeout": "2s",
  965. },
  966. },
  967. },
  968. }
  969. d := Daemon{Config: cfg}
  970. if err := d.Start(); err != nil {
  971. t.Error(err)
  972. }
  973. body := "Subject: Test subject\r\n" +
  974. "\r\n" +
  975. "A an email body.\r\n" +
  976. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  977. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  978. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  979. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  980. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  981. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  982. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  983. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  984. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  985. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  986. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n" +
  987. "Header|headersparser|compress|Decompress|debug Header|headersparser|compress|Decompress|debug.\r\n"
  988. // lets have a talk with the server
  989. if err := talkToServer("127.0.0.1:2525", body); err != nil {
  990. t.Error(err)
  991. }
  992. d.Shutdown()
  993. b, err := ioutil.ReadFile("tests/testlog")
  994. if err != nil {
  995. t.Error("could not read logfile")
  996. return
  997. }
  998. time.Sleep(time.Second * 2)
  999. // lets check for fingerprints
  1000. if strings.Index(string(b), "Debug stream") < 0 {
  1001. t.Error("did not log: Debug stream")
  1002. }
  1003. if strings.Index(string(b), "background process done") < 0 {
  1004. t.Error("did not log: background process done")
  1005. }
  1006. if strings.Index(string(b), "Error") != -1 {
  1007. t.Error("There was an error", string(b))
  1008. }
  1009. }
  1010. var mime0 = `MIME-Version: 1.0
  1011. X-Mailer: MailBee.NET 8.0.4.428
  1012. Subject: test
  1013. subject
  1014. To: [email protected]
  1015. Content-Type: multipart/mixed;
  1016. boundary="XXXXboundary text"
  1017. --XXXXboundary text
  1018. Content-Type: multipart/alternative;
  1019. boundary="XXXXboundary text"
  1020. --XXXXboundary text
  1021. Content-Type: text/plain;
  1022. charset="utf-8"
  1023. Content-Transfer-Encoding: quoted-printable
  1024. This is the body text of a sample message.
  1025. --XXXXboundary text
  1026. Content-Type: text/html;
  1027. charset="utf-8"
  1028. Content-Transfer-Encoding: quoted-printable
  1029. <pre>This is the body text of a sample message.</pre>
  1030. --XXXXboundary text
  1031. Content-Type: text/plain;
  1032. name="log_attachment.txt"
  1033. Content-Disposition: attachment;
  1034. filename="log_attachment.txt"
  1035. Content-Transfer-Encoding: base64
  1036. TUlNRS1WZXJzaW9uOiAxLjANClgtTWFpbGVyOiBNYWlsQmVlLk5FVCA4LjAuNC40MjgNClN1Ympl
  1037. Y3Q6IHRlc3Qgc3ViamVjdA0KVG86IGtldmlubUBkYXRhbW90aW9uLmNvbQ0KQ29udGVudC1UeXBl
  1038. OiBtdWx0aXBhcnQvYWx0ZXJuYXRpdmU7DQoJYm91bmRhcnk9Ii0tLS09X05leHRQYXJ0XzAwMF9B
  1039. RTZCXzcyNUUwOUFGLjg4QjdGOTM0Ig0KDQoNCi0tLS0tLT1fTmV4dFBhcnRfMDAwX0FFNkJfNzI1
  1040. RTA5QUYuODhCN0Y5MzQNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsNCgljaGFyc2V0PSJ1dGYt
  1041. OCINCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IHF1b3RlZC1wcmludGFibGUNCg0KdGVzdCBi
  1042. b2R5DQotLS0tLS09X05leHRQYXJ0XzAwMF9BRTZCXzcyNUUwOUFGLjg4QjdGOTM0DQpDb250ZW50
  1043. LVR5cGU6IHRleHQvaHRtbDsNCgljaGFyc2V0PSJ1dGYtOCINCkNvbnRlbnQtVHJhbnNmZXItRW5j
  1044. b2Rpbmc6IHF1b3RlZC1wcmludGFibGUNCg0KPHByZT50ZXN0IGJvZHk8L3ByZT4NCi0tLS0tLT1f
  1045. TmV4dFBhcnRfMDAwX0FFNkJfNzI1RTA5QUYuODhCN0Y5MzQtLQ0K
  1046. --XXXXboundary text--
  1047. `
  1048. var mime2 = `From: [email protected]
  1049. Content-Type: multipart/mixed;
  1050. boundary="----_=_NextPart_001_01CBE273.65A0E7AA"
  1051. To: [email protected]
  1052. This is a multi-part message in MIME format.
  1053. ------_=_NextPart_001_01CBE273.65A0E7AA
  1054. Content-Type: multipart/alternative;
  1055. boundary="----_=_NextPart_002_01CBE273.65A0E7AA"
  1056. ------_=_NextPart_002_01CBE273.65A0E7AA
  1057. Content-Type: text/plain;
  1058. charset="UTF-8"
  1059. Content-Transfer-Encoding: base64
  1060. [base64-content]
  1061. ------_=_NextPart_002_01CBE273.65A0E7AA
  1062. Content-Type: text/html;
  1063. charset="UTF-8"
  1064. Content-Transfer-Encoding: base64
  1065. [base64-content]
  1066. ------_=_NextPart_002_01CBE273.65A0E7AA--
  1067. ------_=_NextPart_001_01CBE273.65A0E7AA
  1068. Content-Type: message/rfc822
  1069. Content-Transfer-Encoding: 7bit
  1070. X-MimeOLE: Produced By Microsoft Exchange V6.5
  1071. Content-class: urn:content-classes:message
  1072. MIME-Version: 1.0
  1073. Content-Type: multipart/mixed;
  1074. boundary="----_=_NextPart_003_01CBE272.13692C80"
  1075. From: [email protected]
  1076. To: [email protected]
  1077. This is a multi-part message in MIME format.
  1078. ------_=_NextPart_003_01CBE272.13692C80
  1079. Content-Type: multipart/alternative;
  1080. boundary="----_=_NextPart_004_01CBE272.13692C80"
  1081. ------_=_NextPart_004_01CBE272.13692C80
  1082. Content-Type: text/plain;
  1083. charset="iso-8859-1"
  1084. Content-Transfer-Encoding: quoted-printable
  1085. =20
  1086. Viele Gr=FC=DFe
  1087. ------_=_NextPart_004_01CBE272.13692C80
  1088. Content-Type: text/html;
  1089. charset="iso-8859-1"
  1090. Content-Transfer-Encoding: quoted-printable
  1091. <html>...</html>
  1092. ------_=_NextPart_004_01CBE272.13692C80--
  1093. ------_=_NextPart_003_01CBE272.13692C80
  1094. Content-Type: application/x-zip-compressed;
  1095. name="abc.zip"
  1096. Content-Transfer-Encoding: base64
  1097. Content-Disposition: attachment;
  1098. filename="abc.zip"
  1099. [base64-content]
  1100. ------_=_NextPart_003_01CBE272.13692C80--
  1101. ------_=_NextPart_001_01CBE273.65A0E7AA--
  1102. `
  1103. var mime3 = `From [email protected] Mon Feb 19 22:24:21 2001
  1104. Received: from [137.154.210.66] by hotmail.com (3.2) with ESMTP id MHotMailBC5B58230039400431D5899AD24289FA0; Mon Feb 19 22:22:29 2001
  1105. Received: from lancelot.cit.nepean.uws.edu.au (lancelot.cit.uws.edu.au [137.154.148.30])
  1106. by day.uws.edu.au (8.11.1/8.11.1) with ESMTP id f1K6MN404936;
  1107. Tue, 20 Feb 2001 17:22:24 +1100 (EST)
  1108. Received: from hotmail.com (law2-f35.hotmail.com [216.32.181.35])
  1109. by lancelot.cit.nepean.uws.edu.au (8.10.0.Beta10/8.10.0.Beta10) with ESMTP id f1K6MJb13619;
  1110. Tue, 20 Feb 2001 17:22:19 +1100 (EST)
  1111. Received: from mail pickup service by hotmail.com with Microsoft SMTPSVC;
  1112. Mon, 19 Feb 2001 22:21:44 -0800
  1113. Received: from 203.54.221.89 by lw2fd.hotmail.msn.com with HTTP; Tue, 20 Feb 2001 06:21:44 GMT
  1114. X-Originating-IP: [203.54.221.89]
  1115. From: "lara devine" <[email protected]>
  1116. To: [email protected], [email protected],
  1117. [email protected], [email protected],
  1118. [email protected], [email protected],
  1119. [email protected], [email protected],
  1120. [email protected]
  1121. Subject: Fwd: Goldfish
  1122. Date: Tue, 20 Feb 2001 06:21:44
  1123. Mime-Version: 1.0
  1124. Content-Type: text/plain; format=flowed
  1125. Message-ID: <[email protected]>
  1126. X-OriginalArrivalTime: 20 Feb 2001 06:21:44.0718 (UTC) FILETIME=[658BDAE0:01C09B05]
  1127. >> >Two builders (Chris and James) are seated either side of a table in a
  1128. > > >rough
  1129. > > >pub when a well-dressed man enters, orders beer and sits on a stool at
  1130. > > >the bar.
  1131. > > >The two builders start to speculate about the occupation of the suit.
  1132. > > >
  1133. > > >Chris: - I reckon he's an accountant.
  1134. > > >
  1135. > > >James: - No way - he's a stockbroker.
  1136. > > >
  1137. > > >Chris: - He ain't no stockbroker! A stockbroker wouldn't come in here!
  1138. > > >
  1139. > > >The argument repeats itself for some time until the volume of beer gets
  1140. > > >the better of Chris and he makes for the toilet. On entering the toilet
  1141. > > >he
  1142. > > >sees that the suit is standing at a urinal. Curiosity and the several
  1143. > > >beers
  1144. > > >get the better of the builder...
  1145. > > >
  1146. > > >Chris: - 'scuse me.... no offence meant, but me and me mate were
  1147. > > wondering
  1148. > > >
  1149. > > > what you do for a living?
  1150. > > >
  1151. > > >Suit: - No offence taken! I'm a Logical Scientist by profession!
  1152. > > >
  1153. > > >Chris: - Oh! What's that then?
  1154. > > >
  1155. > > >Suit:- I'll try to explain by example... Do you have a goldfish at
  1156. >home?
  1157. > > >
  1158. > > >Chris:- Er...mmm... well yeah, I do as it happens!
  1159. > > >
  1160. > > >Suit: - Well, it's logical to follow that you keep it in a bowl or in a
  1161. > > >pond. Which is it?
  1162. > > >
  1163. > > >Chris: - It's in a pond!
  1164. > > >
  1165. > > >Suit: - Well then it's reasonable to suppose that you have a large
  1166. > > >garden
  1167. > > >then?
  1168. > > >
  1169. > > >Chris: - As it happens, yes I have got a big garden!
  1170. > > >
  1171. > > >Suit: - Well then it's logical to assume that in this town that if you
  1172. > > >have a large garden that you have a large house?
  1173. > > >
  1174. > > >Chris: - As it happens I've got a five bedroom house... built it
  1175. >myself!
  1176. > > >
  1177. > > >Suit: - Well given that you've built a five-bedroom house it is logical
  1178. > > >to asume that you haven't built it just for yourself and that you are
  1179. > > >quite
  1180. > > >probably married?
  1181. > > >
  1182. > > >Chris: - Yes I am married, I live with my wife and three children!
  1183. > > >
  1184. > > >Suit: - Well then it is logical to assume that you are sexually active
  1185. > > >with your wife on a regular basis?
  1186. > > >
  1187. > > >Chris:- Yep! Four nights a week!
  1188. > > >
  1189. > > >Suit: - Well then it is logical to suggest that you do not masturbate
  1190. > > >very often?
  1191. > > >
  1192. > > >Chris: - Me? Never.
  1193. > > >
  1194. > > >Suit: - Well there you are! That's logical science at work!
  1195. > > >
  1196. > > >Chris:- How's that then?
  1197. > > >
  1198. > > >Suit: - Well from finding out that you had a goldfish, I've told you
  1199. > > >about the size of garden you have, size of house, your family and your
  1200. > > >sex
  1201. > > >life!
  1202. > > >
  1203. > > >Chris: - I see! That's pretty impressive... thanks mate!
  1204. > > >
  1205. > > >Both leave the toilet and Chris returns to his mate.
  1206. > > >
  1207. > > >James: - I see the suit was in there. Did you ask him what he does?
  1208. > > >
  1209. > > >Chris: - Yep! He's a logical scientist!
  1210. > > >
  1211. > > >James: What's a logical Scientist?
  1212. > > >
  1213. > > >Chris: - I'll try and explain. Do you have a goldfish?
  1214. > > >
  1215. > > >James: - Nope.
  1216. > > >
  1217. > > >Chris: - Well then, you're a wanker.
  1218. >
  1219. _________________________________________________________________________
  1220. Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com.
  1221. `
  1222. /*
  1223. 1 0 166 1514
  1224. 1.1 186 260 259
  1225. 1.2 280 374 416
  1226. 1.3 437 530 584
  1227. 1.4 605 769 1514
  1228. */
  1229. func TestStreamMimeProcessor(t *testing.T) {
  1230. if err := os.Truncate("tests/testlog", 0); err != nil {
  1231. t.Error(err)
  1232. }
  1233. cfg := &AppConfig{
  1234. LogFile: "tests/testlog",
  1235. AllowedHosts: []string{"grr.la"},
  1236. BackendConfig: backends.BackendConfig{
  1237. backends.ConfigStreamProcessors: {
  1238. "debug": {
  1239. "log_reads": true,
  1240. },
  1241. },
  1242. backends.ConfigGateways: {
  1243. "default": {
  1244. "save_process": "HeadersParser|Debugger",
  1245. "save_stream": "mimeanalyzer|headersparser|compress|Decompress|debug",
  1246. },
  1247. },
  1248. },
  1249. }
  1250. d := Daemon{Config: cfg}
  1251. if err := d.Start(); err != nil {
  1252. t.Error(err)
  1253. }
  1254. go func() {
  1255. time.Sleep(time.Second * 15)
  1256. // for debugging deadlocks
  1257. //pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
  1258. //os.Exit(1)
  1259. }()
  1260. // change \n to \r\n
  1261. mime0 = strings.Replace(mime2, "\n", "\r\n", -1)
  1262. // lets have a talk with the server
  1263. if err := talkToServer("127.0.0.1:2525", mime0); err != nil {
  1264. t.Error(err)
  1265. }
  1266. d.Shutdown()
  1267. b, err := ioutil.ReadFile("tests/testlog")
  1268. if err != nil {
  1269. t.Error("could not read logfile")
  1270. return
  1271. }
  1272. // lets check for fingerprints
  1273. if strings.Index(string(b), "Debug stream") < 0 {
  1274. t.Error("did not log: Debug stream")
  1275. }
  1276. if strings.Index(string(b), "Error") != -1 {
  1277. t.Error("There was an error", string(b))
  1278. }
  1279. }
  1280. var email = `From: Al Gore <[email protected]>
  1281. To: White House Transportation Coordinator <[email protected]>
  1282. Subject: [Fwd: Map of Argentina with Description]
  1283. MIME-Version: 1.0
  1284. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed; s=ncr424; d=reliancegeneral.co.in;
  1285. h=List-Unsubscribe:MIME-Version:From:To:Reply-To:Date:Subject:Content-Type:Content-Transfer-Encoding:Message-ID; [email protected];
  1286. bh=F4UQPGEkpmh54C7v3DL8mm2db1QhZU4gRHR1jDqffG8=;
  1287. b=MVltcq6/I9b218a370fuNFLNinR9zQcdBSmzttFkZ7TvV2mOsGrzrwORT8PKYq4KNJNOLBahswXf
  1288. GwaMjDKT/5TXzegdX/L3f/X4bMAEO1einn+nUkVGLK4zVQus+KGqm4oP7uVXjqp70PWXScyWWkbT
  1289. 1PGUwRfPd/HTJG5IUqs=
  1290. Content-Type: multipart/mixed;
  1291. boundary="D7F------------D7FD5A0B8AB9C65CCDBFA872"
  1292. This is a multi-part message in MIME format.
  1293. --D7F------------D7FD5A0B8AB9C65CCDBFA872
  1294. Content-Type: text/plain; charset=us-ascii
  1295. Content-Transfer-Encoding: 7bit
  1296. Fred,
  1297. Fire up Air Force One! We're going South!
  1298. Thanks,
  1299. Al
  1300. --D7F------------D7FD5A0B8AB9C65CCDBFA872
  1301. Content-Type: message/rfc822
  1302. Content-Transfer-Encoding: 7bit
  1303. Content-Disposition: inline
  1304. Return-Path: <[email protected]>
  1305. Received: from mailhost.whitehouse.gov ([192.168.51.200])
  1306. by heartbeat.whitehouse.gov (8.8.8/8.8.8) with ESMTP id SAA22453
  1307. for <[email protected]>;
  1308. Mon, 13 Aug 1998 l8:14:23 +1000
  1309. Received: from the_big_box.whitehouse.gov ([192.168.51.50])
  1310. by mailhost.whitehouse.gov (8.8.8/8.8.7) with ESMTP id RAA20366
  1311. for [email protected]; Mon, 13 Aug 1998 17:42:41 +1000
  1312. Date: Mon, 13 Aug 1998 17:42:41 +1000
  1313. Message-Id: <[email protected]>
  1314. From: Bill Clinton <[email protected]>
  1315. To: A1 (The Enforcer) Gore <[email protected]>
  1316. Subject: Map of Argentina with Description
  1317. MIME-Version: 1.0
  1318. Content-Type: multipart/mixed;
  1319. boundary="DC8------------DC8638F443D87A7F0726DEF7"
  1320. This is a multi-part message in MIME format.
  1321. --DC8------------DC8638F443D87A7F0726DEF7
  1322. Content-Type: text/plain; charset=us-ascii
  1323. Content-Transfer-Encoding: 7bit
  1324. Hi A1,
  1325. I finally figured out this MIME thing. Pretty cool. I'll send you
  1326. some sax music in .au files next week!
  1327. Anyway, the attached image is really too small to get a good look at
  1328. Argentina. Try this for a much better map:
  1329. http://www.1one1yp1anet.com/dest/sam/graphics/map-arg.htm
  1330. Then again, shouldn't the CIA have something like that?
  1331. Bill
  1332. --DC8------------DC8638F443D87A7F0726DEF7
  1333. Content-Type: image/gif; name="map_of_Argentina.gif"
  1334. Content-Transfer-Encoding: base64
  1335. Content-Disposition: inline; filename="map_of_Argentina.gif"
  1336. R01GOD1hJQA1AKIAAP/////78P/omn19fQAAAAAAAAAAAAAAACwAAAAAJQA1AAAD7Qi63P5w
  1337. wEmjBCLrnQnhYCgM1wh+pkgqqeC9XrutmBm7hAK3tP31gFcAiFKVQrGFR6kscnonTe7FAAad
  1338. GugmRu3CmiBt57fsVq3Y0VFKnpYdxPC6M7Ze4crnnHum4oN6LFJ1bn5NXTN7OF5fQkN5WYow
  1339. BEN2dkGQGWJtSzqGTICJgnQuTJN/WJsojad9qXMuhIWdjXKjY4tenjo6tjVssk2gaWq3uGNX
  1340. U6ZGxseyk8SasGw3J9GRzdTQky1iHNvcPNNI4TLeKdfMvy0vMqLrItvuxfDW8ubjueDtJufz
  1341. 7itICBxISKDBgwgTKjyYAAA7
  1342. --DC8------------DC8638F443D87A7F0726DEF7--
  1343. --D7F------------D7FD5A0B8AB9C65CCDBFA872--
  1344. `
  1345. func TestStreamChunkSaver(t *testing.T) {
  1346. if err := os.Truncate("tests/testlog", 0); err != nil {
  1347. t.Error(err)
  1348. }
  1349. go func() {
  1350. time.Sleep(time.Second * 15)
  1351. // for debugging deadlocks
  1352. //pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
  1353. //os.Exit(1)
  1354. }()
  1355. cfg := &AppConfig{
  1356. LogFile: "tests/testlog",
  1357. AllowedHosts: []string{"grr.la"},
  1358. BackendConfig: backends.BackendConfig{
  1359. backends.ConfigStreamProcessors: {
  1360. "chunksaver": {
  1361. "chunk_size": 1024 * 32,
  1362. "stream_buffer_size": 1024 * 16,
  1363. "storage_engine": "memory",
  1364. },
  1365. },
  1366. backends.ConfigGateways: {
  1367. "default": {
  1368. "save_process": "HeadersParser|Debugger",
  1369. "save_stream": "mimeanalyzer|chunksaver",
  1370. "save_timeout": "5",
  1371. },
  1372. },
  1373. },
  1374. }
  1375. d := Daemon{Config: cfg}
  1376. if err := d.Start(); err != nil {
  1377. t.Error(err)
  1378. }
  1379. // change \n to \r\n
  1380. email = strings.Replace(email, "\n", "\r\n", -1)
  1381. // lets have a talk with the server
  1382. if err := talkToServer("127.0.0.1:2525", email); err != nil {
  1383. t.Error(err)
  1384. }
  1385. time.Sleep(time.Second * 1)
  1386. d.Shutdown()
  1387. b, err := ioutil.ReadFile("tests/testlog")
  1388. if err != nil {
  1389. t.Error("could not read logfile")
  1390. return
  1391. }
  1392. fmt.Println(string(b))
  1393. // lets check for fingerprints
  1394. if strings.Index(string(b), "Debug stream") < 0 {
  1395. // t.Error("did not log: Debug stream")
  1396. }
  1397. }