Skip to content

Commit

Permalink
Merge pull request #5 from wiggin77/auth
Browse files Browse the repository at this point in the history
add LOGIN auth support
  • Loading branch information
wiggin77 authored May 17, 2020
2 parents 93a5fc6 + 5f58b03 commit 73a784f
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 100 deletions.
73 changes: 73 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -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

5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"cSpell.words": [
"myname"
"myname",
"HELO",
"EHLO",
"gosec"
]
}
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

`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

`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.

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.

## Testing your configuration
Expand All @@ -43,6 +43,7 @@ On local PC (192.168.1.54) create file `/etc/mailrelay.json` with contents:
"smtp_starttls": false,
"smtp_username": "[email protected]",
"smtp_password": "secretAppPassword",
"smtp_login_auth_type": false,
"local_listen_ip": "0.0.0.0",
"local_listen_port": 2525,
"allowed_hosts": ["*"]
Expand Down
34 changes: 34 additions & 0 deletions auth.go
Original file line number Diff line number Diff line change
@@ -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
}
45 changes: 29 additions & 16 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type closeable interface {

// sendMail sends the contents of the envelope to a SMTP server.
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)

var msg bytes.Buffer
Expand All @@ -33,8 +33,8 @@ func sendMail(e *mail.Envelope, config *relayConfig) error {
var writer io.WriteCloser

tlsconfig := &tls.Config{
InsecureSkipVerify: true,
ServerName: config.SMTPServer,
InsecureSkipVerify: config.SkipVerify, //nolint:gosec
ServerName: config.Server,
}

if config.STARTTLS {
Expand All @@ -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")
return errors.Wrap(err, "newclient error")
}
Expand All @@ -58,15 +58,8 @@ func sendMail(e *mail.Envelope, config *relayConfig) error {
}
}(&shouldCloseClient)

if config.STARTTLS {
if err = client.StartTLS(tlsconfig); err != nil {
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 = handshake(client, config, tlsconfig); err != nil {
return err
}

if err = client.Mail(e.MailFrom.String()); err != nil {
Expand Down Expand Up @@ -98,10 +91,30 @@ func sendMail(e *mail.Envelope, config *relayConfig) error {
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) {
err := c.Close()
if err != nil {
fmt.Printf("!!!!! Error closing %s: %v\n", what, err)
fmt.Printf("Error closing %s: %v\n", what, err)
}
}

Expand All @@ -122,8 +135,8 @@ func isQuitError(err error) bool {
// getTo returns the array of email addresses in the envelope.
func getTo(e *mail.Envelope) []string {
var ret []string
for _, addy := range e.RcptTo {
ret = append(ret, addy.String())
for i := range e.RcptTo {
ret = append(ret, e.RcptTo[i].String())
}
return ret
}
14 changes: 7 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ require (
github.com/asaskevich/EventBus v0.0.0-20180103000110-68a521d7cbbb // indirect
github.com/flashmob/go-guerrilla v1.6.1
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/onsi/ginkgo v1.12.0 // indirect
github.com/onsi/gomega v1.10.0 // indirect
github.com/pkg/errors v0.8.0
github.com/sirupsen/logrus v1.0.5 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.6.0 // indirect
github.com/stretchr/testify v1.5.1 // indirect
golang.org/x/crypto v0.0.0-20181126163421-e657309f52e7 // indirect
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)
64 changes: 23 additions & 41 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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/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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/flashmob/go-guerrilla v0.0.0-20180822023650-1c628e503aed h1:vEVXJyIHYlQuQ/mU8+gL9xpn50OYgBsMpB/zr69aGFc=
github.com/flashmob/go-guerrilla v0.0.0-20180822023650-1c628e503aed/go.mod h1:ZT9TRggRsSY4ZVndoyx8TRUxi3tM/nOYtKWKDX94H0I=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
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/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/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.0 h1:Gwkk+PTu/nfOwNMtUB/mRUv0X7ewW5dO4AERT1ThVKo=
github.com/onsi/gomega v1.10.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
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/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
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/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/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
golang.org/x/crypto v0.0.0-20181126163421-e657309f52e7 h1:70UTJTdHsz+jRjphEW+is2SdxjhZL1AdKsewqjYzcQU=
golang.org/x/crypto v0.0.0-20181126163421-e657309f52e7/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
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=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 h1:YTzHMGlqJu67/uEo1lBv0n3wBXhXNeUbB1XfN2vmTm0=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
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/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
2 changes: 2 additions & 0 deletions mailrelay.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
"smtp_server": "smtp.fastmail.com",
"smtp_port": 465,
"smtp_starttls": false,
"smtp_login_auth_type": false,
"smtp_username": "[email protected]",
"smtp_password": "secret_app_password",
"smtp_skip_cert_verify": false,
"local_listen_port": 2525,
"local_listen_ip": "0.0.0.0",
"allowed_hosts": ["*"]
Expand Down
Loading

0 comments on commit 73a784f

Please sign in to comment.