diff --git a/bookings b/bookings
new file mode 100755
index 0000000..90706e4
Binary files /dev/null and b/bookings differ
diff --git a/cmd/web/main.go b/cmd/web/main.go
index 57f3ce5..2bb20eb 100644
--- a/cmd/web/main.go
+++ b/cmd/web/main.go
@@ -32,6 +32,9 @@ func main() {
}
defer db.SQL.Close()
+ defer close(app.MailChan)
+ listenForMail()
+
fmt.Println(fmt.Sprintf("Starting application on port %s", portNumber))
// _ = http.ListenAndServe(portNumber, nil)
@@ -50,6 +53,9 @@ func run() (*driver.DB, error) {
gob.Register(models.Room{})
gob.Register(models.Restriction{})
+ mailChan := make(chan models.MailData)
+ app.MailChan = mailChan
+
// change this to true when in production
app.InProduction = false
diff --git a/cmd/web/send-mail.go b/cmd/web/send-mail.go
new file mode 100644
index 0000000..43a87c2
--- /dev/null
+++ b/cmd/web/send-mail.go
@@ -0,0 +1,56 @@
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "strings"
+ "time"
+
+ "github.com/abneed/bookings/internal/models"
+ mail "github.com/xhit/go-simple-mail/v2"
+)
+
+func listenForMail() {
+ go func() {
+ for {
+ msg := <-app.MailChan
+ sendMsg(msg)
+ }
+ }()
+}
+
+func sendMsg(m models.MailData) {
+ server := mail.NewSMTPClient()
+ server.Host = "localhost"
+ server.Port = 1025
+ server.KeepAlive = false
+ server.ConnectTimeout = 10 * time.Second
+ server.SendTimeout = 10 * time.Second
+
+ client, err := server.Connect()
+ if err != nil {
+ errorLog.Println(err)
+ }
+ email := mail.NewMSG()
+ email.SetFrom(m.From).AddTo(m.To).SetSubject(m.Subject)
+ if m.Template == "" {
+ email.SetBody(mail.TextHTML, m.Content)
+ } else {
+ data, err := ioutil.ReadFile(fmt.Sprintf("./email-templates/%s", m.Template))
+ if err != nil {
+ app.ErrorLog.Println(err)
+ }
+
+ mailTemplate := string(data)
+ msgToSend := strings.Replace(mailTemplate, "[%body%]", m.Content, 1)
+ email.SetBody(mail.TextHTML, msgToSend)
+ }
+
+ err = email.Send(client)
+ if err != nil {
+ log.Println(err)
+ } else {
+ log.Println("Email sent!")
+ }
+}
diff --git a/email-templates/basic.html b/email-templates/basic.html
new file mode 100644
index 0000000..e9e55ba
--- /dev/null
+++ b/email-templates/basic.html
@@ -0,0 +1,1884 @@
+
+
+
+
+
+
+ Title
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Fort Smythe
+ |
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+ [%body%]
+
+ |
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+
+
+ |
+
+
+
+
+
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 8a7c4d7..c8eeb88 100644
--- a/go.mod
+++ b/go.mod
@@ -67,6 +67,8 @@ require (
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect
github.com/spf13/cobra v1.4.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
+ github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
+ github.com/xhit/go-simple-mail/v2 v2.11.0 // indirect
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
diff --git a/go.sum b/go.sum
index ea3f655..d5df3f8 100644
--- a/go.sum
+++ b/go.sum
@@ -469,7 +469,11 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 h1:PM5hJF7HVfNWmCjMdEfbuOBNXSVF2cMFGgQTPdKCbwM=
+github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208/go.mod h1:BzWtXXrXzZUvMacR0oF/fbDDgUPO8L36tDMmRAf14ns=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/xhit/go-simple-mail/v2 v2.11.0 h1:o/056V50zfkO3Mm5tVdo9rG3ryg4ZmJ2XW5GMinHfVs=
+github.com/xhit/go-simple-mail/v2 v2.11.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/internal/config/config.go b/internal/config/config.go
index 980725c..9ad74a8 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -4,6 +4,7 @@ import (
"html/template"
"log"
+ "github.com/abneed/bookings/internal/models"
"github.com/alexedwards/scs/v2"
)
@@ -15,4 +16,5 @@ type AppConfig struct {
ErrorLog *log.Logger
InProduction bool
Session *scs.SessionManager
+ MailChan chan models.MailData
}
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go
index 3f88031..448024e 100644
--- a/internal/handlers/handlers.go
+++ b/internal/handlers/handlers.go
@@ -2,6 +2,7 @@ package handlers
import (
"encoding/json"
+ "fmt"
"net/http"
"strconv"
"strings"
@@ -180,6 +181,38 @@ func (m *Repository) PostReservation(w http.ResponseWriter, r *http.Request) {
return
}
+ // send notifications - first to guest
+ htmlMessage := fmt.Sprintf(`
+ Reservation Confirmation
+ Dear %s,
+ This is to confirm your reservation from %s to %s.
+ `, reservation.FirstName, reservation.StartDate.Format("2006-01-02"), reservation.EndDate.Format("2006-01-02"))
+
+ msg := models.MailData{
+ To: reservation.Email,
+ From: "me@here.com",
+ Subject: "Reservation Confirmation",
+ Content: htmlMessage,
+ Template: "basic.html",
+ }
+
+ m.App.MailChan <- msg
+
+ // send notifications to property owner
+ htmlMessage = fmt.Sprintf(`
+ Reservation Notifcation
+ A reservation has been made for %s from %s to %s.
+ `, reservation.Room.RoomName, reservation.StartDate.Format("2006-01-02"), reservation.EndDate.Format("2006-01-02"))
+
+ msg = models.MailData{
+ To: "me@here.com",
+ From: "me@here.com",
+ Subject: "Reservation Notification",
+ Content: htmlMessage,
+ }
+
+ m.App.MailChan <- msg
+
m.App.Session.Put(r.Context(), "reservation", reservation)
http.Redirect(w, r, "/reservation-summary", http.StatusSeeOther)
diff --git a/internal/handlers/setup_test.go b/internal/handlers/setup_test.go
index fe87d18..8d1d474 100644
--- a/internal/handlers/setup_test.go
+++ b/internal/handlers/setup_test.go
@@ -45,6 +45,12 @@ func TestMain(m *testing.M) {
app.Session = session
+ mailChan := make(chan models.MailData)
+ app.MailChan = mailChan
+ defer close(mailChan)
+
+ listenForMail()
+
tc, err := CreateTestTemplateCache()
if err != nil {
log.Fatal("cannot create template cache")
@@ -60,6 +66,14 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
+func listenForMail() {
+ go func() {
+ for {
+ _ = <-app.MailChan
+ }
+ }()
+}
+
func getRoutes() http.Handler {
mux := chi.NewRouter()
diff --git a/internal/models/models.go b/internal/models/models.go
index 77fc632..a9356f9 100644
--- a/internal/models/models.go
+++ b/internal/models/models.go
@@ -1,6 +1,8 @@
package models
-import "time"
+import (
+ "time"
+)
// User is the user model
type User struct {
@@ -59,3 +61,12 @@ type RoomRestriction struct {
Reservation Reservation
Restriction Restriction
}
+
+// MailData holds an email message
+type MailData struct {
+ To string
+ From string
+ Subject string
+ Content string
+ Template string
+}