This commit is contained in:
Winni Neessen 2022-03-09 13:20:01 +01:00
parent 82bb87ea4f
commit 4b4c8065f6
Signed by: wneessen
GPG key ID: 385AC9889632126E
4 changed files with 55 additions and 24 deletions

8
.idea/.gitignore vendored
View file

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettings">
<enabledExtensions>
<entry key="MermaidLanguageExtension" value="false" />
<entry key="PlantUMLLanguageExtension" value="false" />
</enabledExtensions>
</component>
</project>

View file

@ -40,6 +40,9 @@ type Client struct {
// HELO/EHLO string for the greeting the target SMTP server // HELO/EHLO string for the greeting the target SMTP server
helo string helo string
// enc indicates if a Client connection is encrypted or not
enc bool
// The SMTP client that is set up when using the Dial*() methods // The SMTP client that is set up when using the Dial*() methods
sc *smtp.Client sc *smtp.Client
} }
@ -55,9 +58,9 @@ var (
// NewClient returns a new Session client object // NewClient returns a new Session client object
func NewClient(h string, o ...Option) (*Client, error) { func NewClient(h string, o ...Option) (*Client, error) {
c := &Client{ c := &Client{
cto: DefaultTimeout,
host: h, host: h,
port: DefaultPort, port: DefaultPort,
cto: DefaultTimeout,
tlspolicy: TLSMandatory, tlspolicy: TLSMandatory,
tlsconfig: &tls.Config{ServerName: h}, tlsconfig: &tls.Config{ServerName: h},
} }
@ -112,6 +115,20 @@ func WithHELO(h string) Option {
} }
} }
// WithTLSPolicy tells the client to use the provided TLSPolicy
func WithTLSPolicy(p TLSPolicy) Option {
return func(c *Client) {
c.tlspolicy = p
}
}
// WithTLSConfig tells the client to use the provided *tls.Config
func WithTLSConfig(co *tls.Config) Option {
return func(c *Client) {
c.tlsconfig = co
}
}
// TLSPolicy returns the currently set TLSPolicy as string // TLSPolicy returns the currently set TLSPolicy as string
func (c *Client) TLSPolicy() string { func (c *Client) TLSPolicy() string {
return fmt.Sprintf("%s", c.tlspolicy) return fmt.Sprintf("%s", c.tlspolicy)
@ -127,6 +144,11 @@ func (c *Client) SetTLSPolicy(p TLSPolicy) {
c.tlspolicy = p c.tlspolicy = p
} }
// SetTLSConfig overrides the current *tls.Config with the given *tls.Config value
func (c *Client) SetTLSConfig(co *tls.Config) {
c.tlsconfig = co
}
// Send sends out the mail message // Send sends out the mail message
func (c *Client) Send() error { func (c *Client) Send() error {
return nil return nil
@ -163,6 +185,7 @@ func (c *Client) DialWithContext(uctx context.Context) error {
var co net.Conn var co net.Conn
var err error var err error
if c.ssl { if c.ssl {
c.enc = true
co, err = td.DialContext(ctx, "tcp", c.ServerAddr()) co, err = td.DialContext(ctx, "tcp", c.ServerAddr())
} }
if !c.ssl { if !c.ssl {
@ -181,13 +204,26 @@ func (c *Client) DialWithContext(uctx context.Context) error {
} }
if !c.ssl && c.tlspolicy != NoTLS { if !c.ssl && c.tlspolicy != NoTLS {
if ok, _ := c.sc.Extension("STARTTLS"); !ok { est := false
return fmt.Errorf("STARTTLS mode set to: %q, but target host does not support STARTTLS", st, _ := c.sc.Extension("STARTTLS")
c.tlspolicy) if c.tlspolicy == TLSMandatory {
est = true
if !st {
return fmt.Errorf("STARTTLS mode set to: %q, but target host does not support STARTTLS",
c.tlspolicy)
}
} }
if err := c.sc.StartTLS(c.tlsconfig); err != nil { if c.tlspolicy == TLSOpportunistic {
return err if st {
est = true
}
} }
if est {
if err := c.sc.StartTLS(c.tlsconfig); err != nil {
return err
}
}
_, c.enc = c.sc.TLSConnectionState()
} }
return nil return nil

View file

@ -2,6 +2,7 @@ package main
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"github.com/wneessen/go-mail" "github.com/wneessen/go-mail"
"os" "os"
@ -10,11 +11,22 @@ import (
func main() { func main() {
th := os.Getenv("TEST_HOST") th := os.Getenv("TEST_HOST")
c, err := mail.NewClient(th, mail.WithTimeout(time.Millisecond*500)) if th == "" {
fmt.Printf("$TEST_HOST env variable cannot be empty\n")
os.Exit(1)
}
c, err := mail.NewClient(th, mail.WithTimeout(time.Millisecond*500), mail.WithTLSPolicy(mail.TLSOpportunistic))
if err != nil { if err != nil {
fmt.Printf("failed to create new client: %s\n", err) fmt.Printf("failed to create new client: %s\n", err)
os.Exit(1) os.Exit(1)
} }
//c.SetTLSPolicy(mail.TLSMandatory)
tc := &tls.Config{
ServerName: th,
MinVersion: tls.VersionTLS10,
MaxVersion: tls.VersionTLS10,
}
c.SetTLSConfig(tc)
ctx, cfn := context.WithCancel(context.Background()) ctx, cfn := context.WithCancel(context.Background())
defer cfn() defer cfn()