diff --git a/Makefile b/Makefile
index 93b529d..97777a0 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@ all: test build
deploy:
which gcloud
gcloud components install app-engine-go
- gcloud app deploy
+ gcloud app deploy --quiet
build:
$(GOBUILD) -o $(PACKAGE_NAME) -v
diff --git a/README.md b/README.md
index 9924fba..2746108 100644
--- a/README.md
+++ b/README.md
@@ -3,24 +3,85 @@
# Configuration variables
+* Create the App Engine configuration file
+ ```
+ cp app.yaml.sample app.yaml
+ ```
+* Edit the `app.yaml` file with your favorite editor and set the following environement variables appropriately:
+
```
-SERVER_ADDR=":8393"
-SMTP_SERVER_ADDR="mail.example.com:465"
-SMTP_CLIENT_USERNAME="demo@example.com"
-SMTP_CLIENT_PASSWORD="dem0ToBeChanged"
-CONTACT_REPLY_EMAIL="noreply@example.com"
-CONTACT_REPLY_CC_EMAIL="contact@example.com"
-DEMO_URL="https://demo.example.com/"
-ALLOWED_ORIGIN_DOMAIN="localhost:1313"
-TEMPLATE_DEMO_REQUEST_REPLY=templates/template_demo_request_reply.html
-TEMPLATE_CONTACT_REQUEST_REPLY=templates/template_contact_request_reply.html
+ SMTP_SERVER_ADDR: "smtp.mailgun.org:587"
+ SMTP_VERITY_CERT: true
+ SMTP_CLIENT_USERNAME: "postmaster@example.com"
+ SMTP_CLIENT_PASSWORD: "postmasterSecretPassWord"
+ CONTACT_REPLY_EMAIL: "noreply@example.com"
+ CONTACT_REPLY_CC_EMAIL: "contact@example.com"
+ DEMO_URL: "https://demo.example.com/"
+ ALLOWED_ORIGIN_DOMAIN: "example.com"
```
+
+## Required HTTP Headers
+
+* `Origin`
+* `Referer`
+
## SMTP
https://cloud.google.com/compute/docs/tutorials/sending-mail/using-mailgun?hl=fr
+## Test
+```
+curl -H'Origin: http://realopinsight.com' \
+ -H'Referer: realopinsight.com' \
+ -H'Content-Type: application/x-www-form-urlencoded' \
+ -d 'target=contact' \
+ -XPOST https://hugo-mx-gateway.ew.r.appspot.com/sendmail
+```
# Build
-
```sh
make build
```
+
+# Hugo Contact Form
+See `./model/hugo-contact-form.html`.
+
+
+```
+
+
+
+
+```
diff --git a/app.yaml.sample b/app.yaml.sample
index 05b03c8..1188fd8 100644
--- a/app.yaml.sample
+++ b/app.yaml.sample
@@ -5,9 +5,7 @@ env_variables:
SMTP_VERITY_CERT: true
SMTP_CLIENT_USERNAME: "postmaster@example.com"
SMTP_CLIENT_PASSWORD: "postmasterSecretPassWord"
+ ALLOWED_ORIGINS: "127.0.0.1,example.com"
CONTACT_REPLY_EMAIL: "noreply@example.com"
CONTACT_REPLY_CC_EMAIL: "contact@example.com"
- DEMO_URL: "https://demo.example.com/"
- ALLOWED_ORIGIN_DOMAIN: "example.com"
- TEMPLATE_DEMO_REQUEST_REPLY: templates/template_reply_demo_request.html
- TEMPLATE_CONTACT_REQUEST_REPLY: templates/template_reply_contact_request.html
\ No newline at end of file
+ DEMO_URL: "https://demo.example.com/"
\ No newline at end of file
diff --git a/examples/demo-request.html b/examples/demo-request.html
deleted file mode 100644
index eefaa98..0000000
--- a/examples/demo-request.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
\ No newline at end of file
diff --git a/main.go b/main.go
index b9f51c8..21d1697 100644
--- a/main.go
+++ b/main.go
@@ -18,7 +18,8 @@ package main
import (
"net/http"
- "time"
+ "time"
+ "os"
"github.com/spf13/viper"
"github.com/gorilla/mux"
@@ -76,7 +77,6 @@ func NewRouter() *mux.Router {
func main() {
viper.AutomaticEnv()
- viper.SetDefault("SERVER_ADDR", ":8080")
viper.SetDefault("SERVER_TLS_CERT", "/etc/cert/cert.pem")
viper.SetDefault("SERVER_TLS_PRIVATEKEY", "/etc/cert/privkey.pem")
viper.SetDefault("SMTP_SERVER_ADDR", "127.0.0.1:465")
@@ -87,13 +87,17 @@ func main() {
viper.SetDefault("EMAIL_SUBJECT", "Thanks to try our product")
viper.SetDefault("DEMO_URL", "http://company.com/product-demo")
+ port := os.Getenv("PORT")
+ if port == "" {
+ port = "8080"
+ log.Infof("Defaulting to port %s", port)
+ }
+
router := NewRouter()
- serverAddr := viper.GetString("SERVER_ADDR")
+ log.Infof("Listening on port %s", port)
- log.Infof("Listening on %s", serverAddr)
-
- log.Fatal(http.ListenAndServe(serverAddr, router))
+ log.Fatal(http.ListenAndServe(":"+port, router))
}
diff --git a/model/hugo-contact-form.html b/model/hugo-contact-form.html
new file mode 100644
index 0000000..81f87e8
--- /dev/null
+++ b/model/hugo-contact-form.html
@@ -0,0 +1,37 @@
+
+
\ No newline at end of file
diff --git a/sendmail.go b/sendmail.go
index d6de036..6a5dda6 100644
--- a/sendmail.go
+++ b/sendmail.go
@@ -22,12 +22,12 @@ import (
"encoding/json"
"fmt"
"html/template"
- "log"
"net"
"net/http"
"net/smtp"
"strings"
+ log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
@@ -79,7 +79,7 @@ func (m *SendMailRequest) Execute() error {
// TLS config
tlsconfig := &tls.Config{
- InsecureSkipVerify: true,
+ InsecureSkipVerify: viper.GetBool("SMTP_VERITY_CERT"),
ServerName: smtpServerHost,
}
@@ -151,24 +151,25 @@ func (m *SendMailRequest) ParseTemplate(templateFileName string, data interface{
// SendMail handles HTTP request to send email
func SendMail(httpResp http.ResponseWriter, httpReq *http.Request) {
- AllowedOriginDomain := viper.GetString("ALLOWED_ORIGIN_DOMAIN")
- AllowedOrigins := map[string]bool{
- fmt.Sprintf("http://%s", AllowedOriginDomain): true,
- fmt.Sprintf("https://%s", AllowedOriginDomain): true,
- fmt.Sprintf("http://www.%s", AllowedOriginDomain): true,
- fmt.Sprintf("https://www.%s", AllowedOriginDomain): true,
+ allowedDomains := strings.Split(viper.GetString("ALLOWED_ORIGINS"), ",")
+ allowedOrigins := make(map[string]bool)
+ for _, domain := range allowedDomains {
+ domainTrimmed := strings.TrimSpace(domain)
+ allowedOrigins[fmt.Sprintf("http://%s", domainTrimmed)] = true
+ allowedOrigins[fmt.Sprintf("https://%s", domainTrimmed)] = true
+ allowedOrigins[fmt.Sprintf("http://www.%s", domainTrimmed)] = true
+ allowedOrigins[fmt.Sprintf("https://www.%s", domainTrimmed)] = true
}
-
if len(httpReq.Header["Origin"]) == 0 || len(httpReq.Header["Referer"]) == 0 {
rawHeader, _ := json.Marshal(httpReq.Header)
- log.Println("request with unexpected headers:", string(rawHeader))
+ log.Infoln("request with unexpected headers", string(rawHeader))
httpResp.WriteHeader(http.StatusForbidden)
return
}
reqOrigin := httpReq.Header["Origin"][0]
- if _, domainFound := AllowedOrigins[reqOrigin]; !domainFound {
- log.Println("Not allowed origin:", reqOrigin)
+ if _, domainFound := allowedOrigins[reqOrigin]; !domainFound {
+ log.Errorln("not allowed origin", reqOrigin)
httpResp.WriteHeader(http.StatusForbidden)
return
}
@@ -191,13 +192,13 @@ func SendMail(httpResp http.ResponseWriter, httpReq *http.Request) {
case "contact":
recipients = []string{viper.GetString("CONTACT_REPLY_CC_EMAIL")}
default:
- log.Println("Not allowed request type:", contactRequest.RequestTarget)
+ log.Infoln("not allowed request type:", contactRequest.RequestTarget)
httpResp.WriteHeader(http.StatusForbidden)
return
}
userData, _ := json.Marshal(contactRequest)
- log.Println("New Request:", string(userData))
+ log.Infoln("New Request:", string(userData))
templateData := struct {
Name string
@@ -233,7 +234,7 @@ func SendMail(httpResp http.ResponseWriter, httpReq *http.Request) {
if err == nil {
err := sendMailReq.Execute()
if err != nil {
- log.Printf("error: %s", err.Error())
+ log.Infof("error: %s", err.Error())
contactResponse.Status = "error"
contactResponse.Message = fmt.Sprintf("An internal error occurred, please try later or send us an email at %s.", viper.GetString("CONTACT_REPLY_CC_EMAIL"))
} else {
@@ -245,7 +246,7 @@ func SendMail(httpResp http.ResponseWriter, httpReq *http.Request) {
}
}
} else {
- log.Printf("error: %s", err.Error())
+ log.Infof("error: %s", err.Error())
contactResponse.Status = "error"
contactResponse.Message = "Invalid request, please review your input and try again."
}