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.

82 lines
2.3 KiB

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