[go] Best way use smtp via Proxy

Hi if you have experience with smtp+proxy pls help, I can’t find anything on internet, help

I found this but all time I get error EOF

https://play.golang.org/p/ZCx8_8Uhzs2

who know how use smtp+sock5 for example send email use gmail via proxy?

Hi. Where do you get EOF?

Well, at first sight your example seems to not support TLS and that could be a good reason to won’t work with Gmail. Search for another example, are many on the internet.

https://www.google.com/search?q=golang+gmail+sender

Thank you for answer, I already dropped the code above and found the only one on the Internet - it also does not work so far …

err := s.Send(“测试 from socks5”, "from@xx.com", []string{“to@xx.com”}, “sockssmtp测试”)
if err != nil {
log.Fatalln(err)
}

also I try do this

I also failed, maybe not right

I need via proxy (socks5)+smtp method,found nothing(

But this is at the toplevel. The error must occur somewhere in the function and be returned. Where in the function is this error from?

package main

import (
	"encoding/base64"
	"fmt"
	"log"
	"math/rand"
	"net"
	"net/smtp"
	"os"
	"strings"
	"time"

	"github.com/pkg/errors"
	"golang.org/x/net/proxy"
)

type SocksSMTP struct {
	ProxyUserName string
	ProxyPassword string
	ProxyAddress  string

	Address  string
	UserName string
	Password string
}

func BaseEncode(s string) string {
	return fmt.Sprintf("=?UTF-8?B?%s?=", base64.StdEncoding.EncodeToString([]byte(s)))
}

func (s *SocksSMTP) CreateClient() (*smtp.Client, error) {
	var auth *proxy.Auth
	if s.ProxyUserName != "" {
		auth = &proxy.Auth{
			User:     s.ProxyUserName,
			Password: s.ProxyPassword,
		}
	}
	dialer, err := proxy.SOCKS5("tcp", s.ProxyAddress, auth, proxy.Direct)
	if err != nil {
		return nil, errors.Wrap(err, "Create SOCKS5")
	}
	conn, err := dialer.Dial("tcp", s.Address)
	if err != nil {
		return nil, errors.Wrap(err, "Dial")
	}

	host, _, _ := net.SplitHostPort(s.Address)
	c, err := smtp.NewClient(conn, host)

	return c, err
}

type _PlainAuth struct {
	identity, username, password string
	host                         string
}

func PlainAuth(identity, username, password string,
	host string) smtp.Auth {
	return &_PlainAuth{identity, username, password,
		host}
}

func (a *_PlainAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
	if server.Name != a.host {
		return "", nil, errors.New("wrong host name")
	}
	resp := []byte(a.identity + "\x00" + a.username + "\x00" + a.password)
	return "PLAIN", resp, nil
}

func (a *_PlainAuth) Next(from_server []byte, more bool) ([]byte, error) {
	if more {
		// We've already sent everything.
		return nil, errors.New("unexpected server challenge")
	}
	return nil, nil
}

// 发送文本
func (s *SocksSMTP) Send(subjct string, from_name string, to []string, body string) error {
	c, err := s.CreateClient()
	if err != nil {
		return errors.Wrap(err, "CreateClient")
	}
	defer c.Close()

	if err = c.Hello("localhost"); err != nil {
		return errors.Wrap(err, "hello")
	}

	host, _, err := net.SplitHostPort(s.Address)
	if err != nil {
		return err
	}

	if ok, _ := c.Extension("STARTTLS"); ok {
		fmt.Println("NEED TLS")
		// TODO
	}

	auth := PlainAuth("", s.UserName, s.Password, host)
	if err = c.Auth(auth); err != nil {
		return errors.Wrap(err, "Auth")
	}

	// 设置发件人
	if err = c.Mail(s.UserName); err != nil {
		return errors.Wrap(err, "Set Sender")
	}

	// 设置接收人
	for _, addr := range to {
		if err = c.Rcpt(addr); err != nil {
			return errors.Wrap(err, "Set Receiver")
		}
	}
	w, err := c.Data()
	if err != nil {
		return errors.Wrap(err, "Client.Data")
	}

	hostname, err := os.Hostname()
	if err != nil {
		return errors.Wrap(err, "Get hostname")
	}
	headers := map[string]string{}
	headers["Subject"] = BaseEncode(subjct)
	headers["To"] = strings.Join(to, ", ")
	headers["From"] = from_name
	headers["MIME-Version"] = "1.0"
	headers["Content-Type"] = "text/plain; charset=UTF-8"
	headers["Message-ID"] = fmt.Sprintf("<%f.%d@%s>", rand.Float64(),
		time.Now().UnixNano(), hostname)

	msg := ""
	for k, v := range headers {
		msg += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	msg += fmt.Sprintf("\r\n" + body)

	if _, err = w.Write([]byte(msg)); err != nil {
		return errors.Wrap(err, "Writer msg")
	}
	if err = w.Close(); err != nil {
		return err
	}

	return c.Quit()
}

func main() {
	s := &SocksSMTP{
		ProxyUserName: "",
		ProxyPassword: "",
		ProxyAddress:  "",

		Address:  "<host>:<port>",
		UserName: "",
		Password: "",
	}

	err := s.Send("测试 from socks5", "from@xx.com", []string{"to@xx.com"}, "sockssmtp测试")
	if err != nil {
		log.Fatalln(err)
	}
}

I try this code, find in google

What I wanted to know was where inside the function the error occurs. This error is then returned and printed but to help you we must know where the program goes wrong.

an error is created when i connect to the SMTP server, in response I’m thinking of EOF, and this is most likely due to the missing code, in which I unfortunately do not have knowledge

Stupid question. Have you filled in all the fields of this with the values which is related to your proxy?

ProxyUserName: “”,
ProxyPassword: “”,
ProxyAddress: “”,

Address: “:”,
UserName: “”,
Password: “”,

yes i am all filled in=)

1 Like

closed

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.