Merge pull request #5 from wiggin77/auth

add LOGIN auth support
This commit is contained in:
Doug Lauder 2020-05-17 00:17:07 -04:00 committed by GitHub
commit 73a784ff65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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": [
"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.
`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
@ -43,6 +43,7 @@ On local PC (192.168.1.54) create file `/etc/mailrelay.json` with contents:
"smtp_starttls": false,
"smtp_username": "username@fastmail.com",
"smtp_password": "secretAppPassword",
"smtp_login_auth_type": false,
"local_listen_ip": "0.0.0.0",
"local_listen_port": 2525,
"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.
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
@ -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 {
@ -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")
}
@ -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 {
@ -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)
}
}
@ -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
go.mod
View File

@ -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
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/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=

View File

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

40
main.go
View File

@ -15,14 +15,16 @@ import (
var Logger log.Logger
type mailRelayConfig struct {
SMTPServer string `json:"smtp_server"`
SMTPPort int `json:"smtp_port"`
SMTPStartTLS bool `json:"smtp_starttls"`
SMTPUsername string `json:"smtp_username"`
SMTPPassword string `json:"smtp_password"`
LocalListenIP string `json:"local_listen_ip"`
LocalListenPort int `json:"local_listen_port"`
AllowedHosts []string `json:"allowed_hosts"`
SMTPServer string `json:"smtp_server"`
SMTPPort int `json:"smtp_port"`
SMTPStartTLS bool `json:"smtp_starttls"`
SMTPLoginAuthType bool `json:"smtp_login_auth_type"`
SMTPUsername string `json:"smtp_username"`
SMTPPassword string `json:"smtp_password"`
SkipCertVerify bool `json:"smtp_skip_cert_verify"`
LocalListenIP string `json:"local_listen_ip"`
LocalListenPort int `json:"local_listen_port"`
AllowedHosts []string `json:"allowed_hosts"`
}
func main() {
@ -114,18 +116,18 @@ func sendTest(sender string, rcpt string, port int) error {
return err
}
writeBody := func(c *smtp.Client) 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)
if err := writeBody(conn, sender); err != nil {
return err
}
if err := writeBody(conn); err != nil {
return err
}
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"
)
const saveWorkersSize = 3
// Start starts the server.
func Start(appConfig *mailRelayConfig, verbose bool) (err error) {
listen := fmt.Sprintf("%s:%d", appConfig.LocalListenIP, appConfig.LocalListenPort)
logLevel := "info"
@ -31,15 +32,17 @@ func Start(appConfig *mailRelayConfig, verbose bool) (err error) {
cfg.Servers = append(cfg.Servers, sc)
bcfg := backends.BackendConfig{
"save_workers_size": 3,
"save_process": "HeadersParser|Header|Hasher|Debugger|MailRelay",
"log_received_mails": true,
"primary_mail_host": "homeoffice.com",
"smtp_username": appConfig.SMTPUsername,
"smtp_password": appConfig.SMTPPassword,
"smtp_server": appConfig.SMTPServer,
"smtp_port": appConfig.SMTPPort,
"smtp_starttls": appConfig.SMTPStartTLS,
"save_workers_size": saveWorkersSize,
"save_process": "HeadersParser|Header|Hasher|Debugger|MailRelay",
"log_received_mails": true,
"primary_mail_host": "homeoffice.com",
"smtp_username": appConfig.SMTPUsername,
"smtp_password": appConfig.SMTPPassword,
"smtp_server": appConfig.SMTPServer,
"smtp_port": appConfig.SMTPPort,
"smtp_starttls": appConfig.SMTPStartTLS,
"smtp_login_auth_type": appConfig.SMTPLoginAuthType,
"smtp_skip_cert_verify": appConfig.SkipCertVerify,
}
cfg.BackendConfig = bcfg
@ -50,11 +53,13 @@ func Start(appConfig *mailRelayConfig, verbose bool) (err error) {
}
type relayConfig struct {
SMTPServer string `json:"smtp_server"`
SMTPPort int `json:"smtp_port"`
STARTTLS bool `json:"smtp_starttls"`
SMTPUsername string `json:"smtp_username"`
SMTPPassword string `json:"smtp_password"`
Server string `json:"smtp_server"`
Port int `json:"smtp_port"`
STARTTLS bool `json:"smtp_starttls"`
LoginAuthType bool `json:"smtp_login_auth_type"`
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.