Bump github.com/xhit/go-simple-mail/v2 from 2.13.0 to 2.15.0

Bumps [github.com/xhit/go-simple-mail/v2](https://github.com/xhit/go-simple-mail) from 2.13.0 to 2.15.0.
- [Release notes](https://github.com/xhit/go-simple-mail/releases)
- [Commits](https://github.com/xhit/go-simple-mail/compare/v2.13.0...v2.15.0)

---
updated-dependencies:
- dependency-name: github.com/xhit/go-simple-mail/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2023-07-17 06:50:57 +00:00
committed by Ralf Haferkamp
parent 102e316361
commit ee2df8dc61
6 changed files with 210 additions and 74 deletions

2
go.mod
View File

@@ -78,7 +78,7 @@ require (
github.com/thejerf/suture/v4 v4.0.2
github.com/tus/tusd v1.10.1
github.com/urfave/cli/v2 v2.25.7
github.com/xhit/go-simple-mail/v2 v2.13.0
github.com/xhit/go-simple-mail/v2 v2.15.0
go-micro.dev/v4 v4.9.0
go.etcd.io/bbolt v1.3.7
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.1-0.20230608065455-5cc3715df180

4
go.sum
View File

@@ -1628,8 +1628,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xhit/go-simple-mail/v2 v2.13.0 h1:OANWU9jHZrVfBkNkvLf8Ww0fexwpQVF/v/5f96fFTLI=
github.com/xhit/go-simple-mail/v2 v2.13.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98=
github.com/xhit/go-simple-mail/v2 v2.15.0 h1:qMXeqcZErUW/Dw6EXxmPuxHzVI8MdxWnEnu2xcisohU=
github.com/xhit/go-simple-mail/v2 v2.15.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=

View File

@@ -25,4 +25,7 @@ _testmain.go
# Eclipse Project files
.project
.settings
.settings
# Go coverage file
coverage.txt

View File

@@ -69,6 +69,7 @@ Go Simple Mail supports:
- Add Custom Headers in Message
- Send NOOP, RESET, QUIT and CLOSE to SMTP client
- PLAIN, LOGIN and CRAM-MD5 Authentication (since v2.3.0)
- AUTO Authentication (since v2.14.0)
- Allow connect to SMTP without authentication (since v2.10.0)
- Custom TLS Configuration (since v2.5.0)
- Send a RFC822 formatted message (since v2.8.0)
@@ -76,12 +77,15 @@ Go Simple Mail supports:
- Support text/calendar content type body (since v2.11.0)
- Support add a List-Unsubscribe header (since v2.11.0)
- Support to add a DKIM signarure (since v2.11.0)
- Support to send using custom connection, ideal for proxy (since v2.15.0)
## Documentation
https://pkg.go.dev/github.com/xhit/go-simple-mail/v2?tab=doc
Note: by default duplicated recipients throws an error, from `v2.13.0` you can use `email.AllowDuplicateAddress = true` to avoid the check.
Note 1: by default duplicated recipients throws an error, from `v2.13.0` you can use `email.AllowDuplicateAddress = true` to avoid the check.
Note 2: by default Bcc header is not set in email. From `v2.14.0` you can use `email.AddBccToHeader = true` to add this.
## Download
@@ -99,7 +103,7 @@ package main
import (
"log"
"github.com/xhit/go-simple-mail/v2"
mail "github.com/xhit/go-simple-mail/v2"
"github.com/toorop/go-dkim"
)
@@ -153,12 +157,13 @@ func main() {
server.Password = "examplepass"
server.Encryption = mail.EncryptionSTARTTLS
// Since v2.3.0 you can specified authentication type:
// - PLAIN (default)
// You can specified authentication type:
// - AUTO (default)
// - PLAIN
// - LOGIN
// - CRAM-MD5
// - None
// server.Authentication = mail.AuthPlain
// server.Authentication = mail.AuthAuto
// Variable to keep alive connection
server.KeepAlive = false
@@ -265,6 +270,77 @@ func main() {
}
```
# Send with custom connection
It's possible to use a custom connection with custom dieler, like a dialer that uses a proxy server, etc...
With this, these servers params are ignored: `Host`, `Port`. You have total control of the connection.
Example using a conn for proxy:
```go
package main
import (
"crypto/tls"
"fmt"
"log"
"net"
mail "github.com/xhit/go-simple-mail/v2"
"golang.org/x/net/proxy"
)
func main() {
server := mail.NewSMTPClient()
host := "smtp.example.com"
port := 587
proxyAddr := "proxy.server"
conn, err := getCustomConnWithProxy(proxyAddr, host, port)
if err != nil {
log.Fatal(err)
}
server.Username = "test@example.com"
server.Password = "examplepass"
server.Encryption = mail.EncryptionSTARTTLS
server.CustomConn = conn
smtpClient, err := server.Connect()
if err != nil {
log.Fatal(err)
}
email := mail.NewMSG()
err = email.SetFrom("From Example <nube@example.com>").AddTo("xhit@example.com").Send(smtpClient)
if err != nil {
log.Fatal(err)
}
}
func getCustomConnWithProxy(proxyAddr, host string, port int) (net.Conn, error) {
dial, err := proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
if err != nil {
return nil, err
}
dialer, err := dial.Dial("tcp", fmt.Sprintf("%s:%d", host, port))
if err != nil {
return nil, err
}
conf := &tls.Config{ServerName: host}
conn := tls.Client(dialer, conf)
return conn, nil
}
```
## More examples
See [example/example_test.go](example/example_test.go).

View File

@@ -9,6 +9,8 @@ import (
"net/mail"
"net/textproto"
"strconv"
"strings"
"sync"
"time"
"github.com/toorop/go-dkim"
@@ -31,6 +33,7 @@ type Email struct {
SMTPServer *smtpClient
DkimMsg string
AllowDuplicateAddress bool
AddBccToHeader bool
}
/*
@@ -49,10 +52,14 @@ type SMTPServer struct {
Port int
KeepAlive bool
TLSConfig *tls.Config
// use custom dialer
CustomConn net.Conn
}
// SMTPClient represents a SMTP Client for send email
type SMTPClient struct {
mu sync.Mutex
Client *smtpClient
KeepAlive bool
SendTimeout time.Duration
@@ -134,8 +141,23 @@ const (
AuthCRAMMD5
// AuthNone for SMTP servers without authentication
AuthNone
// AuthAuto (default) use the first AuthType of the list of returned types supported by SMTP
AuthAuto
)
func (at AuthType) String() string {
switch at {
case AuthPlain:
return "PLAIN"
case AuthLogin:
return "LOGIN"
case AuthCRAMMD5:
return "CRAM-MD5"
default:
return ""
}
}
// NewMSG creates a new email. It uses UTF-8 by default. All charsets: http://webcheatsheet.com/HTML/character_sets_list.php
func NewMSG() *Email {
email := &Email{
@@ -152,7 +174,7 @@ func NewMSG() *Email {
// NewSMTPClient returns the client for send email
func NewSMTPClient() *SMTPServer {
server := &SMTPServer{
Authentication: AuthPlain,
Authentication: AuthAuto,
Encryption: EncryptionNone,
ConnectTimeout: 10 * time.Second,
SendTimeout: 10 * time.Second,
@@ -333,6 +355,11 @@ func (email *Email) AddAddresses(header string, addresses ...string) *Email {
return email
}
// add Bcc only if AddBccToHeader is true
if header == "Bcc" && email.AddBccToHeader {
email.headers.Add(header, address.String())
}
// add all addresses to the headers except for Bcc and Return-Path
if header != "Bcc" && header != "Return-Path" {
// add the address to the headers
@@ -687,27 +714,30 @@ func (email *Email) SendEnvelopeFrom(from string, client *SMTPClient) error {
}
// dial connects to the smtp server with the request encryption type
func dial(host string, port string, encryption Encryption, config *tls.Config) (*smtpClient, error) {
func dial(customConn net.Conn, host string, port string, encryption Encryption, config *tls.Config) (*smtpClient, error) {
var conn net.Conn
var err error
var c *smtpClient
address := host + ":" + port
if customConn != nil {
conn = customConn
} else {
address := host + ":" + port
// do the actual dial
switch encryption {
// TODO: Remove EncryptionSSL check before launch v3
case EncryptionSSL, EncryptionSSLTLS:
conn, err = tls.Dial("tcp", address, config)
default:
conn, err = net.Dial("tcp", address)
}
// do the actual dial
switch encryption {
// TODO: Remove EncryptionSSL check before launch v3
case EncryptionSSL, EncryptionSSLTLS:
conn, err = tls.Dial("tcp", address, config)
default:
conn, err = net.Dial("tcp", address)
if err != nil {
return nil, errors.New("Mail Error on dialing with encryption type " + encryption.String() + ": " + err.Error())
}
}
if err != nil {
return nil, errors.New("Mail Error on dialing with encryption type " + encryption.String() + ": " + err.Error())
}
c, err := newClient(conn, host)
c, err = newClient(conn, host)
if err != nil {
return nil, fmt.Errorf("Mail Error on smtp dial: %w", err)
}
@@ -717,9 +747,9 @@ func dial(host string, port string, encryption Encryption, config *tls.Config) (
// smtpConnect connects to the smtp server and starts TLS and passes auth
// if necessary
func smtpConnect(host, port, helo string, a auth, at AuthType, encryption Encryption, config *tls.Config) (*smtpClient, error) {
func smtpConnect(customConn net.Conn, host, port, helo string, encryption Encryption, config *tls.Config) (*smtpClient, error) {
// connect to the mail server
c, err := dial(host, port, encryption, config)
c, err := dial(customConn, host, port, encryption, config)
if err != nil {
return nil, err
@@ -746,42 +776,60 @@ func smtpConnect(host, port, helo string, a auth, at AuthType, encryption Encryp
}
}
// only pass authentication if defined
if at != AuthNone {
// pass the authentication if necessary
if a != nil {
if ok, _ := c.extension("AUTH"); ok {
if err = c.authenticate(a); err != nil {
c.close()
return nil, fmt.Errorf("Mail Error on Auth: %w", err)
}
}
return c, nil
}
func (server *SMTPServer) getAuth(a string) (auth, error) {
var afn auth
switch {
case strings.Contains(a, AuthPlain.String()):
if server.Username != "" || server.Password != "" {
afn = plainAuthfn("", server.Username, server.Password, server.Host)
}
case strings.Contains(a, AuthLogin.String()):
if server.Username != "" || server.Password != "" {
afn = loginAuthfn("", server.Username, server.Password, server.Host)
}
case strings.Contains(a, AuthCRAMMD5.String()):
if server.Username != "" || server.Password != "" {
afn = cramMD5Authfn(server.Username, server.Password)
}
default:
return nil, fmt.Errorf("Mail Error on determining auth type, %s is not supported", a)
}
return afn, nil
}
func (server *SMTPServer) validateAuth(c *smtpClient) error {
var err error
var afn auth
switch {
case server.Authentication == AuthNone || server.Username == "":
return nil
case server.Authentication != AuthAuto:
afn, err = server.getAuth(server.Authentication.String())
if err != nil {
return err
}
}
return c, nil
if ok, a := c.extension("AUTH"); ok {
// Determine Auth type automatically from extension
if afn == nil {
afn, err = server.getAuth(a)
if err != nil {
return err
}
}
if err = c.authenticate(afn); err != nil {
c.close()
return fmt.Errorf("Mail Error on Auth: %w", err)
}
}
return nil
}
// Connect returns the smtp client
func (server *SMTPServer) Connect() (*SMTPClient, error) {
var a auth
switch server.Authentication {
case AuthPlain:
if server.Username != "" || server.Password != "" {
a = plainAuthfn("", server.Username, server.Password, server.Host)
}
case AuthLogin:
if server.Username != "" || server.Password != "" {
a = loginAuthfn("", server.Username, server.Password, server.Host)
}
case AuthCRAMMD5:
if server.Username != "" || server.Password != "" {
a = cramMD5Authfn(server.Username, server.Password)
}
}
var smtpConnectChannel chan error
var c *smtpClient
var err error
@@ -795,7 +843,7 @@ func (server *SMTPServer) Connect() (*SMTPClient, error) {
if server.ConnectTimeout != 0 {
smtpConnectChannel = make(chan error, 2)
go func() {
c, err = smtpConnect(server.Host, fmt.Sprintf("%d", server.Port), server.Helo, a, server.Authentication, server.Encryption, tlsConfig)
c, err = smtpConnect(server.CustomConn, server.Host, fmt.Sprintf("%d", server.Port), server.Helo, server.Encryption, tlsConfig)
// send the result
smtpConnectChannel <- err
}()
@@ -810,7 +858,7 @@ func (server *SMTPServer) Connect() (*SMTPClient, error) {
}
} else {
// no ConnectTimeout, just fire the connect
c, err = smtpConnect(server.Host, fmt.Sprintf("%d", server.Port), server.Helo, a, server.Authentication, server.Encryption, tlsConfig)
c, err = smtpConnect(server.CustomConn, server.Host, fmt.Sprintf("%d", server.Port), server.Helo, server.Encryption, tlsConfig)
if err != nil {
return nil, err
}
@@ -820,26 +868,34 @@ func (server *SMTPServer) Connect() (*SMTPClient, error) {
Client: c,
KeepAlive: server.KeepAlive,
SendTimeout: server.SendTimeout,
}, nil
}, server.validateAuth(c)
}
// Reset send RSET command to smtp client
func (smtpClient *SMTPClient) Reset() error {
smtpClient.mu.Lock()
defer smtpClient.mu.Unlock()
return smtpClient.Client.reset()
}
// Noop send NOOP command to smtp client
func (smtpClient *SMTPClient) Noop() error {
smtpClient.mu.Lock()
defer smtpClient.mu.Unlock()
return smtpClient.Client.noop()
}
// Quit send QUIT command to smtp client
func (smtpClient *SMTPClient) Quit() error {
smtpClient.mu.Lock()
defer smtpClient.mu.Unlock()
return smtpClient.Client.quit()
}
// Close closes the connection
func (smtpClient *SMTPClient) Close() error {
smtpClient.mu.Lock()
defer smtpClient.mu.Unlock()
return smtpClient.Client.close()
}
@@ -869,14 +925,14 @@ func send(from string, to []string, msg string, client *SMTPClient) error {
if client.SendTimeout != 0 {
smtpSendChannel = make(chan error, 1)
go func(from string, to []string, msg string, c *smtpClient) {
smtpSendChannel <- sendMailProcess(from, to, msg, c)
}(from, to, msg, client.Client)
go func(from string, to []string, msg string, client *SMTPClient) {
smtpSendChannel <- sendMailProcess(from, to, msg, client)
}(from, to, msg, client)
}
if client.SendTimeout == 0 {
// no SendTimeout, just fire the sendMailProcess
return sendMailProcess(from, to, msg, client.Client)
return sendMailProcess(from, to, msg, client)
}
// get the send result or timeout result, which ever happens first
@@ -888,35 +944,36 @@ func send(from string, to []string, msg string, client *SMTPClient) error {
checkKeepAlive(client)
return errors.New("Mail Error: SMTP Send timed out")
}
}
}
return errors.New("Mail Error: No SMTP Client Provided")
}
func sendMailProcess(from string, to []string, msg string, c *smtpClient) error {
func sendMailProcess(from string, to []string, msg string, c *SMTPClient) error {
c.mu.Lock()
defer c.mu.Unlock()
cmdArgs := make(map[string]string)
if _, ok := c.ext["SIZE"]; ok {
if _, ok := c.Client.ext["SIZE"]; ok {
cmdArgs["SIZE"] = strconv.Itoa(len(msg))
}
// Set the sender
if err := c.mail(from, cmdArgs); err != nil {
if err := c.Client.mail(from, cmdArgs); err != nil {
return err
}
// Set the recipients
for _, address := range to {
if err := c.rcpt(address); err != nil {
if err := c.Client.rcpt(address); err != nil {
return err
}
}
// Send the data command
w, err := c.data()
w, err := c.Client.data()
if err != nil {
return err
}
@@ -938,9 +995,9 @@ func sendMailProcess(from string, to []string, msg string, c *smtpClient) error
// check if keepAlive for close or reset
func checkKeepAlive(client *SMTPClient) {
if client.KeepAlive {
client.Client.reset()
client.Reset()
} else {
client.Client.quit()
client.Client.close()
client.Quit()
client.Close()
}
}

2
vendor/modules.txt vendored
View File

@@ -1686,7 +1686,7 @@ github.com/xeipuuv/gojsonpointer
# github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415
## explicit
github.com/xeipuuv/gojsonreference
# github.com/xhit/go-simple-mail/v2 v2.13.0
# github.com/xhit/go-simple-mail/v2 v2.15.0
## explicit; go 1.13
github.com/xhit/go-simple-mail/v2
# github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e