Browse Source

in progress

0x4a52466c696e74 1 year ago
parent
commit
9d9526a618
6 changed files with 97 additions and 26 deletions
  1. 1 1
      .gitignore
  2. 4 1
      go.mod
  3. 3 0
      go.sum
  4. 15 4
      smtp/emailer/auth.go
  5. 37 20
      smtp/emailer/smtp.go
  6. 37 0
      smtp/emailer/z_test.go

+ 1 - 1
.gitignore

@@ -1 +1 @@
-*.config
+*.config

+ 4 - 1
go.mod

@@ -2,4 +2,7 @@ module git.ali33.ru/fcg-xvii/go-tools
 
 go 1.18
 
-require github.com/lib/pq v1.10.4 // indirect
+require (
+	github.com/fcg-xvii/go-tools v0.0.0-20220316201232-6d6629b9d1e7
+	github.com/lib/pq v1.10.4
+)

+ 3 - 0
go.sum

@@ -1,2 +1,5 @@
+github.com/fcg-xvii/go-tools v0.0.0-20220316201232-6d6629b9d1e7 h1:y9HN4JU8mMzR6KfCRQVO7V5CUJqrCe55fDYreyur7YU=
+github.com/fcg-xvii/go-tools v0.0.0-20220316201232-6d6629b9d1e7/go.mod h1:iqeLyAqB+RN0zxQTNk7yWI9dzy09Oc6yUk1m1vkdws0=
+github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
 github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=

+ 15 - 4
smtp/emailer/auth.go

@@ -28,6 +28,7 @@ type Auth interface {
 	// If Next returns a non-nil error, the SMTP client aborts
 	// the authentication attempt and closes the connection.
 	Next(fromServer []byte, more bool) (toServer []byte, err error)
+	IsTLS() bool
 }
 
 // ServerInfo records information about an SMTP server.
