mirror of
https://github.com/h44z/wg-portal
synced 2025-02-26 05:49:14 +00:00
switch to another email lib to support more AUTH types
This commit is contained in:
parent
7b1f59d86a
commit
19e6fa2a1a
@ -130,6 +130,7 @@ The following configuration options are available:
|
|||||||
| EMAIL_CERT_VALIDATION | certcheck | email | false | Validate the email server certificate. |
|
| EMAIL_CERT_VALIDATION | certcheck | email | false | Validate the email server certificate. |
|
||||||
| EMAIL_USERNAME | user | email | | An optional username for SMTP authentication. |
|
| EMAIL_USERNAME | user | email | | An optional username for SMTP authentication. |
|
||||||
| EMAIL_PASSWORD | pass | email | | An optional password for SMTP authentication. |
|
| EMAIL_PASSWORD | pass | email | | An optional password for SMTP authentication. |
|
||||||
|
| EMAIL_AUTHTYPE | auth | email | plain | Either plain, login or crammd5. If username and password are empty, this value is ignored. |
|
||||||
| WG_DEVICES | devices | wg | wg0 | A comma separated list of WireGuard devices. |
|
| WG_DEVICES | devices | wg | wg0 | A comma separated list of WireGuard devices. |
|
||||||
| WG_DEFAULT_DEVICE | defaultDevice | wg | wg0 | This device is used for auto-created peers (if CREATE_DEFAULT_PEER is enabled). |
|
| WG_DEFAULT_DEVICE | defaultDevice | wg | wg0 | This device is used for auto-created peers (if CREATE_DEFAULT_PEER is enabled). |
|
||||||
| WG_CONFIG_PATH | configDirectory | wg | /etc/wireguard | If set, interface configuration updates will be written to this path, filename: <devicename>.conf. |
|
| WG_CONFIG_PATH | configDirectory | wg | /etc/wireguard | If set, interface configuration updates will be written to this path, filename: <devicename>.conf. |
|
||||||
|
2
go.mod
2
go.mod
@ -13,7 +13,6 @@ require (
|
|||||||
github.com/go-openapi/swag v0.19.15 // indirect
|
github.com/go-openapi/swag v0.19.15 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.4.1
|
github.com/go-playground/validator/v10 v10.4.1
|
||||||
github.com/gorilla/sessions v1.2.1 // indirect
|
github.com/gorilla/sessions v1.2.1 // indirect
|
||||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
|
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/milosgajdos/tenus v0.0.3
|
github.com/milosgajdos/tenus v0.0.3
|
||||||
@ -25,6 +24,7 @@ require (
|
|||||||
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
|
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
|
||||||
github.com/toorop/gin-logrus v0.0.0-20210225092905-2c785434f26f
|
github.com/toorop/gin-logrus v0.0.0-20210225092905-2c785434f26f
|
||||||
github.com/utrack/gin-csrf v0.0.0-20190424104817-40fb8d2c8fca
|
github.com/utrack/gin-csrf v0.0.0-20190424104817-40fb8d2c8fca
|
||||||
|
github.com/xhit/go-simple-mail/v2 v2.8.1
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||||
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6 // indirect
|
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6 // indirect
|
||||||
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83 // indirect
|
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83 // indirect
|
||||||
|
@ -3,13 +3,10 @@ package common
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
"net/smtp"
|
"io/ioutil"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
mail "github.com/xhit/go-simple-mail/v2"
|
||||||
"github.com/jordan-wright/email"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MailEncryption string
|
type MailEncryption string
|
||||||
@ -20,6 +17,14 @@ const (
|
|||||||
MailEncryptionStartTLS MailEncryption = "starttls"
|
MailEncryptionStartTLS MailEncryption = "starttls"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type MailAuthType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
MailAuthPlain MailAuthType = "plain"
|
||||||
|
MailAuthLogin MailAuthType = "login"
|
||||||
|
MailAuthCramMD5 MailAuthType = "crammd5"
|
||||||
|
)
|
||||||
|
|
||||||
type MailConfig struct {
|
type MailConfig struct {
|
||||||
Host string `yaml:"host" envconfig:"EMAIL_HOST"`
|
Host string `yaml:"host" envconfig:"EMAIL_HOST"`
|
||||||
Port int `yaml:"port" envconfig:"EMAIL_PORT"`
|
Port int `yaml:"port" envconfig:"EMAIL_PORT"`
|
||||||
@ -28,6 +33,7 @@ type MailConfig struct {
|
|||||||
CertValidation bool `yaml:"certcheck" envconfig:"EMAIL_CERT_VALIDATION"`
|
CertValidation bool `yaml:"certcheck" envconfig:"EMAIL_CERT_VALIDATION"`
|
||||||
Username string `yaml:"user" envconfig:"EMAIL_USERNAME"`
|
Username string `yaml:"user" envconfig:"EMAIL_USERNAME"`
|
||||||
Password string `yaml:"pass" envconfig:"EMAIL_PASSWORD"`
|
Password string `yaml:"pass" envconfig:"EMAIL_PASSWORD"`
|
||||||
|
AuthType MailAuthType `yaml:"auth" envconfig:"EMAIL_AUTHTYPE"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MailAttachment struct {
|
type MailAttachment struct {
|
||||||
@ -39,60 +45,72 @@ type MailAttachment struct {
|
|||||||
|
|
||||||
// SendEmailWithAttachments sends a mail with optional attachments.
|
// SendEmailWithAttachments sends a mail with optional attachments.
|
||||||
func SendEmailWithAttachments(cfg MailConfig, sender, replyTo, subject, body string, htmlBody string, receivers []string, attachments []MailAttachment) error {
|
func SendEmailWithAttachments(cfg MailConfig, sender, replyTo, subject, body string, htmlBody string, receivers []string, attachments []MailAttachment) error {
|
||||||
e := email.NewEmail()
|
srv := mail.NewSMTPClient()
|
||||||
|
|
||||||
hostname := cfg.Host + ":" + strconv.Itoa(cfg.Port)
|
srv.Host = cfg.Host
|
||||||
subject = strings.Trim(subject, "\n\r\t")
|
srv.Port = cfg.Port
|
||||||
sender = strings.Trim(sender, "\n\r\t")
|
srv.Username = cfg.Username
|
||||||
replyTo = strings.Trim(replyTo, "\n\r\t")
|
srv.Password = cfg.Password
|
||||||
if replyTo == "" {
|
|
||||||
replyTo = sender
|
|
||||||
}
|
|
||||||
|
|
||||||
var auth smtp.Auth
|
|
||||||
if cfg.Username == "" {
|
|
||||||
auth = nil
|
|
||||||
} else {
|
|
||||||
// Set up authentication information.
|
|
||||||
auth = smtp.PlainAuth(
|
|
||||||
"",
|
|
||||||
cfg.Username,
|
|
||||||
cfg.Password,
|
|
||||||
cfg.Host,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set email data.
|
|
||||||
e.From = sender
|
|
||||||
e.To = receivers
|
|
||||||
e.ReplyTo = []string{replyTo}
|
|
||||||
e.Subject = subject
|
|
||||||
e.Text = []byte(body)
|
|
||||||
if htmlBody != "" {
|
|
||||||
e.HTML = []byte(htmlBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, attachment := range attachments {
|
|
||||||
a, err := e.Attach(attachment.Data, attachment.Name, attachment.ContentType)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to attach %s to mailbody", attachment.Name)
|
|
||||||
}
|
|
||||||
if attachment.Embedded {
|
|
||||||
a.HTMLRelated = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove this once the deprecated MailConfig.TLS config option has been removed
|
// TODO: remove this once the deprecated MailConfig.TLS config option has been removed
|
||||||
if cfg.TLS {
|
if cfg.TLS {
|
||||||
cfg.Encryption = MailEncryptionStartTLS
|
cfg.Encryption = MailEncryptionStartTLS
|
||||||
}
|
}
|
||||||
|
|
||||||
switch cfg.Encryption {
|
switch cfg.Encryption {
|
||||||
case MailEncryptionTLS:
|
case MailEncryptionTLS:
|
||||||
return e.SendWithTLS(hostname, auth, &tls.Config{ServerName: cfg.Host, InsecureSkipVerify: !cfg.CertValidation})
|
srv.Encryption = mail.EncryptionTLS
|
||||||
case MailEncryptionStartTLS:
|
case MailEncryptionStartTLS:
|
||||||
return e.SendWithStartTLS(hostname, auth, &tls.Config{ServerName: cfg.Host, InsecureSkipVerify: !cfg.CertValidation})
|
srv.Encryption = mail.EncryptionSTARTTLS
|
||||||
default: // MailEncryptionNone
|
default: // MailEncryptionNone
|
||||||
return e.Send(hostname, auth)
|
srv.Encryption = mail.EncryptionNone
|
||||||
}
|
}
|
||||||
|
srv.TLSConfig = &tls.Config{InsecureSkipVerify: !cfg.CertValidation}
|
||||||
|
switch cfg.AuthType {
|
||||||
|
case MailAuthPlain:
|
||||||
|
srv.Authentication = mail.AuthPlain
|
||||||
|
case MailAuthLogin:
|
||||||
|
srv.Authentication = mail.AuthLogin
|
||||||
|
case MailAuthCramMD5:
|
||||||
|
srv.Authentication = mail.AuthCRAMMD5
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := srv.Connect()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to connect via SMTP")
|
||||||
|
}
|
||||||
|
|
||||||
|
if replyTo == "" {
|
||||||
|
replyTo = sender
|
||||||
|
}
|
||||||
|
|
||||||
|
email := mail.NewMSG()
|
||||||
|
email.SetFrom(sender).
|
||||||
|
AddTo(receivers...).
|
||||||
|
SetReplyTo(replyTo).
|
||||||
|
SetSubject(subject)
|
||||||
|
|
||||||
|
email.SetBody(mail.TextPlain, body)
|
||||||
|
if htmlBody != "" {
|
||||||
|
email.SetBody(mail.TextHTML, htmlBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, attachment := range attachments {
|
||||||
|
attachmentData, err := ioutil.ReadAll(attachment.Data)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to read attachment data for %s", attachment.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if attachment.Embedded {
|
||||||
|
email.AddInlineData(attachmentData, attachment.Name, attachment.ContentType)
|
||||||
|
} else {
|
||||||
|
email.AddAttachmentData(attachmentData, attachment.Name, attachment.ContentType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call Send and pass the client
|
||||||
|
err = email.Send(client)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to send email")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ func NewConfig() *Config {
|
|||||||
cfg.Email.Host = "127.0.0.1"
|
cfg.Email.Host = "127.0.0.1"
|
||||||
cfg.Email.Port = 25
|
cfg.Email.Port = 25
|
||||||
cfg.Email.Encryption = common.MailEncryptionNone
|
cfg.Email.Encryption = common.MailEncryptionNone
|
||||||
|
cfg.Email.AuthType = common.MailAuthPlain
|
||||||
|
|
||||||
// Load config from file and environment
|
// Load config from file and environment
|
||||||
cfgFile, ok := os.LookupEnv("CONFIG_FILE")
|
cfgFile, ok := os.LookupEnv("CONFIG_FILE")
|
||||||
|
@ -265,6 +265,7 @@ func (s *Server) GetPeerConfigMail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Apply mail template
|
// Apply mail template
|
||||||
|
qrcodeFileName := "wireguard-qrcode.png"
|
||||||
var tplBuff bytes.Buffer
|
var tplBuff bytes.Buffer
|
||||||
if err := s.mailTpl.Execute(&tplBuff, struct {
|
if err := s.mailTpl.Execute(&tplBuff, struct {
|
||||||
Peer wireguard.Peer
|
Peer wireguard.Peer
|
||||||
@ -274,7 +275,7 @@ func (s *Server) GetPeerConfigMail(c *gin.Context) {
|
|||||||
}{
|
}{
|
||||||
Peer: peer,
|
Peer: peer,
|
||||||
User: user,
|
User: user,
|
||||||
QrcodePngName: "wireguard-config.png",
|
QrcodePngName: qrcodeFileName,
|
||||||
PortalUrl: s.config.Core.ExternalUrl,
|
PortalUrl: s.config.Core.ExternalUrl,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
s.GetHandleError(c, http.StatusInternalServerError, "Template error", err.Error())
|
s.GetHandleError(c, http.StatusInternalServerError, "Template error", err.Error())
|
||||||
@ -289,7 +290,13 @@ func (s *Server) GetPeerConfigMail(c *gin.Context) {
|
|||||||
Data: bytes.NewReader(cfg),
|
Data: bytes.NewReader(cfg),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "wireguard-config.png",
|
Name: qrcodeFileName,
|
||||||
|
ContentType: "image/png",
|
||||||
|
Data: bytes.NewReader(png),
|
||||||
|
Embedded: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: qrcodeFileName,
|
||||||
ContentType: "image/png",
|
ContentType: "image/png",
|
||||||
Data: bytes.NewReader(png),
|
Data: bytes.NewReader(png),
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user