add LOGIN auth support

This commit is contained in:
wiggin77 2020-05-17 00:15:49 -04:00
parent 93a5fc6ab9
commit 5f58b030c3
10 changed files with 216 additions and 101 deletions

73
.golangci.yml Normal file
View File

@ -0,0 +1,73 @@
linters-settings:
gocritic:
enabled-tags:
- diagnostic
- experimental
- performance
- style
disabled-checks:
- dupImport # https://github.com/go-critic/go-critic/issues/845
- ifElseChain
- octalLiteral
- whyNoLint
- wrapperFunc
govet:
check-shadowing: true
misspell:
locale: US
linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon.
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
disable-all: true
enable:
- bodyclose
- deadcode
- depguard
- dogsled
- dupl
- errcheck
# - funlen
- gochecknoinits
- goconst
# - gocritic
- gocyclo
- gofmt
- goimports
- golint
- gomnd
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
- interfacer
- lll
- misspell
- nakedret
# - nolintlint
- rowserrcheck
- scopelint
- staticcheck
- structcheck
- stylecheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
- whitespace
# don't enable:
# - asciicheck
# - gochecknoglobals
# - gocognit
# - godot
# - godox
# - goerr113
# - maligned
# - nestif
# - prealloc
# - testpackage
# - wsl

View File

@ -1,5 +1,8 @@
{ {
"cSpell.words": [ "cSpell.words": [
"myname" "myname",
"HELO",
"EHLO",
"gosec"
] ]
} }

View File

@ -12,14 +12,14 @@ Some older appliances such as scanners, multi-function printers, RAID cards or N
Run `mailrelay` on a local PC or server and set your device (e.g. scanner) to send mail to it. Run `mailrelay` on a local PC or server and set your device (e.g. scanner) to send mail to it.
`mailrelay` is written in Go, and can be compiled for any Go supported platform including Linux, MacOS, Windows. `mailrelay` can be compiled for any Go supported platform including Linux, MacOS, Windows.
## Encryption ## Encryption
`mailrelay` uses TLS to connect to your SMTP provider. By default implicit TLS connections are assumed, meaning the connection is established `mailrelay` uses TLS to connect to your SMTP provider. By default implicit TLS connections are assumed, meaning the connection is established
using TLS at the socket level. This is in accordance with [RFC 8314 section 3](https://tools.ietf.org/html/rfc8314#section-3). These connections usually use port 465. using TLS at the socket level. This is in accordance with [RFC 8314 section 3](https://tools.ietf.org/html/rfc8314#section-3). These connections usually use port 465.
However, some providers do not adhere to this recommendation (I'm looking at you Office365!) and only support the legacy STARTTLS command, which expects a non-encrypted socket connection at first, which is then upgraded to TLS. To enable this, set `smtp_starttls` to `true` in your config. However, some providers do not adhere to this recommendation (I'm looking at you Office365!) and only support the legacy STARTTLS command, which expects a non-encrypted socket connection at first, which is then upgraded to TLS. To enable this, set `smtp_starttls` to `true` in your config. You may also need to set `smtp_login_auth_type` to `true` which enables the legacy [LOGIN authentication](https://www.ietf.org/archive/id/draft-murchison-sasl-login-00.txt) method.
These connections usually use port 587. These connections usually use port 587.
## Testing your configuration ## Testing your configuration
@ -43,6 +43,7 @@ On local PC (192.168.1.54) create file `/etc/mailrelay.json` with contents:
"smtp_starttls": false, "smtp_starttls": false,
"smtp_username": "username@fastmail.com", "smtp_username": "username@fastmail.com",
"smtp_password": "secretAppPassword", "smtp_password": "secretAppPassword",
"smtp_login_auth_type": false,
"local_listen_ip": "0.0.0.0", "local_listen_ip": "0.0.0.0",
"local_listen_port": 2525, "local_listen_port": 2525,
"allowed_hosts": ["*"] "allowed_hosts": ["*"]

34
auth.go Normal file
View File

@ -0,0 +1,34 @@
package main
import (
"fmt"
"net/smtp"
)
type loginAuth struct {
username, password string
}
// LoginAuth provides a simple implementation of LOGIN authorization of SMTP as
// described here: https://www.ietf.org/archive/id/draft-murchison-sasl-login-00.txt
func LoginAuth(username, password string) smtp.Auth {
return &loginAuth{username, password}
}
func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
return "LOGIN", []byte{}, nil
}
func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
if more {
switch string(fromServer) {
case "User Name", "Username:":
return []byte(a.username), nil
case "Password", "Password:":
return []byte(a.password), nil
default:
return nil, fmt.Errorf("unknown server response \"%s\"", string(fromServer))
}
}
return nil, nil
}