@@ -40,6 +41,11 @@ type ServerInfo struct {
 type plainAuth struct {
 	identity, username, password string
 	host                         string
+	tls                          bool
+}
+
+func (s *plainAuth) IsTLS() bool {
+	return s.tls
 }
 
 // PlainAuth returns an Auth that implements the PLAIN authentication
@@ -50,8 +56,8 @@ type plainAuth struct {
 // PlainAuth will only send the credentials if the connection is using TLS
 // or is connected to localhost. Otherwise authentication will fail with an
 // error, without sending the credentials.
-func PlainAuth(identity, username, password, host string) Auth {
-	return &plainAuth{identity, username, password, host}
+func PlainAuth(identity, username, password, host string, tls bool) Auth {
+	return &plainAuth{identity, username, password, host, tls}
 }
 
 func isLocalhost(name string) bool {
@@ -84,14 +90,19 @@ func (a *plainAuth) Next(fromServer []byte, more bool) ([]byte, error) {
 
 type cramMD5Auth struct {
 	username, secret string
+	tls              bool
 }
 
 // CRAMMD5Auth returns an Auth that implements the CRAM-MD5 authentication
 // mechanism as defined in RFC 2195.
 // The returned Auth uses the given username and secret to authenticate
 // to the server using the challenge-response mechanism.
-func CRAMMD5Auth(username, secret string) Auth {
-	return &cramMD5Auth{username, secret}
+func CRAMMD5Auth(username, secret string, tls bool) Auth {
+	return &cramMD5Auth{username, secret, tls}
+}
+
+func (s *cramMD5Auth) IsTLS() bool {
+	return s.tls
 }
 
 func (a *cramMD5Auth) Start(server *ServerInfo) (string, []byte, error) {

+ 37 - 20
smtp/emailer/smtp.go

@@ -49,12 +49,22 @@ type Client struct {
 
 // Dial returns a new Client connected to an SMTP server at addr.
 // The addr must include a port, as in "mail.example.com:smtp".
-func Dial(addr string) (*Client, error) {
-	conn, err := net.DialTimeout("tcp", addr, time.Second*10)
-	if err != nil {
-		return nil, err
-	}
+func Dial(addr string, tlsEnabled bool) (cl *Client, err error) {
 	host, _, _ := net.SplitHostPort(addr)
+	var conn net.Conn
+	if tlsEnabled {
+		tlsconfig := &tls.Config{
+			InsecureSkipVerify: true,
+			ServerName:         host,
+		}
+		if conn, err = tls.Dial("tcp", addr, tlsconfig); err != nil {
+			return
+		}
+	} else {
+		if conn, err = net.DialTimeout("tcp", addr, time.Second*10); err != nil {
+			return
+		}
+	}
 	return NewClient(conn, host)
 }
 
@@ -62,6 +72,8 @@ func Dial(addr string) (*Client, error) {
 // server name to be used when authenticating.
 func NewClient(conn net.Conn, host string) (*Client, error) {
 	text := textproto.NewConn(conn)
+	// read deadline
+	conn.SetReadDeadline(time.Now().Add(time.Second * 5))
 	_, _, err := text.ReadResponse(220)
 	if err != nil {
 		text.Close()
@@ -154,13 +166,16 @@ func (c *Client) StartTLS(config *tls.Config) error {
 	if err := c.hello(); err != nil {
 		return err
 	}
-	_, _, err := c.cmd(220, "STARTTLS")
-	if err != nil {
-		return err
-	}
-	c.conn = tls.Client(c.conn, config)
-	c.Text = textproto.NewConn(c.conn)
 	c.tls = true
+	/*
+		_, _, err := c.cmd(220, "STARTTLS")
+		if err != nil {
+			return err
+		}
+		c.conn = tls.Client(c.conn, config)
+		c.Text = textproto.NewConn(c.conn)
+		c.tls = true
+	*/
 	return c.ehlo()
 }
 
@@ -326,7 +341,7 @@ func SendMail(addr string, a Auth, from string, to []string, msg []byte) error {
 			return err
 		}
 	}
-	c, err := Dial(addr)
+	c, err := Dial(addr, a.IsTLS())
 	if err != nil {
 		return err
 	}
@@ -334,15 +349,17 @@ func SendMail(addr string, a Auth, from string, to []string, msg []byte) error {
 	if err = c.hello(); err != nil {
 		return err
 	}
-	if ok, _ := c.Extension("STARTTLS"); ok {
-		config := &tls.Config{ServerName: c.serverName}
-		if testHookStartTLS != nil {
-			testHookStartTLS(config)
-		}
-		if err = c.StartTLS(config); err != nil {
-			return err
+	/*
+		if ok, _ := c.Extension("STARTTLS"); ok {
+			config := &tls.Config{ServerName: c.serverName}
+			if testHookStartTLS != nil {
+				testHookStartTLS(config)
+			}
+			if err = c.StartTLS(config); err != nil {
+				return err
+			}
 		}
-	}
+	*/
 	if a != nil && c.ext != nil {
 		if _, ok := c.ext["AUTH"]; !ok {
 			return errors.New("smtp: server doesn't support AUTH")

+ 37 - 0
smtp/emailer/z_test.go

@@ -0,0 +1,37 @@
+package emailer
+
+import (
+	"log"
+	"net/mail"
+	"testing"
+
+	"github.com/fcg-xvii/go-tools/text/config"
+	_ "github.com/fcg-xvii/go-tools/text/config/ini"
+)
+
+func TestEmail(t *testing.T) {
+	conf, err := config.FromFile("ini", "z_conf.config")
+	if err != nil {
+		t.Fatal(err)
+	}
+	from := conf.ValueDefault("from", "").(string)
+	message := conf.ValueDefault("message", "").(string)
+	to := conf.ValueDefault("to", "").(string)
+	user := conf.ValueDefault("user", "").(string)
+	password := conf.ValueDefault("password", "").(string)
+	host := conf.ValueDefault("smtp_host", "").(string)
+	addr := conf.ValueDefault("smtp_addr", "").(string)
+	tls := conf.ValueDefault("tls_enabled", false).(bool)
+	auth := PlainAuth("", user, password, host, tls)
+
+	t.Log(addr, host, from, to, message)
+	mes := NewMessage("Subj )", message)
+	//mes.BodyContentType = "text/plain;"
+	mes.From = mail.Address{Name: from, Address: from}
+	mes.AddTo(mail.Address{Name: to, Address: to})
+	log.Println(string(mes.Bytes()))
+	if err := Send(addr, auth, mes); err != nil {
+		t.Fatal(err)
+	}
+	t.Log("DONE")
+}