A simple way to handle form submissions from static websites.
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.

89 lines
2.4 KiB

4 years ago
4 years ago
4 years ago
4 years ago
  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net/smtp"
  6. "sort"
  7. "strconv"
  8. "strings"
  9. "time"
  10. )
  11. func sendForm(values FormValues) {
  12. recipient := findRecipient(values)
  13. sendMail(recipient, buildMessage(recipient, time.Now(), values))
  14. }
  15. func buildMessage(recipient string, date time.Time, values FormValues) string {
  16. var msgBuffer bytes.Buffer
  17. _, _ = fmt.Fprintf(&msgBuffer, "From: Forms <%s>", appConfig.Sender)
  18. _, _ = fmt.Fprintln(&msgBuffer)
  19. _, _ = fmt.Fprintf(&msgBuffer, "To: %s", recipient)
  20. _, _ = fmt.Fprintln(&msgBuffer)
  21. if replyTo := findReplyTo(values); replyTo != "" {
  22. _, _ = fmt.Fprintf(&msgBuffer, "Reply-To: %s", replyTo)
  23. _, _ = fmt.Fprintln(&msgBuffer)
  24. }
  25. _, _ = fmt.Fprintf(&msgBuffer, "Date: %s", date.Format(time.RFC1123Z))
  26. _, _ = fmt.Fprintln(&msgBuffer)
  27. _, _ = fmt.Fprintf(&msgBuffer, "Subject: New submission on %s", findFormName(values))
  28. _, _ = fmt.Fprintln(&msgBuffer)
  29. _, _ = fmt.Fprintln(&msgBuffer)
  30. bodyValues := removeMetaValues(values)
  31. var keys []string
  32. for key, _ := range bodyValues {
  33. keys = append(keys, key)
  34. }
  35. sort.Strings(keys)
  36. for _, key := range keys {
  37. _, _ = fmt.Fprint(&msgBuffer, key)
  38. _, _ = fmt.Fprint(&msgBuffer, ": ")
  39. _, _ = fmt.Fprintln(&msgBuffer, strings.Join(bodyValues[key], ", "))
  40. }
  41. return msgBuffer.String()
  42. }
  43. func sendMail(to, message string) {
  44. auth := smtp.PlainAuth("", appConfig.SmtpUser, appConfig.SmtpPassword, appConfig.SmtpHost)
  45. err := smtp.SendMail(appConfig.SmtpHost+":"+strconv.Itoa(appConfig.SmtpPort), auth, appConfig.Sender, []string{to}, []byte(message))
  46. if err != nil {
  47. fmt.Println("Failed to send mail:", err.Error())
  48. }
  49. }
  50. func findRecipient(values FormValues) string {
  51. if len(values["_to"]) == 1 && values["_to"][0] != "" {
  52. formDefinedRecipient := values["_to"][0]
  53. for _, allowed := range appConfig.AllowedRecipients {
  54. if formDefinedRecipient == allowed {
  55. return formDefinedRecipient
  56. }
  57. }
  58. }
  59. return appConfig.DefaultRecipient
  60. }
  61. func findFormName(values FormValues) string {
  62. if len(values["_formName"]) == 1 && values["_formName"][0] != "" {
  63. return values["_formName"][0]
  64. }
  65. return "a form"
  66. }
  67. func findReplyTo(values FormValues) string {
  68. if len(values["_replyTo"]) == 1 && values["_replyTo"][0] != "" {
  69. return values["_replyTo"][0]
  70. }
  71. return ""
  72. }
  73. func removeMetaValues(values FormValues) FormValues {
  74. cleanedValues := FormValues{}
  75. for key, value := range values {
  76. if !strings.HasPrefix(key, "_") {
  77. cleanedValues[key] = value
  78. }
  79. }
  80. return cleanedValues
  81. }