Skip to content

Commit

Permalink
Merge pull request #33 from souramoo/add-smtp-insecure-req
Browse files Browse the repository at this point in the history
Add smtp insecure req
  • Loading branch information
souramoo authored Apr 24, 2021
2 parents 84ffbc2 + b3588cb commit e57da71
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 39 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ If you want the old behaviour, you can disable this with an environment variable
$ export COMMENTO_ENABLE_WILDCARDS=false
```

#### Disabling SMTP Host verification check

Commento++ allows configuration of the tlsConfig for both SMTPS as well as StartTLS for email sending.
For context, this is required for the [https://cloudron.io/](Cloudron) app package.

To skip SMTP hostname verification, use:

```
$ export SMTP_SKIP_HOST_VERIFY=true
```


#### Docker setup
Alternatively you can use the pre-build images from:
Expand Down
11 changes: 6 additions & 5 deletions api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ func configParse() error {

"GZIP_STATIC": "false",

"SMTP_USERNAME": "",
"SMTP_PASSWORD": "",
"SMTP_HOST": "",
"SMTP_PORT": "",
"SMTP_FROM_ADDRESS": "",
"SMTP_USERNAME": "",
"SMTP_PASSWORD": "",
"SMTP_HOST": "",
"SMTP_PORT": "",
"SMTP_FROM_ADDRESS": "",
"SMTP_SKIP_HOST_VERIFY": "false",

"AKISMET_KEY": "",

Expand Down
6 changes: 1 addition & 5 deletions api/smtp_domain_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"bytes"
"net/smtp"
"os"
)

Expand All @@ -13,13 +12,10 @@ type domainExportPlugs struct {
}

func smtpDomainExport(to string, toName string, domain string, exportHex string) error {
var header bytes.Buffer
headerTemplate.Execute(&header, &headerPlugs{FromAddress: os.Getenv("SMTP_FROM_ADDRESS"), ToAddress: to, ToName: toName, Subject: "Commento Data Export"})

var body bytes.Buffer
templates["domain-export"].Execute(&body, &domainExportPlugs{Origin: os.Getenv("ORIGIN"), ExportHex: exportHex})

err := smtp.SendMail(os.Getenv("SMTP_HOST")+":"+os.Getenv("SMTP_PORT"), smtpAuth, os.Getenv("SMTP_FROM_ADDRESS"), []string{to}, concat(header, body))
err := smtpSendMail(to, toName, "", "Commento Data Export", body.String())
if err != nil {
logger.Errorf("cannot send data export email: %v", err)
return errorCannotSendEmail
Expand Down
6 changes: 1 addition & 5 deletions api/smtp_domain_export_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"bytes"
"net/smtp"
"os"
)

Expand All @@ -12,13 +11,10 @@ type domainExportErrorPlugs struct {
}

func smtpDomainExportError(to string, toName string, domain string) error {
var header bytes.Buffer
headerTemplate.Execute(&header, &headerPlugs{FromAddress: os.Getenv("SMTP_FROM_ADDRESS"), ToAddress: to, ToName: toName, Subject: "Commento Data Export"})

var body bytes.Buffer
templates["data-export-error"].Execute(&body, &domainExportPlugs{Origin: os.Getenv("ORIGIN")})

err := smtp.SendMail(os.Getenv("SMTP_HOST")+":"+os.Getenv("SMTP_PORT"), smtpAuth, os.Getenv("SMTP_FROM_ADDRESS"), []string{to}, concat(header, body))
err := smtpSendMail(to, toName, "", "Commento Data Export", body.String())
if err != nil {
logger.Errorf("cannot send data export error email: %v", err)
return errorCannotSendEmail
Expand Down
16 changes: 2 additions & 14 deletions api/smtp_email_notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import (
"bytes"
"fmt"
ht "html/template"
"net/smtp"
"os"
tt "text/template"
)

type emailNotificationPlugs struct {
Expand All @@ -22,16 +20,6 @@ type emailNotificationPlugs struct {
}

func smtpEmailNotification(to string, toName string, kind string, domain string, path string, commentHex string, commenterName string, title string, html string, unsubscribeSecretHex string) error {
h, err := tt.New("header").Parse(`MIME-Version: 1.0
From: Commento <{{.FromAddress}}>
To: {{.ToName}} <{{.ToAddress}}>
Content-Type: text/html; charset=UTF-8
Subject: {{.Subject}}
`)
var header bytes.Buffer
h.Execute(&header, &headerPlugs{FromAddress: os.Getenv("SMTP_FROM_ADDRESS"), ToAddress: to, ToName: toName, Subject: "[Commento] " + title})

t, err := ht.ParseFiles(fmt.Sprintf("%s/templates/email-notification.txt", os.Getenv("STATIC")))
if err != nil {
logger.Errorf("cannot parse %s/templates/email-notification.txt: %v", os.Getenv("STATIC"), err)
Expand All @@ -55,9 +43,9 @@ Subject: {{.Subject}}
return err
}

err = smtp.SendMail(os.Getenv("SMTP_HOST")+":"+os.Getenv("SMTP_PORT"), smtpAuth, os.Getenv("SMTP_FROM_ADDRESS"), []string{to}, concat(header, body))
err = smtpSendMail(to, toName, "text/html; charset=UTF-8", "[Commento] "+title, body.String())
if err != nil {
logger.Errorf("cannot send email notification: %v", err)
logger.Errorf("cannot send email notification email: %v", err)
return errorCannotSendEmail
}

Expand Down
6 changes: 1 addition & 5 deletions api/smtp_owner_confirm_hex.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"bytes"
"net/smtp"
"os"
)

Expand All @@ -12,13 +11,10 @@ type ownerConfirmHexPlugs struct {
}

func smtpOwnerConfirmHex(to string, toName string, confirmHex string) error {
var header bytes.Buffer
headerTemplate.Execute(&header, &headerPlugs{FromAddress: os.Getenv("SMTP_FROM_ADDRESS"), ToAddress: to, ToName: toName, Subject: "Please confirm your email address"})

var body bytes.Buffer
templates["confirm-hex"].Execute(&body, &ownerConfirmHexPlugs{Origin: os.Getenv("ORIGIN"), ConfirmHex: confirmHex})

err := smtp.SendMail(os.Getenv("SMTP_HOST")+":"+os.Getenv("SMTP_PORT"), smtpAuth, os.Getenv("SMTP_FROM_ADDRESS"), []string{to}, concat(header, body))
err := smtpSendMail(to, toName, "", "Please confirm your email address", body.String())
if err != nil {
logger.Errorf("cannot send confirmation email: %v", err)
return errorCannotSendEmail
Expand Down
6 changes: 1 addition & 5 deletions api/smtp_reset_hex.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"bytes"
"net/smtp"
"os"
)

Expand All @@ -12,13 +11,10 @@ type resetHexPlugs struct {
}

func smtpResetHex(to string, toName string, resetHex string) error {
var header bytes.Buffer
headerTemplate.Execute(&header, &headerPlugs{FromAddress: os.Getenv("SMTP_FROM_ADDRESS"), ToAddress: to, ToName: toName, Subject: "Reset your password"})

var body bytes.Buffer
templates["reset-hex"].Execute(&body, &resetHexPlugs{Origin: os.Getenv("ORIGIN"), ResetHex: resetHex})

err := smtp.SendMail(os.Getenv("SMTP_HOST")+":"+os.Getenv("SMTP_PORT"), smtpAuth, os.Getenv("SMTP_FROM_ADDRESS"), []string{to}, concat(header, body))
err := smtpSendMail(to, toName, "", "Reset your password", body.String())
if err != nil {
logger.Errorf("cannot send reset email: %v", err)
return errorCannotSendEmail
Expand Down
92 changes: 92 additions & 0 deletions api/smtp_send.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package main

import (
"crypto/tls"
"fmt"
"net"
"net/mail"
"net/smtp"
"os"
)

func smtpSendMail(toAddress string, toName string, contentType string, subject string, body string) error {
from := mail.Address{"", os.Getenv("SMTP_FROM_ADDRESS")}
to := mail.Address{"", toAddress}

// Setup headers
headers := make(map[string]string)
headers["Subject"] = subject
headers["From"] = "Commento <" + from.String() + ">"
if toName == "" {
headers["To"] = to.String()
} else {
headers["To"] = toName + " <" + to.String() + ">"
}
if contentType == "" {
headers["Content-Type"] = "text/plain; charset=UTF-8"
} else {
headers["Content-Type"] = contentType
}

// Setup message
message := ""
for k, v := range headers {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\n" + body

// Connect to the SMTP Server
servername := os.Getenv("SMTP_HOST") + ":" + os.Getenv("SMTP_PORT")

host, _, _ := net.SplitHostPort(servername)

// TLS config
tlsconfig := &tls.Config{
ServerName: host,
}
if os.Getenv("SMTP_SKIP_HOST_VERIFY") == "true" {
tlsconfig.InsecureSkipVerify = true
}

c, err := smtp.Dial(servername)
if err != nil {
return err
}

err = c.StartTLS(tlsconfig)
if err != nil {
return err
}

err = c.Auth(smtpAuth)
if err != nil {
return err
}

err = c.Mail(from.Address)
if err != nil {
return err
}

err = c.Rcpt(to.Address)
if err != nil {
return err
}

w, err := c.Data()
if err != nil {
return err
}

_, err = w.Write([]byte(message))
if err != nil {
return err
}

err = w.Close()
if err != nil {
return err
}

return nil
}
5 changes: 5 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
"description": "Allows use of wildcards in domain names in the admin dashboard, defaults to true. Set to false to disable (e.g. if you share your commento instance with more than one admin/allow new registrations)",
"required": false,
"value": "true"
},
"COMMENTO_SMTP_SKIP_HOST_VERIFY": {
"description": "Allows skipping of host verification for SMTP email sending, defaults to false. Set to true to enable (e.g. for the Cloudron app package)",
"required": false,
"value": "false"
}
}
}

0 comments on commit e57da71

Please sign in to comment.