SMTP support (#146)
This commit is contained in:
		
							parent
							
								
									da99259f55
								
							
						
					
					
						commit
						af62be378f
					
				
							
								
								
									
										16
									
								
								README.md
								
								
								
								
							
							
						
						
									
										16
									
								
								README.md
								
								
								
								
							|  | @ -33,7 +33,9 @@ wireguard interface stats. See the `cap_add` and `network_mode` options on the d | ||||||
| 
 | 
 | ||||||
| Set the `SESSION_SECRET` environment variable to a random value. | Set the `SESSION_SECRET` environment variable to a random value. | ||||||
| 
 | 
 | ||||||
| In order to sent the wireguard configuration to clients via email (using sendgrid api) set the following environment variables | In order to sent the wireguard configuration to clients via email, set the following environment variables: | ||||||
|  | 
 | ||||||
|  | - using SendGrid API | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| SENDGRID_API_KEY: Your sendgrid api key | SENDGRID_API_KEY: Your sendgrid api key | ||||||
|  | @ -41,6 +43,18 @@ EMAIL_FROM_ADDRESS: the email address you registered on sendgrid | ||||||
| EMAIL_FROM_NAME: the sender's email address | EMAIL_FROM_NAME: the sender's email address | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | - using SMTP | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | SMTP_HOSTNAME | ||||||
|  | SMTP_PORT | ||||||
|  | SMTP_USERNAME | ||||||
|  | SMTP_PASSWORD | ||||||
|  | SMTP_AUTH_TYPE | ||||||
|  | EMAIL_FROM_ADDRESS: the sender's email address | ||||||
|  | EMAIL_FROM_NAME: the sender's name | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ### Using binary file | ### Using binary file | ||||||
| 
 | 
 | ||||||
| Download the binary file from the release and run it with command: | Download the binary file from the release and run it with command: | ||||||
|  |  | ||||||
|  | @ -0,0 +1,81 @@ | ||||||
|  | package emailer | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"crypto/tls" | ||||||
|  | 	"fmt" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	mail "github.com/xhit/go-simple-mail/v2" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type SmtpMail struct { | ||||||
|  | 	hostname   string | ||||||
|  | 	port       int | ||||||
|  | 	username   string | ||||||
|  | 	password   string | ||||||
|  | 	authType   mail.AuthType | ||||||
|  | 	noTLSCheck bool | ||||||
|  | 	fromName   string | ||||||
|  | 	from       string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func authType(authType string) mail.AuthType { | ||||||
|  | 	switch authType { | ||||||
|  | 	case "PLAIN": | ||||||
|  | 		return mail.AuthPlain | ||||||
|  | 	case "LOGIN": | ||||||
|  | 		return mail.AuthLogin | ||||||
|  | 	default: | ||||||
|  | 		return mail.AuthNone | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewSmtpMail(hostname string, port int, username string, password string, noTLSCheck bool, auth string, fromName, from string) *SmtpMail { | ||||||
|  | 	ans := SmtpMail{hostname: hostname, port: port, username: username, password: password, noTLSCheck: noTLSCheck, fromName: fromName, from: from, authType: authType(auth)} | ||||||
|  | 	return &ans | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func addressField(address string, name string) string { | ||||||
|  | 	if name == "" { | ||||||
|  | 		return address | ||||||
|  | 	} | ||||||
|  | 	return fmt.Sprintf("%s <%s>", name, address) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (o *SmtpMail) Send(toName string, to string, subject string, content string, attachments []Attachment) error { | ||||||
|  | 	server := mail.NewSMTPClient() | ||||||
|  | 
 | ||||||
|  | 	server.Host = o.hostname | ||||||
|  | 	server.Port = o.port | ||||||
|  | 	server.Authentication = o.authType | ||||||
|  | 	server.Username = o.username | ||||||
|  | 	server.Password = o.password | ||||||
|  | 	server.Encryption = mail.EncryptionSTARTTLS | ||||||
|  | 	server.KeepAlive = false | ||||||
|  | 	server.ConnectTimeout = 10 * time.Second | ||||||
|  | 	server.SendTimeout = 10 * time.Second | ||||||
|  | 
 | ||||||
|  | 	if o.noTLSCheck { | ||||||
|  | 		server.TLSConfig = &tls.Config{InsecureSkipVerify: true} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	smtpClient, err := server.Connect() | ||||||
|  | 
 | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	email := mail.NewMSG() | ||||||
|  | 	email.SetFrom("From "+addressField(o.from, o.fromName)). | ||||||
|  | 		AddTo(addressField(to, toName)). | ||||||
|  | 		SetSubject(subject). | ||||||
|  | 		SetBody(mail.TextHTML, content) | ||||||
|  | 
 | ||||||
|  | 	for _, v := range attachments { | ||||||
|  | 		email.Attach(&mail.File{Name: v.Name, Data: v.Data}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = email.Send(smtpClient) | ||||||
|  | 
 | ||||||
|  | 	return err | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										1
									
								
								go.mod
								
								
								
								
							|  | @ -17,6 +17,7 @@ require ( | ||||||
| 	github.com/sendgrid/rest v2.6.4+incompatible // indirect | 	github.com/sendgrid/rest v2.6.4+incompatible // indirect | ||||||
| 	github.com/sendgrid/sendgrid-go v3.10.0+incompatible | 	github.com/sendgrid/sendgrid-go v3.10.0+incompatible | ||||||
| 	github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 | 	github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 | ||||||
|  | 	github.com/xhit/go-simple-mail/v2 v2.10.0 | ||||||
| 	golang.zx2c4.com/wireguard v0.0.20200121 // indirect | 	golang.zx2c4.com/wireguard v0.0.20200121 // indirect | ||||||
| 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c | 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c | ||||||
| 	gopkg.in/go-playground/assert.v1 v1.2.1 // indirect | 	gopkg.in/go-playground/assert.v1 v1.2.1 // indirect | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										2
									
								
								go.sum
								
								
								
								
							|  | @ -147,6 +147,8 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC | ||||||
| github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= | github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= | ||||||
| github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4= | github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4= | ||||||
| github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= | github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= | ||||||
|  | github.com/xhit/go-simple-mail/v2 v2.10.0 h1:nib6RaJ4qVh5HD9UE9QJqnUZyWp3upv+Z6CFxaMj0V8= | ||||||
|  | github.com/xhit/go-simple-mail/v2 v2.10.0/go.mod h1:kA1XbQfCI4JxQ9ccSN6VFyIEkkugOm7YiPkA5hKiQn4= | ||||||
| go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | ||||||
| golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								main.go
								
								
								
								
							
							
						
						
									
										25
									
								
								main.go
								
								
								
								
							|  | @ -25,6 +25,12 @@ var ( | ||||||
| 	// configuration variables
 | 	// configuration variables
 | ||||||
| 	flagDisableLogin   bool   = false | 	flagDisableLogin   bool   = false | ||||||
| 	flagBindAddress    string = "0.0.0.0:5000" | 	flagBindAddress    string = "0.0.0.0:5000" | ||||||
|  | 	flagSmtpHostname   string = "127.0.0.1" | ||||||
|  | 	flagSmtpPort       int    = 25 | ||||||
|  | 	flagSmtpUsername   string | ||||||
|  | 	flagSmtpPassword   string | ||||||
|  | 	flagSmtpAuthType   string = "None" | ||||||
|  | 	flagSmtpNoTLSCheck bool   = false | ||||||
| 	flagSendgridApiKey string | 	flagSendgridApiKey string | ||||||
| 	flagEmailFrom      string | 	flagEmailFrom      string | ||||||
| 	flagEmailFromName  string = "WireGuard UI" | 	flagEmailFromName  string = "WireGuard UI" | ||||||
|  | @ -45,6 +51,12 @@ func init() { | ||||||
| 	// command-line flags and env variables
 | 	// command-line flags and env variables
 | ||||||
| 	flag.BoolVar(&flagDisableLogin, "disable-login", util.LookupEnvOrBool("DISABLE_LOGIN", flagDisableLogin), "Disable authentication on the app. This is potentially dangerous.") | 	flag.BoolVar(&flagDisableLogin, "disable-login", util.LookupEnvOrBool("DISABLE_LOGIN", flagDisableLogin), "Disable authentication on the app. This is potentially dangerous.") | ||||||
| 	flag.StringVar(&flagBindAddress, "bind-address", util.LookupEnvOrString("BIND_ADDRESS", flagBindAddress), "Address:Port to which the app will be bound.") | 	flag.StringVar(&flagBindAddress, "bind-address", util.LookupEnvOrString("BIND_ADDRESS", flagBindAddress), "Address:Port to which the app will be bound.") | ||||||
|  | 	flag.StringVar(&flagSmtpHostname, "smtp-hostname", util.LookupEnvOrString("SMTP_HOSTNAME", flagSmtpHostname), "SMTP Hostname") | ||||||
|  | 	flag.IntVar(&flagSmtpPort, "smtp-port", util.LookupEnvOrInt("SMTP_PORT", flagSmtpPort), "SMTP Port") | ||||||
|  | 	flag.StringVar(&flagSmtpUsername, "smtp-username", util.LookupEnvOrString("SMTP_USERNAME", flagSmtpUsername), "SMTP Password") | ||||||
|  | 	flag.StringVar(&flagSmtpPassword, "smtp-password", util.LookupEnvOrString("SMTP_PASSWORD", flagSmtpPassword), "SMTP Password") | ||||||
|  | 	flag.BoolVar(&flagSmtpNoTLSCheck, "smtp-no-tls-check", util.LookupEnvOrBool("SMTP_NO_TLS_CHECK", flagSmtpNoTLSCheck), "Disable TLS verification for SMTP. This is potentially dangerous.") | ||||||
|  | 	flag.StringVar(&flagSmtpAuthType, "smtp-auth-type", util.LookupEnvOrString("SMTP_AUTH_TYPE", flagSmtpAuthType), "SMTP Auth Type : Plain or None.") | ||||||
| 	flag.StringVar(&flagSendgridApiKey, "sendgrid-api-key", util.LookupEnvOrString("SENDGRID_API_KEY", flagSendgridApiKey), "Your sendgrid api key.") | 	flag.StringVar(&flagSendgridApiKey, "sendgrid-api-key", util.LookupEnvOrString("SENDGRID_API_KEY", flagSendgridApiKey), "Your sendgrid api key.") | ||||||
| 	flag.StringVar(&flagEmailFrom, "email-from", util.LookupEnvOrString("EMAIL_FROM_ADDRESS", flagEmailFrom), "'From' email address.") | 	flag.StringVar(&flagEmailFrom, "email-from", util.LookupEnvOrString("EMAIL_FROM_ADDRESS", flagEmailFrom), "'From' email address.") | ||||||
| 	flag.StringVar(&flagEmailFromName, "email-from-name", util.LookupEnvOrString("EMAIL_FROM_NAME", flagEmailFromName), "'From' email name.") | 	flag.StringVar(&flagEmailFromName, "email-from-name", util.LookupEnvOrString("EMAIL_FROM_NAME", flagEmailFromName), "'From' email name.") | ||||||
|  | @ -54,6 +66,12 @@ func init() { | ||||||
| 	// update runtime config
 | 	// update runtime config
 | ||||||
| 	util.DisableLogin = flagDisableLogin | 	util.DisableLogin = flagDisableLogin | ||||||
| 	util.BindAddress = flagBindAddress | 	util.BindAddress = flagBindAddress | ||||||
|  | 	util.SmtpHostname = flagSmtpHostname | ||||||
|  | 	util.SmtpPort = flagSmtpPort | ||||||
|  | 	util.SmtpUsername = flagSmtpUsername | ||||||
|  | 	util.SmtpPassword = flagSmtpPassword | ||||||
|  | 	util.SmtpAuthType = flagSmtpAuthType | ||||||
|  | 	util.SmtpNoTLSCheck = flagSmtpNoTLSCheck | ||||||
| 	util.SendgridApiKey = flagSendgridApiKey | 	util.SendgridApiKey = flagSendgridApiKey | ||||||
| 	util.EmailFrom = flagEmailFrom | 	util.EmailFrom = flagEmailFrom | ||||||
| 	util.EmailFromName = flagEmailFromName | 	util.EmailFromName = flagEmailFromName | ||||||
|  | @ -103,7 +121,12 @@ func main() { | ||||||
| 		app.POST("/login", handler.Login(db)) | 		app.POST("/login", handler.Login(db)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sendmail := emailer.NewSendgridApiMail(util.SendgridApiKey, util.EmailFromName, util.EmailFrom) | 	var sendmail emailer.Emailer | ||||||
|  | 	if util.SendgridApiKey != "" { | ||||||
|  | 		sendmail = emailer.NewSendgridApiMail(util.SendgridApiKey, util.EmailFromName, util.EmailFrom) | ||||||
|  | 	} else { | ||||||
|  | 		sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	app.GET("/_health", handler.Health()) | 	app.GET("/_health", handler.Health()) | ||||||
| 	app.GET("/logout", handler.Logout(), handler.ValidSession) | 	app.GET("/logout", handler.Logout(), handler.ValidSession) | ||||||
|  |  | ||||||
|  | @ -4,6 +4,12 @@ package util | ||||||
| var ( | var ( | ||||||
| 	DisableLogin   bool | 	DisableLogin   bool | ||||||
| 	BindAddress    string | 	BindAddress    string | ||||||
|  | 	SmtpHostname   string | ||||||
|  | 	SmtpPort       int | ||||||
|  | 	SmtpUsername   string | ||||||
|  | 	SmtpPassword   string | ||||||
|  | 	SmtpNoTLSCheck bool | ||||||
|  | 	SmtpAuthType   string | ||||||
| 	SendgridApiKey string | 	SendgridApiKey string | ||||||
| 	EmailFrom      string | 	EmailFrom      string | ||||||
| 	EmailFromName  string | 	EmailFromName  string | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue