You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.6KB

  1. package main // import "github.com/productionwentdown/email-collector"
  2. import (
  3. "bytes"
  4. "encoding/csv"
  5. "encoding/json"
  6. "flag"
  7. "io/ioutil"
  8. "log"
  9. "net/http"
  10. "os"
  11. "sync"
  12. "time"
  13. // modified from @badoux's checkmail
  14. "github.com/productionwentdown/email-collector/checkmail"
  15. )
  16. var filename string
  17. var listen string
  18. var redirect string
  19. var slack string
  20. func main() {
  21. flag.StringVar(&filename, "file", "list.csv", "file to append records to")
  22. flag.StringVar(&listen, "listen", ":8080", "address to listen to")
  23. flag.StringVar(&redirect, "redirect", "/subscribed", "path to redirect to upon success")
  24. flag.StringVar(&slack, "slack", "", "optional slack webhook url")
  25. flag.Parse()
  26. csvMutex := &sync.Mutex{}
  27. csvFile, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
  28. defer csvFile.Close()
  29. if err != nil {
  30. log.Fatal(err)
  31. }
  32. csvWriter := csv.NewWriter(csvFile)
  33. http.HandleFunc("/subscribe", func(w http.ResponseWriter, r *http.Request) {
  34. err := r.ParseForm()
  35. if err != nil {
  36. log.Println(err)
  37. http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
  38. return
  39. }
  40. email := r.Form.Get("email")
  41. if err := checkmail.ValidateFormat(email); err != nil {
  42. log.Println(email, err)
  43. http.Error(w, "Email is not valid", http.StatusBadRequest)
  44. return
  45. }
  46. err = checkmail.ValidateHost(email)
  47. if _, ok := err.(checkmail.SmtpError); !ok && err != nil {
  48. log.Println(email, err)
  49. http.Error(w, "Email is not valid", http.StatusBadRequest)
  50. return
  51. }
  52. log.Println(email, "success")
  53. csvMutex.Lock()
  54. csvWriter.Write([]string{email, time.Now().String()})
  55. csvWriter.Flush()
  56. csvMutex.Unlock()
  57. if len(slack) > 4 {
  58. object := map[string]string{
  59. "text": "A human (" + email + ") subscribed to the list! Wohoo!",
  60. }
  61. payload, err := json.Marshal(object)
  62. if err != nil {
  63. log.Println("json.Marshal failed, not supposed to happen!")
  64. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  65. return
  66. }
  67. resp, err := http.Post(slack, "application/json", bytes.NewBuffer(payload))
  68. if err != nil {
  69. log.Println(err)
  70. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  71. return
  72. }
  73. defer resp.Body.Close()
  74. if resp.StatusCode != http.StatusOK {
  75. body, _ := ioutil.ReadAll(resp.Body)
  76. log.Println(body)
  77. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  78. return
  79. }
  80. }
  81. w.Header().Add("Location", redirect)
  82. w.WriteHeader(303)
  83. })
  84. log.Fatal(http.ListenAndServe(listen, nil))
  85. }