Skip to content

Commit 457c8da

Browse files
committed
use custom conn
Fix #79, #24
1 parent 6b425f7 commit 457c8da

File tree

2 files changed

+98
-20
lines changed

2 files changed

+98
-20
lines changed

README.md

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Go Simple Mail supports:
7777
- Support text/calendar content type body (since v2.11.0)
7878
- Support add a List-Unsubscribe header (since v2.11.0)
7979
- Support to add a DKIM signarure (since v2.11.0)
80+
- Support to send using custom connection, ideal for proxy (since v2.15.0)
8081

8182
## Documentation
8283

@@ -102,7 +103,7 @@ package main
102103
import (
103104
"log"
104105

105-
"github.com/xhit/go-simple-mail/v2"
106+
mail "github.com/xhit/go-simple-mail/v2"
106107
"github.com/toorop/go-dkim"
107108
)
108109

@@ -269,6 +270,77 @@ func main() {
269270
}
270271
```
271272

273+
# Send with custom connection
274+
275+
It's possible to use a custom connection with custom dieler, like a dialer that uses a proxy server, etc...
276+
277+
With this, these servers params are ignored: `Host`, `Port`. You have total control of the connection.
278+
279+
Example using a conn for proxy:
280+
281+
```go
282+
package main
283+
284+
import (
285+
"crypto/tls"
286+
"fmt"
287+
"log"
288+
"net"
289+
290+
mail "github.com/xhit/go-simple-mail/v2"
291+
"golang.org/x/net/proxy"
292+
)
293+
294+
func main() {
295+
server := mail.NewSMTPClient()
296+
297+
host := "smtp.example.com"
298+
port := 587
299+
proxyAddr := "proxy.server"
300+
301+
conn, err := getCustomConnWithProxy(proxyAddr, host, port)
302+
if err != nil {
303+
log.Fatal(err)
304+
}
305+
306+
server.Username = "[email protected]"
307+
server.Password = "examplepass"
308+
server.Encryption = mail.EncryptionSTARTTLS
309+
server.CustomConn = conn
310+
311+
smtpClient, err := server.Connect()
312+
if err != nil {
313+
log.Fatal(err)
314+
}
315+
316+
email := mail.NewMSG()
317+
318+
err = email.SetFrom("From Example <[email protected]>").AddTo("[email protected]").Send(smtpClient)
319+
if err != nil {
320+
log.Fatal(err)
321+
}
322+
323+
}
324+
325+
func getCustomConnWithProxy(proxyAddr, host string, port int) (net.Conn, error) {
326+
dial, err := proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
327+
if err != nil {
328+
return nil, err
329+
}
330+
331+
dialer, err := dial.Dial("tcp", fmt.Sprintf("%s:%d", host, port))
332+
if err != nil {
333+
return nil, err
334+
}
335+
336+
conf := &tls.Config{ServerName: host}
337+
conn := tls.Client(dialer, conf)
338+
339+
return conn, nil
340+
}
341+
342+
```
343+
272344
## More examples
273345

274346
See [example/example_test.go](example/example_test.go).

email.go

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ type SMTPServer struct {
5252
Port int
5353
KeepAlive bool
5454
TLSConfig *tls.Config
55+
56+
// use custom dialer
57+
CustomConn net.Conn
5558
}
5659

5760
// SMTPClient represents a SMTP Client for send email
@@ -711,27 +714,30 @@ func (email *Email) SendEnvelopeFrom(from string, client *SMTPClient) error {
711714
}
712715

713716
// dial connects to the smtp server with the request encryption type
714-
func dial(host string, port string, encryption Encryption, config *tls.Config) (*smtpClient, error) {
717+
func dial(customConn net.Conn, host string, port string, encryption Encryption, config *tls.Config) (*smtpClient, error) {
715718
var conn net.Conn
716719
var err error
720+
var c *smtpClient
717721

718-
address := host + ":" + port
719-
720-
// do the actual dial
721-
switch encryption {
722-
// TODO: Remove EncryptionSSL check before launch v3
723-
case EncryptionSSL, EncryptionSSLTLS:
724-
conn, err = tls.Dial("tcp", address, config)
725-
default:
726-
conn, err = net.Dial("tcp", address)
727-
}
722+
if customConn != nil {
723+
conn = customConn
724+
} else {
725+
address := host + ":" + port
726+
// do the actual dial
727+
switch encryption {
728+
// TODO: Remove EncryptionSSL check before launch v3
729+
case EncryptionSSL, EncryptionSSLTLS:
730+
conn, err = tls.Dial("tcp", address, config)
731+
default:
732+
conn, err = net.Dial("tcp", address)
733+
}
728734

729-
if err != nil {
730-
return nil, errors.New("Mail Error on dialing with encryption type " + encryption.String() + ": " + err.Error())
735+
if err != nil {
736+
return nil, errors.New("Mail Error on dialing with encryption type " + encryption.String() + ": " + err.Error())
737+
}
731738
}
732739

733-
c, err := newClient(conn, host)
734-
740+
c, err = newClient(conn, host)
735741
if err != nil {
736742
return nil, fmt.Errorf("Mail Error on smtp dial: %w", err)
737743
}
@@ -741,9 +747,9 @@ func dial(host string, port string, encryption Encryption, config *tls.Config) (
741747

742748
// smtpConnect connects to the smtp server and starts TLS and passes auth
743749
// if necessary
744-
func smtpConnect(host, port, helo string, encryption Encryption, config *tls.Config) (*smtpClient, error) {
750+
func smtpConnect(customConn net.Conn, host, port, helo string, encryption Encryption, config *tls.Config) (*smtpClient, error) {
745751
// connect to the mail server
746-
c, err := dial(host, port, encryption, config)
752+
c, err := dial(customConn, host, port, encryption, config)
747753

748754
if err != nil {
749755
return nil, err
@@ -837,7 +843,7 @@ func (server *SMTPServer) Connect() (*SMTPClient, error) {
837843
if server.ConnectTimeout != 0 {
838844
smtpConnectChannel = make(chan error, 2)
839845
go func() {
840-
c, err = smtpConnect(server.Host, fmt.Sprintf("%d", server.Port), server.Helo, server.Encryption, tlsConfig)
846+
c, err = smtpConnect(server.CustomConn, server.Host, fmt.Sprintf("%d", server.Port), server.Helo, server.Encryption, tlsConfig)
841847
// send the result
842848
smtpConnectChannel <- err
843849
}()
@@ -852,7 +858,7 @@ func (server *SMTPServer) Connect() (*SMTPClient, error) {
852858
}
853859
} else {
854860
// no ConnectTimeout, just fire the connect
855-
c, err = smtpConnect(server.Host, fmt.Sprintf("%d", server.Port), server.Helo, server.Encryption, tlsConfig)
861+
c, err = smtpConnect(server.CustomConn, server.Host, fmt.Sprintf("%d", server.Port), server.Helo, server.Encryption, tlsConfig)
856862
if err != nil {
857863
return nil, err
858864
}

0 commit comments

Comments
 (0)