mirror of https://github.com/h44z/wg-portal.git
				
				
				
			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