View File

@ -19,7 +19,7 @@ type closeable interface {
// sendMail sends the contents of the envelope to a SMTP server. // sendMail sends the contents of the envelope to a SMTP server.
func sendMail(e *mail.Envelope, config *relayConfig) error { func sendMail(e *mail.Envelope, config *relayConfig) error {
server := fmt.Sprintf("%s:%d", config.SMTPServer, config.SMTPPort) server := fmt.Sprintf("%s:%d", config.Server, config.Port)
to := getTo(e) to := getTo(e)
var msg bytes.Buffer var msg bytes.Buffer
@ -33,8 +33,8 @@ func sendMail(e *mail.Envelope, config *relayConfig) error {
var writer io.WriteCloser var writer io.WriteCloser
tlsconfig := &tls.Config{ tlsconfig := &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: config.SkipVerify, //nolint:gosec
ServerName: config.SMTPServer, ServerName: config.Server,
} }
if config.STARTTLS { if config.STARTTLS {
@ -47,7 +47,7 @@ func sendMail(e *mail.Envelope, config *relayConfig) error {
} }
} }
if client, err = smtp.NewClient(conn, config.SMTPServer); err != nil { if client, err = smtp.NewClient(conn, config.Server); err != nil {
close(conn, "conn") close(conn, "conn")
return errors.Wrap(err, "newclient error") return errors.Wrap(err, "newclient error")
} }
@ -58,15 +58,8 @@ func sendMail(e *mail.Envelope, config *relayConfig) error {
} }
}(&shouldCloseClient) }(&shouldCloseClient)
if config.STARTTLS { if err = handshake(client, config, tlsconfig); err != nil {
if err = client.StartTLS(tlsconfig); err != nil { return err
return errors.Wrap(err, "starttls error")
}
}
auth := smtp.PlainAuth("", config.SMTPUsername, config.SMTPPassword, config.SMTPServer)
if err = client.Auth(auth); err != nil {
return errors.Wrap(err, "auth error")
} }
if err = client.Mail(e.MailFrom.String()); err != nil { if err = client.Mail(e.MailFrom.String()); err != nil {
@ -98,10 +91,30 @@ func sendMail(e *mail.Envelope, config *relayConfig) error {
return nil return nil
} }
func handshake(client *smtp.Client, config *relayConfig, tlsConfig *tls.Config) error {
if config.STARTTLS {
if err := client.StartTLS(tlsConfig); err != nil {
return errors.Wrap(err, "starttls error")
}
}
var auth smtp.Auth
if config.LoginAuthType {
auth = LoginAuth(config.Username, config.Password)
} else {
auth = smtp.PlainAuth("", config.Username, config.Password, config.Server)
}
if err := client.Auth(auth); err != nil {
return errors.Wrap(err, "auth error")
}
return nil
}
func close(c closeable, what string) { func close(c closeable, what string) {
err := c.Close() err := c.Close()
if err != nil { if err != nil {
fmt.Printf("!!!!! Error closing %s: %v\n", what, err) fmt.Printf("Error closing %s: %v\n", what, err)
} }
} }
@ -122,8 +135,8 @@ func isQuitError(err error) bool {
// getTo returns the array of email addresses in the envelope. // getTo returns the array of email addresses in the envelope.
func getTo(e *mail.Envelope) []string { func getTo(e *mail.Envelope) []string {
var ret []string var ret []string
for _, addy := range e.RcptTo { for i := range e.RcptTo {
ret = append(ret, addy.String()) ret = append(ret, e.RcptTo[i].String())
} }
return ret return ret
} }

14
go.mod
View File

@ -6,12 +6,12 @@ require (
github.com/asaskevich/EventBus v0.0.0-20180103000110-68a521d7cbbb // indirect github.com/asaskevich/EventBus v0.0.0-20180103000110-68a521d7cbbb // indirect
github.com/flashmob/go-guerrilla v1.6.1 github.com/flashmob/go-guerrilla v1.6.1
github.com/go-sql-driver/mysql v1.5.0 // indirect github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/onsi/ginkgo v1.12.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/onsi/gomega v1.10.0 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pkg/errors v0.8.0 github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.0.5 // indirect github.com/sirupsen/logrus v1.6.0 // indirect
github.com/stretchr/testify v1.5.1 // indirect github.com/stretchr/testify v1.5.1 // indirect
golang.org/x/crypto v0.0.0-20181126163421-e657309f52e7 // indirect golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 // indirect
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect
) )

64
go.sum
View File

@ -1,58 +1,40 @@
github.com/asaskevich/EventBus v0.0.0-20180103000110-68a521d7cbbb h1:UgErHX+sTKfxJ1+2IksfX2Jeb2DcSgWN0oqRTUzSg74= github.com/asaskevich/EventBus v0.0.0-20180103000110-68a521d7cbbb h1:UgErHX+sTKfxJ1+2IksfX2Jeb2DcSgWN0oqRTUzSg74=
github.com/asaskevich/EventBus v0.0.0-20180103000110-68a521d7cbbb/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII= github.com/asaskevich/EventBus v0.0.0-20180103000110-68a521d7cbbb/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/flashmob/go-guerrilla v0.0.0-20180822023650-1c628e503aed h1:vEVXJyIHYlQuQ/mU8+gL9xpn50OYgBsMpB/zr69aGFc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/flashmob/go-guerrilla v0.0.0-20180822023650-1c628e503aed/go.mod h1:ZT9TRggRsSY4ZVndoyx8TRUxi3tM/nOYtKWKDX94H0I= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/flashmob/go-guerrilla v1.6.1 h1:MLkqzRFUJveVAWuQ3s2MNPTAWbvXLt8EFsBoraS6qHA= github.com/flashmob/go-guerrilla v1.6.1 h1:MLkqzRFUJveVAWuQ3s2MNPTAWbvXLt8EFsBoraS6qHA=
github.com/flashmob/go-guerrilla v1.6.1/go.mod h1:ZT9TRggRsSY4ZVndoyx8TRUxi3tM/nOYtKWKDX94H0I= github.com/flashmob/go-guerrilla v1.6.1/go.mod h1:ZT9TRggRsSY4ZVndoyx8TRUxi3tM/nOYtKWKDX94H0I=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/gomega v1.10.0 h1:Gwkk+PTu/nfOwNMtUB/mRUv0X7ewW5dO4AERT1ThVKo= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/onsi/gomega v1.10.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
golang.org/x/crypto v0.0.0-20181126163421-e657309f52e7 h1:70UTJTdHsz+jRjphEW+is2SdxjhZL1AdKsewqjYzcQU= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/crypto v0.0.0-20181126163421-e657309f52e7/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 h1:YTzHMGlqJu67/uEo1lBv0n3wBXhXNeUbB1XfN2vmTm0=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -2,8 +2,10 @@
"smtp_server": "smtp.fastmail.com", "smtp_server": "smtp.fastmail.com",
"smtp_port": 465, "smtp_port": 465,
"smtp_starttls": false, "smtp_starttls": false,
"smtp_login_auth_type": false,
"smtp_username": "username@fastmail.com", "smtp_username": "username@fastmail.com",
"smtp_password": "secret_app_password", "smtp_password": "secret_app_password",
"smtp_skip_cert_verify": false,
"local_listen_port": 2525, "local_listen_port": 2525,
"local_listen_ip": "0.0.0.0", "local_listen_ip": "0.0.0.0",
"allowed_hosts": ["*"] "allowed_hosts": ["*"]

40
main.go
View File

@ -15,14 +15,16 @@ import (
var Logger log.Logger var Logger log.Logger
type mailRelayConfig struct { type mailRelayConfig struct {
SMTPServer string `json:"smtp_server"` SMTPServer string `json:"smtp_server"`
SMTPPort int `json:"smtp_port"` SMTPPort int `json:"smtp_port"`
SMTPStartTLS bool `json:"smtp_starttls"` SMTPStartTLS bool `json:"smtp_starttls"`
SMTPUsername string `json:"smtp_username"` SMTPLoginAuthType bool `json:"smtp_login_auth_type"`
SMTPPassword string `json:"smtp_password"` SMTPUsername string `json:"smtp_username"`
LocalListenIP string `json:"local_listen_ip"` SMTPPassword string `json:"smtp_password"`
LocalListenPort int `json:"local_listen_port"` SkipCertVerify bool `json:"smtp_skip_cert_verify"`
AllowedHosts []string `json:"allowed_hosts"` LocalListenIP string `json:"local_listen_ip"`
LocalListenPort int `json:"local_listen_port"`
AllowedHosts []string `json:"allowed_hosts"`
} }
func main() { func main() {
@ -114,18 +116,18 @@ func sendTest(sender string, rcpt string, port int) error {
return err return err
} }
writeBody := func(c *smtp.Client) error { if err := writeBody(conn, sender); err != nil {
wc, err := conn.Data()
if err != nil {
return err
}
defer wc.Close()
_, err = fmt.Fprintf(wc, "From: %s\nSubject: Test message\n\nThis is a test email from mailrelay.\n", sender)
return err return err
} }
if err := writeBody(conn); err != nil {
return err
}
return conn.Quit() return conn.Quit()
} }
func writeBody(conn *smtp.Client, sender string) error {
wc, err := conn.Data()
if err != nil {
return err
}
defer wc.Close()
_, err = fmt.Fprintf(wc, "From: %s\nSubject: Test message\n\nThis is a test email from mailrelay.\n", sender)
return err
}

View File

@ -9,9 +9,10 @@ import (
"github.com/flashmob/go-guerrilla/mail" "github.com/flashmob/go-guerrilla/mail"
) )
const saveWorkersSize = 3
// Start starts the server. // Start starts the server.
func Start(appConfig *mailRelayConfig, verbose bool) (err error) { func Start(appConfig *mailRelayConfig, verbose bool) (err error) {
listen := fmt.Sprintf("%s:%d", appConfig.LocalListenIP, appConfig.LocalListenPort) listen := fmt.Sprintf("%s:%d", appConfig.LocalListenIP, appConfig.LocalListenPort)
logLevel := "info" logLevel := "info"
@ -31,15 +32,17 @@ func Start(appConfig *mailRelayConfig, verbose bool) (err error) {
cfg.Servers = append(cfg.Servers, sc) cfg.Servers = append(cfg.Servers, sc)
bcfg := backends.BackendConfig{ bcfg := backends.BackendConfig{
"save_workers_size": 3, "save_workers_size": saveWorkersSize,
"save_process": "HeadersParser|Header|Hasher|Debugger|MailRelay", "save_process": "HeadersParser|Header|Hasher|Debugger|MailRelay",
"log_received_mails": true, "log_received_mails": true,
"primary_mail_host": "homeoffice.com", "primary_mail_host": "homeoffice.com",
"smtp_username": appConfig.SMTPUsername, "smtp_username": appConfig.SMTPUsername,
"smtp_password": appConfig.SMTPPassword, "smtp_password": appConfig.SMTPPassword,
"smtp_server": appConfig.SMTPServer, "smtp_server": appConfig.SMTPServer,
"smtp_port": appConfig.SMTPPort, "smtp_port": appConfig.SMTPPort,
"smtp_starttls": appConfig.SMTPStartTLS, "smtp_starttls": appConfig.SMTPStartTLS,
"smtp_login_auth_type": appConfig.SMTPLoginAuthType,
"smtp_skip_cert_verify": appConfig.SkipCertVerify,
} }
cfg.BackendConfig = bcfg cfg.BackendConfig = bcfg
@ -50,11 +53,13 @@ func Start(appConfig *mailRelayConfig, verbose bool) (err error) {
} }
type relayConfig struct { type relayConfig struct {
SMTPServer string `json:"smtp_server"` Server string `json:"smtp_server"`
SMTPPort int `json:"smtp_port"` Port int `json:"smtp_port"`
STARTTLS bool `json:"smtp_starttls"` STARTTLS bool `json:"smtp_starttls"`
SMTPUsername string `json:"smtp_username"` LoginAuthType bool `json:"smtp_login_auth_type"`
SMTPPassword string `json:"smtp_password"` Username string `json:"smtp_username"`
Password string `json:"smtp_password"`
SkipVerify bool `json:"smtp_skip_cert_verify"`
} }
// mailRelayProcessor decorator relays emails to another SMTP server. // mailRelayProcessor decorator relays emails to another SMTP server.