0

I am currently learning Go, and I am trying to create a contact form. I was using the default net/smtp package to send my mail, but then I stumbled upon Gomail. It made it so much easier to send an email.

Here is the html for the contact form:

<h1>Contact Us</h1>
<form action="/" method="post" novalidate>
  <div>
    <label>Email Address</label>
    <input type="email" name="email" value="{{ .Email }}">
  </div>
  <div>
    <label>Message:</label>
    <textarea name="content">{{ .Content }}</textarea>
  </div>
  <div>
    <input type="submit" value="Submit">
  </div>
</form>

I'm using Go's html/template package to get the values.

main.go:

package main

import (
    "fmt"
    "github.com/bmizerany/pat"
    "gopkg.in/gomail.v2"
    "html/template"
    "log"
    "net/http"
)

func main() {
    mux := pat.New()
    mux.Get("/", http.HandlerFunc(index))
    mux.Post("/", http.HandlerFunc(send))
    mux.Get("/confirmation", http.HandlerFunc(confirmation))

    log.Println("Listening...")
    http.ListenAndServe(":2016", mux)
}

func index(w http.ResponseWriter, r *http.Request) {
    render(w, "templates/index.html", nil)
}

func send(w http.ResponseWriter, r *http.Request) {
  m := &Message{
    Email: r.FormValue("email"),
    Content: r.FormValue("content"),
  }

  if err := m.Deliver(); err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
  http.Redirect(w, r, "/confirmation", http.StatusSeeOther)
}

func confirmation(w http.ResponseWriter, r *http.Request) {
    render(w, "templates/confirmation.html", nil)
}

func render(w http.ResponseWriter, filename string, data interface{}) {
    tmpl, err := template.ParseFiles(filename)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    if err := tmpl.Execute(w, data); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

type Message struct {
    Email   string
    Content string
}

func (m *Message) Deliver() {
    m := gomail.NewMessage()
    m.SetHeader("From", "John Smith <jsmith@gmail.com>")
    m.SetHeader("To", "John Smith <jsmith@gmail.com>")
    m.SetAddressHeader("reply-to", "m.Email")
    m.SetHeader("Subject", "Contact")
    m.SetBody("text/html", "<b>Message</b>: m.Content")
    d := gomail.NewDialer("smtp.gmail.com", 587, "jsmith@gmail.com", "password")
    if err := d.DialAndSend(m); err != nil {
        panic(err)
    }
}

Basically what this does is serve the index page (the contact form) and the confirmation page. It also defines the Email and Contact strings. If I wanted to print out the content of the message, I can just use m.Content, but since Gomail asks for the body and serves html, I don't really know a way to get the string from the form and add it like this:

m.SetBody("text/html", "<b>Message</b>: <!-- Content Goes Here -->")`
cmelone
  • 69
  • 2
  • 10

1 Answers1

1

In this case what you can do, is to use the Sprintf formatting method. In your particular case:

m.SetBody("text/html", fmt.Sprintf("<b>Message</b>: %s", m.Content))
Endre Simo
  • 11,330
  • 2
  • 40
  • 49
  • Thanks for the answer, I had to change m.Content to msg.Content in order to avoid confusion with the compiler. This is what I had to change my code to: http://pastebin.com/raw/TxZPmiw6. Now when I compile, I get `./main.go:59: undefined: msg in msg.Content` – cmelone Apr 10 '16 at 06:22
  • You are instantiating the message struct in the send function, that's why you are getting the undefined error. You have to move out the struct into the main execution thread. Because i suppose `Deliver` func is getting executed on start. – Endre Simo Apr 10 '16 at 06:36
  • If I add the `Message` struct to the main function, (https://git.io/vVSXR0) i get the following errors: `./main.go:29: undefined: msg in msg.Content ./main.go:43: undefined: Message` – cmelone Apr 10 '16 at 07:05
  • i cannot access the url – Endre Simo Apr 10 '16 at 07:22
  • The issue is not where the struct type is defined, but where is referenced. You are referencing, in other words constructing the struct type in the send function, but you are trying to access it in the deliver function, and of course this is not yet accessible. So my suggestion is to either reference the message struct as a pointer, or to move the `Deliver()` content inside the send function. – Endre Simo Apr 10 '16 at 09:46
  • I figured it all out, thanks for your help! I was wondering if you could look at something else really quick. – cmelone Apr 10 '16 at 09:48