Files
golib/smtp/config/interface.go
Nicolas JUHEL 984ba51587 Rework Error interface
Package Errors:
- add function to check & cast error interface into golib Error interface
- update CodeError type to simplify management & error creation
- add function to simplify call of Error function from a generic error interface
- remove some useless function from Error interface

All Other Packages:
- apply change of package Errors into all other packages
2023-08-28 11:22:08 +02:00

192 lines
4.6 KiB
Go

/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package config
import (
"net"
"net/url"
"strconv"
"strings"
"github.com/nabbar/golib/smtp/network"
smtptp "github.com/nabbar/golib/smtp/tlsmode"
libtls "github.com/nabbar/golib/certificates"
liberr "github.com/nabbar/golib/errors"
)
type SMTP interface {
GetHost() string
GetPort() int
GetUser() string
GetPass() string
GetNet() network.NetworkMode
GetTls() libtls.Config
GetTlSServerName() string
GetTlsMode() smtptp.TLSMode
SetTlsMode(mode smtptp.TLSMode)
IsTLSSkipVerify() bool
GetDsn() string
}
type Config interface {
SMTP
SetHost(host string)
SetPort(port int)
SetUser(user string)
SetPass(pass string)
SetNet(mode network.NetworkMode)
SetTls(tls libtls.Config)
ForceTLSSkipVerify(skip bool)
SetTLSServerName(serverName string)
}
// New parses the DSN string to a Config.
// nolint: gocognit
func New(cfg ConfigModel) (Config, liberr.Error) {
var (
dsn = cfg.DSN
smtpcnf = &smtpConfig{
DSN: dsn,
TLSCfg: cfg.TLS,
}
)
// [user[:password]@][net[(addr)]]/tlsmode[?param1=value1&paramN=valueN]
// Find the last '/' (since the password or the net addr might contain a '/')
if !strings.ContainsRune(dsn, '?') && !strings.ContainsRune(dsn, '/') {
dsn += "/"
} else if strings.ContainsRune(dsn, '?') && !strings.ContainsRune(dsn, '/') {
v := strings.Split(dsn, "?")
v[len(v)-2] += "/"
dsn = strings.Join(v, "?")
}
foundSlash := false
for i := len(dsn) - 1; i >= 0; i-- {
if dsn[i] == '/' {
foundSlash = true
var j, k int
// left part is empty if i <= 0
if i > 0 {
// [username[:password]@][protocol[(address)]]
// Find the last '@' in dsn[:i]
for j = i; j >= 0; j-- {
if dsn[j] == '@' {
// username[:password]
// Find the first ':' in dsn[:j]
for k = 0; k < j; k++ {
if dsn[k] == ':' {
smtpcnf.Pass = dsn[k+1 : j]
break
}
}
smtpcnf.User = dsn[:k]
break
}
}
// [protocol[(address)]]
// Find the first '(' in dsn[j+1:i]
for k = j + 1; k < i; k++ {
if dsn[k] == '(' {
// dsn[i-1] must be == ')' if an address is specified
if dsn[i-1] != ')' {
if strings.ContainsRune(dsn[k+1:i], ')') {
return nil, ErrorConfigInvalidDSN.Error(nil)
}
return nil, ErrorConfigInvalidNetwork.Error(nil)
}
if strings.ContainsRune(dsn[k+1:i-1], ':') {
h, p, e := net.SplitHostPort(dsn[k+1 : i-1])
if e == nil && p != "" {
pint, er := strconv.ParseInt(p, 10, 64)
if er == nil {
if pint <= 65535 {
smtpcnf.Port = int(pint)
}
}
smtpcnf.Host = h
}
}
if smtpcnf.Host == "" || smtpcnf.Port == 0 {
smtpcnf.Host = dsn[k+1 : i-1]
}
break
}
}
smtpcnf.Net = network.NetworkModeFromString(dsn[j+1 : k])
}
// [?param1=value1&...&paramN=valueN]
// Find the first '?' in dsn[i+1:]
for j = i + 1; j < len(dsn); j++ {
if dsn[j] == '?' {
if val, err := url.ParseQuery(dsn[j+1:]); err != nil {
return nil, ErrorConfigInvalidParams.Error(err)
} else {
if val.Get("ServerName") != "" {
smtpcnf.ServerName = val.Get("ServerName")
}
if val.Get("SkipVerify") != "" {
vi, e := strconv.ParseBool(val.Get("SkipVerify"))
if e == nil {
smtpcnf.SkipVerify = vi
}
}
}
break
}
}
smtpcnf.TLS = smtptp.TLSModeFromString(dsn[i+1 : j])
break
}
}
if !foundSlash && len(dsn) > 0 {
return nil, ErrorConfigInvalidHost.Error(nil)
}
return smtpcnf, nil
}