mirror of
https://github.com/wiggin77/mailrelay.git
synced 2024-11-25 00:23:09 +01:00
add LOGIN auth support
This commit is contained in:
parent
93a5fc6ab9
commit
5f58b030c3
73
.golangci.yml
Normal file
73
.golangci.yml
Normal 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
|
||||||
|
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"myname"
|
"myname",
|
||||||
|
"HELO",
|
||||||
|
"EHLO",
|
||||||
|
"gosec"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -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
34
auth.go
Normal 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
|
||||||
|
}
|
45
client.go
45
client.go
@ -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
14
go.mod
@ -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
64
go.sum
@ -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=
|
||||||
|
@ -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
40
main.go
@ -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
|
||||||
|
}
|
||||||
|
35
server.go
35
server.go
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user