smtp: add debug option
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
a2fc7d3cc5
commit
8339fee69d
10 changed files with 101 additions and 17 deletions
|
@ -457,6 +457,7 @@ The configuration file contains the following sections:
|
|||
- `encryption`, integer. 0 means no encryption, 1 means `TLS`, 2 means `STARTTLS`. Default: `0`.
|
||||
- `domain`, string. Domain to use for `HELO` command, if empty `localhost` will be used. Default: blank.
|
||||
- `templates_path`, string. Path to the email templates. This can be an absolute path or a path relative to the config dir. Templates are searched within a subdirectory named "email" in the specified path. You can customize the email templates by simply specifying an alternate path and putting your custom templates there.
|
||||
- `debug`, integer. Set to `1` to enable SMTP debug. Default: `0`.
|
||||
|
||||
</details>
|
||||
<details><summary><font size=4>Plugins</font></summary>
|
||||
|
|
10
go.mod
10
go.mod
|
@ -25,7 +25,7 @@ require (
|
|||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
|
||||
github.com/fclairamb/ftpserverlib v0.21.0
|
||||
github.com/fclairamb/go-log v0.4.1
|
||||
github.com/go-acme/lego/v4 v4.11.0
|
||||
github.com/go-acme/lego/v4 v4.12.0
|
||||
github.com/go-chi/chi/v5 v5.0.8
|
||||
github.com/go-chi/jwtauth/v5 v5.1.0
|
||||
github.com/go-chi/render v1.0.2
|
||||
|
@ -145,7 +145,7 @@ require (
|
|||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
|
@ -160,9 +160,9 @@ require (
|
|||
golang.org/x/tools v0.9.1 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230526015343-6ee61e4f9d5f // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230526015343-6ee61e4f9d5f // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526015343-6ee61e4f9d5f // indirect
|
||||
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e // indirect
|
||||
google.golang.org/grpc v1.55.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
|
|
20
go.sum
20
go.sum
|
@ -951,8 +951,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
|||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/go-acme/lego/v4 v4.11.0 h1:oIPoU7zBJoTfoVrbqk62+/2NsGCSgCVK1JtZSZZ28SU=
|
||||
github.com/go-acme/lego/v4 v4.11.0/go.mod h1:dENL0J3/WughN2NLy0T35otK5k1EWCmXTwCw0+X5ZaE=
|
||||
github.com/go-acme/lego/v4 v4.12.0 h1:jox3II6YRjt1EXvrymSQuSNgEUOcbUkF2je0kyuv6YM=
|
||||
github.com/go-acme/lego/v4 v4.12.0/go.mod h1:UZoOlhVmUYP/N0z4tEbfUjoCNHRZNObzqWZtT76DIsc=
|
||||
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
||||
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/jwtauth/v5 v5.1.0 h1:wJyf2YZ/ohPvNJBwPOzZaQbyzwgMZZceE1m8FOzXLeA=
|
||||
|
@ -1799,8 +1799,8 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
|||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/prometheus/procfs v0.10.0 h1:UkG7GPYkO4UZyLnyXjaWYcgOSONqwdBqFUT95ugmt6I=
|
||||
github.com/prometheus/procfs v0.10.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
||||
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
|
||||
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
||||
github.com/prometheus/prometheus v0.35.0/go.mod h1:7HaLx5kEPKJ0GDgbODG0fZgXbQ8K/XjZNJXQmbmgQlY=
|
||||
github.com/prometheus/prometheus v0.42.0/go.mod h1:Pfqb/MLnnR2KK+0vchiaH39jXxvLMBk+3lnIGP4N7Vk=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
|
@ -2816,12 +2816,12 @@ google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ
|
|||
google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20230526015343-6ee61e4f9d5f h1:DwRdHa3+SynqBR2tx3LVtzJrGooL9hg1OCAfBdQAk1A=
|
||||
google.golang.org/genproto v0.0.0-20230526015343-6ee61e4f9d5f/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230526015343-6ee61e4f9d5f h1:dJhNU2ZodW2tHjMhmDOrcRSahqR0wgfOEBs8nSmVx5Y=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230526015343-6ee61e4f9d5f/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526015343-6ee61e4f9d5f h1:QNVuVEP2S7NNxLdNdOq0RiW3c9pW4gIpUUd+GAOjk1Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526015343-6ee61e4f9d5f/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw=
|
||||
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e h1:AZX1ra8YbFMSb7+1pI8S9v4rrgRR7jU1FmuFSSjTVcQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e h1:NumxXLPfHSndr3wBBdeKiVHjGVFzi9RX2HwwQke94iY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
|
|
|
@ -50,6 +50,7 @@ If the SMTP configuration is correct you should receive this email.`,
|
|||
os.Exit(1)
|
||||
}
|
||||
smtpConfig := config.GetSMTPConfig()
|
||||
smtpConfig.Debug = 1
|
||||
err = smtpConfig.Initialize(configDir, false)
|
||||
if err != nil {
|
||||
logger.ErrorToConsole("unable to initialize SMTP configuration: %v", err)
|
||||
|
|
|
@ -152,6 +152,7 @@ type SMTPConfigs struct {
|
|||
AuthType int `json:"auth_type,omitempty"`
|
||||
Encryption int `json:"encryption,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Debug int `json:"debug,omitempty"`
|
||||
}
|
||||
|
||||
func (c *SMTPConfigs) isEmpty() bool {
|
||||
|
@ -215,6 +216,7 @@ func (c *SMTPConfigs) getACopy() *SMTPConfigs {
|
|||
AuthType: c.AuthType,
|
||||
Encryption: c.Encryption,
|
||||
Domain: c.Domain,
|
||||
Debug: c.Debug,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2635,6 +2635,10 @@ func getSMTPConfigsFromPostFields(r *http.Request) *dataprovider.SMTPConfigs {
|
|||
if err != nil {
|
||||
encryption = 0
|
||||
}
|
||||
debug := 0
|
||||
if r.Form.Get("smtp_debug") != "" {
|
||||
debug = 1
|
||||
}
|
||||
return &dataprovider.SMTPConfigs{
|
||||
Host: r.Form.Get("smtp_host"),
|
||||
Port: port,
|
||||
|
@ -2644,6 +2648,7 @@ func getSMTPConfigsFromPostFields(r *http.Request) *dataprovider.SMTPConfigs {
|
|||
AuthType: authType,
|
||||
Encryption: encryption,
|
||||
Domain: r.Form.Get("smtp_domain"),
|
||||
Debug: debug,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
48
internal/logger/mail.go
Normal file
48
internal/logger/mail.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Copyright (C) 2019-2023 Nicola Murino
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package logger
|
||||
|
||||
const (
|
||||
mailLogSender = "smtpclient"
|
||||
)
|
||||
|
||||
// MailAdapter is an adapter for mail.Logger
|
||||
type MailAdapter struct {
|
||||
ConnectionID string
|
||||
}
|
||||
|
||||
// Errorf emits a log at Error level
|
||||
func (l *MailAdapter) Errorf(format string, v ...any) {
|
||||
ErrorToConsole(format, v...)
|
||||
Log(LevelError, mailLogSender, l.ConnectionID, format, v...)
|
||||
}
|
||||
|
||||
// Warnf emits a log at Warn level
|
||||
func (l *MailAdapter) Warnf(format string, v ...any) {
|
||||
WarnToConsole(format, v...)
|
||||
Log(LevelWarn, mailLogSender, l.ConnectionID, format, v...)
|
||||
}
|
||||
|
||||
// Infof emits a log at Info level
|
||||
func (l *MailAdapter) Infof(format string, v ...any) {
|
||||
InfoToConsole(format, v...)
|
||||
Log(LevelInfo, mailLogSender, l.ConnectionID, format, v...)
|
||||
}
|
||||
|
||||
// Debugf emits a log at Debug level
|
||||
func (l *MailAdapter) Debugf(format string, v ...any) {
|
||||
DebugToConsole(format, v...)
|
||||
Log(LevelDebug, mailLogSender, l.ConnectionID, format, v...)
|
||||
}
|
|
@ -25,6 +25,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/xid"
|
||||
"github.com/wneessen/go-mail"
|
||||
|
||||
"github.com/drakkan/sftpgo/v2/internal/dataprovider"
|
||||
|
@ -83,6 +84,7 @@ func (c *activeConfig) Set(cfg *dataprovider.SMTPConfigs) {
|
|||
AuthType: cfg.AuthType,
|
||||
Encryption: cfg.Encryption,
|
||||
Domain: cfg.Domain,
|
||||
Debug: cfg.Debug,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,6 +169,8 @@ type Config struct {
|
|||
// Path to the email templates. This can be an absolute path or a path relative to the config dir.
|
||||
// Templates are searched within a subdirectory named "email" in the specified path
|
||||
TemplatesPath string `json:"templates_path" mapstructure:"templates_path"`
|
||||
// Set to 1 to enable debug logs
|
||||
Debug int `json:"debug" mapstructure:"debug"`
|
||||
}
|
||||
|
||||
func (c *Config) isEqual(other *Config) bool {
|
||||
|
@ -194,6 +198,9 @@ func (c *Config) isEqual(other *Config) bool {
|
|||
if c.Domain != other.Domain {
|
||||
return false
|
||||
}
|
||||
if c.Debug != other.Debug {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -283,6 +290,13 @@ func (c *Config) getMailClientOptions() []mail.Option {
|
|||
if c.Domain != "" {
|
||||
options = append(options, mail.WithHELO(c.Domain))
|
||||
}
|
||||
if c.Debug > 0 {
|
||||
options = append(options,
|
||||
mail.WithLogger(&logger.MailAdapter{
|
||||
ConnectionID: xid.New().String(),
|
||||
}),
|
||||
mail.WithDebugLog())
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
|
|
|
@ -406,7 +406,8 @@
|
|||
"auth_type": 0,
|
||||
"encryption": 0,
|
||||
"domain": "",
|
||||
"templates_path": "templates"
|
||||
"templates_path": "templates",
|
||||
"debug": 0
|
||||
},
|
||||
"plugins": []
|
||||
}
|
|
@ -275,6 +275,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="idSMTPDebug" name="smtp_debug"
|
||||
{{if gt .Configs.SMTP.Debug 0}}checked{{end}}>
|
||||
<label for="idSMTPDebug" class="form-check-label">Debug logs</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-12">
|
||||
<div class="input-group">
|
||||
|
@ -352,6 +360,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
$('#smtpTestResultModal').modal('show');
|
||||
return;
|
||||
}
|
||||
let debug = 0;
|
||||
if ($('#idSMTPDebug').is(':checked')){
|
||||
debug = 1;
|
||||
}
|
||||
$('#smtpSuccessMsg').hide();
|
||||
$('#smtpErrorMsg').hide();
|
||||
showSpinner();
|
||||
|
@ -360,7 +372,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
url: "{{.ConfigsURL}}/smtp/test",
|
||||
type: 'POST',
|
||||
headers: {'X-CSRF-TOKEN' : '{{.CSRFToken}}'},
|
||||
data: JSON.stringify({"host": $('#idSMTPHost').val(),"port": parseInt($('#idSMTPPort').val()),"from": $('#idSMTPFrom').val(),"user": $('#idSMTPUsername').val(),"password": $('#idSMTPPassword').val(),"auth_type": parseInt($('#idSMTPAuth').val()),"encryption": parseInt($('#idSMTPEncryption').val()), "domain": $('#idSMTPDomain').val(),"recipient": recipient}),
|
||||
data: JSON.stringify({"host": $('#idSMTPHost').val(),"port": parseInt($('#idSMTPPort').val()),"from": $('#idSMTPFrom').val(),"user": $('#idSMTPUsername').val(),"password": $('#idSMTPPassword').val(),"auth_type": parseInt($('#idSMTPAuth').val()),"encryption": parseInt($('#idSMTPEncryption').val()), "domain": $('#idSMTPDomain').val(),"debug": debug, "recipient": recipient}),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
timeout: 15000,
|
||||
|
|
Loading…
Reference in a new issue