Пример #1
2
func smtpSendMailPart2(c *smtp.Client, smtpHost string, a smtp.Auth, from string, to []string, msg []byte) (err error) {
	defer c.Close()
	if err = c.Hello("localhost"); err != nil {
		return err
	}
	if ok, _ := c.Extension("STARTTLS"); ok {
		config := &tls.Config{ServerName: smtpHost}
		if err = c.StartTLS(config); err != nil {
			return err
		}
	}
	if a != nil {
		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(a); err != nil {
				return err
			}
		}
	}
	if err = c.Mail(from); err != nil {
		return err
	}
	for _, addr := range to {
		if err = c.Rcpt(addr); err != nil {
			return err
		}
	}
	w, err := c.Data()
	if err != nil {
		return err
	}
	_, err = w.Write(msg)
	if err != nil {
		return err
	}
	err = w.Close()
	if err != nil {
		return err
	}
	return c.Quit()
}
Пример #2
1
func (DefaultSender) Send(from, to, content string) error {
	var (
		err  error
		c    *smtp.Client
		auth smtp.Auth
	)
	log.Println("mail: sending mail to " + to)
	auth, err = DefaultSender{}.auth()
	if nil != err {
		return err
	}
	c, err = smtp.Dial(MAIL_HOST + ":" + MAIL_PORT)
	if nil != err {
		return err
	}
	defer c.Close()

	tlc := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         MAIL_HOST,
	}
	if err = c.StartTLS(tlc); err != nil {
		log.Println("tls error " + err.Error())
		return err
	}
	c.Auth(auth)
	c.Mail(from)
	c.Rcpt(to)

	// Send the email body.
	wc, err := c.Data()
	if err != nil {
		log.Fatal(err)
	}
	defer wc.Close()
	buf := bytes.NewBufferString(content)
	if _, err = buf.WriteTo(wc); err != nil {
		log.Fatal(err)
	}
	if err != nil {
		log.Println("email: failed to write " + err.Error())
		return err
	}
	return err
}
Пример #3
0
func handleQUIT(rec *SMTPRecord, c *smtp.Client, proxy *SMTPSession) error {
	id, err := c.Text.Cmd(rec.Cmd.Packet)

	if err != nil {
		return err
	}

	c.Text.StartResponse(id)
	defer c.Text.EndResponse(id)

	msg, err := collectClientLines(c.Text)

	if err != nil {
		return err
	}

	fmt.Fprint(proxy.base.Conn, msg)

	c.Close()
	proxy.Close()

	return nil
}
Пример #4
0
// send does the low level sending of the email
func send(host string, port string, from string, to []string, msg string, auth smtp.Auth, encryption encryption, config *tls.Config, connectTimeout int) error {
	var smtpConnectChannel chan smtpConnectErrorChannel
	var c *smtp.Client = nil
	var err error

	// set the timeout value
	timeout := time.Duration(connectTimeout) * time.Second

	// if there is a timeout, setup the channel and do the connect under a goroutine
	if timeout != 0 {
		smtpConnectChannel = make(chan smtpConnectErrorChannel, 2)
		go func() {
			c, err = smtpConnect(host, port, from, to, msg, auth, encryption, config)
			// send the result
			smtpConnectChannel <- smtpConnectErrorChannel{
				client: c,
				err:    err,
			}
		}()
	}

	if timeout == 0 {
		// no timeout, just fire the connect
		c, err = smtpConnect(host, port, from, to, msg, auth, encryption, config)
	} else {
		// get the connect result or timeout result, which ever happens first
		select {
		case result := <-smtpConnectChannel:
			c = result.client
			err = result.err
		case <-time.After(timeout):
			return errors.New("Mail Error: SMTP Connection timed out")
		}
	}

	// check for connect error
	if err != nil {
		return err
	}

	defer c.Close()

	// Set the sender
	if err := c.Mail(from); err != nil {
		return err
	}

	// Set the recipients
	for _, address := range to {
		if err := c.Rcpt(address); err != nil {
			return err
		}
	}

	// Send the data command
	w, err := c.Data()
	if err != nil {
		return err
	}

	// write the message
	_, err = fmt.Fprint(w, msg)
	if err != nil {
		return err
	}

	err = w.Close()
	if err != nil {
		return err
	}

	return c.Quit()
}
Пример #5
0
// TestSMTP tests if can connect with the server and send some commands.
func TestSMTP(addr string, a smtp.Auth, hello string, timeout time.Duration, insecureSkipVerify bool) error {
	serverName := addr
	port := ""
	s := strings.SplitN(addr, ":", 2)
	if len(s) >= 2 {
		serverName = s[0]
		port = s[1]
	}

	if serverName == "" || port == "" {
		return e.New("addrs is invalid")
	}

	hosts, err := dns.LookupHostCache(serverName)
	if err != nil {
		return e.Forward(err)
	}
	if len(hosts) == 0 {
		return e.New("can't resolve the addr")
	}

	conn, err := net.DialTimeout("tcp", hosts[0]+":"+port, timeout)
	if err != nil {
		return e.Forward(err)
	}
	defer conn.Close()

	command := &Command{
		Timeout: timeout,
		Conn:    conn,
	}

	var c *smtp.Client
	r := command.Exec(smtp.NewClient, conn, serverName)
	r(&c, &err)
	if err != nil {
		return e.Forward(err)
	}
	defer c.Close()

	if hello != "" {
		r = command.Exec(c.Hello, hello)
		r(&err)
		if err != nil {
			return e.Forward(err)
		}
	}

	if ok, _ := c.Extension("STARTTLS"); ok {
		r = command.Exec(c.StartTLS, &tls.Config{
			ServerName:         serverName,
			InsecureSkipVerify: insecureSkipVerify,
		})
		r(&err)
		if err != nil {
			return e.Forward(err)
		}
	}

	if a != nil {
		found, _ := c.Extension("AUTH")
		if found {
			r = command.Exec(c.Auth, a)
			r(&err)
			if err != nil {
				return e.Forward(err)
			}
		}
	}

	r = command.Exec(c.Reset)
	r(&err)
	if err != nil {
		return e.New(err)
	}

	r = command.Exec(c.Quit)
	r(&err)
	if err != nil {
		return e.New(err)
	}

	return nil
}
Пример #6
0
// SendMail send a message to specific destination (to) using smtp server in addrs
// and a auth.
func SendMail(addr string, a smtp.Auth, from string, to []string, hello string, msg []byte, timeout time.Duration, insecureSkipVerify bool) error {
	serverName := addr
	port := ""
	serverName, port, err := net.SplitHostPort(addr)
	if err != nil {
		return e.Push(err, "invalid adderess")
	}

	if serverName == "" || port == "" {
		return e.New("addrs is invalid")
	}

	conn, err := net.DialTimeout("tcp", addr, timeout)
	if err != nil {
		return e.New(err)
	}
	defer conn.Close()

	command := &Command{
		Timeout: timeout,
		Conn:    conn,
	}

	var c *smtp.Client
	r := command.Exec(smtp.NewClient, conn, serverName)
	r(&c, &err)
	if err != nil {
		return e.Forward(err)
	}
	defer c.Close()

	if hello != "" {
		r = command.Exec(c.Hello, hello)
		r(&err)
		if err != nil {
			return e.Forward(err)
		}
	}

	if ok, _ := c.Extension("STARTTLS"); ok {
		r = command.Exec(c.StartTLS, &tls.Config{
			ServerName:         serverName,
			InsecureSkipVerify: insecureSkipVerify,
		})
		r(&err)
		if err != nil {
			return e.Forward(err)
		}
	}

	if a != nil {
		found, _ := c.Extension("AUTH")
		if found {
			r = command.Exec(c.Auth, a)
			r(&err)
			if err != nil {
				return e.Forward(err)
			}
		}
	}

	r = command.Exec(c.Mail, from)
	r(&err)
	if err != nil {
		return e.Forward(err)
	}

	for _, addr := range to {
		r = command.Exec(c.Rcpt, addr)
		r(&err)
		if err != nil {
			return e.New(err)
		}
	}

	var w io.WriteCloser
	r = command.ExecTimeout(0, c.Data)
	r(&w, &err)
	if err != nil {
		return e.New(err)
	}
	_, err = w.Write(msg)
	if err != nil {
		return e.New(err)
	}
	err = w.Close()
	if err != nil {
		return e.New(err)
	}

	r = command.Exec(c.Quit)
	r(&err)
	if err != nil {
		return e.New(err)
	}
	return nil
}
Пример #7
0
Файл: email.go Проект: ovh/tat
func sendEmail(templ, subject, username, toUser, tokenVerify, text, cmd, device string) error {
	t := template.New("Email template")
	t, err := t.Parse(templ)
	if err != nil {
		log.Errorf("Error with parsing template:%s ", err.Error())
		return err
	}

	paramEmail := &paramEmail{
		TextVerify: text,
		CMDVerify:  cmd,
	}

	var b bytes.Buffer
	err = t.Execute(&b, paramEmail)
	if err != nil {
		log.Errorf("Error with Execute template:%s ", err.Error())
		return err
	}

	if viper.GetBool("no_smtp") {
		fmt.Println("##### NO SMTP DISPLAY MAIL IN CONSOLE ######")
		fmt.Printf("Subject:%s\n", subject)
		fmt.Printf("Text:%s\n", b.Bytes())
		fmt.Println("##### END MAIL ######")
		return nil
	}

	from := mail.Address{
		Name:    "",
		Address: viper.GetString("smtp_from"),
	}
	to := mail.Address{
		Name:    "",
		Address: toUser,
	}

	// Setup headers
	headers := make(map[string]string)
	headers["From"] = viper.GetString("smtp_from")
	headers["To"] = to.String()
	headers["Subject"] = subject

	// Setup message
	message := ""
	for k, v := range headers {
		message += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	message += "\r\n" + b.String()

	// Connect to the SMTP Server
	servername := fmt.Sprintf("%s:%s", viper.GetString("smtp_host"), viper.GetString("smtp_port"))

	// TLS config
	tlsconfig := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         viper.GetString("smtp_host"),
	}

	var c *smtp.Client
	if viper.GetBool("smtp_tls") {

		// Here is the key, you need to call tls.Dial instead of smtp.Dial
		// for smtp servers running on 465 that require an ssl connection
		// from the very beginning (no starttls)

		conn, errc := tls.Dial("tcp", servername, tlsconfig)
		if errc != nil {
			log.Errorf("Error with c.Dial:%s", errc.Error())
			return err
		}

		c, err = smtp.NewClient(conn, viper.GetString("smtp_host"))
		if err != nil {
			log.Errorf("Error with c.NewClient:%s", err.Error())
			return err
		}
	} else {
		c, err = smtp.Dial(servername)
		if err != nil {
			log.Errorf("Error while smtp.Dial:%s", err)
		}
		defer c.Close()
	}

	// Auth
	if viper.GetString("smtp_user") != "" && viper.GetString("smtp_password") != "" {
		auth := smtp.PlainAuth("", viper.GetString("smtp_user"), viper.GetString("smtp_password"), viper.GetString("smtp_host"))
		if err = c.Auth(auth); err != nil {
			log.Errorf("Error with c.Auth:%s", err.Error())
			return err
		}
	}

	// To && From
	if err = c.Mail(from.Address); err != nil {
		log.Errorf("Error with c.Mail:%s", err.Error())
		return err
	}

	if err = c.Rcpt(to.Address); err != nil {
		log.Errorf("Error with c.Rcpt:%s", err.Error())
		return err
	}

	// Data
	w, err := c.Data()
	if err != nil {
		log.Errorf("Error with c.Data:%s", err.Error())
		return err
	}

	_, err = w.Write([]byte(message))
	if err != nil {
		log.Errorf("Error with c.Write:%s", err.Error())
		return err
	}

	err = w.Close()
	if err != nil {
		log.Errorf("Error with c.Close:%s", err.Error())
		return err
	}

	c.Quit()

	return nil
}
Пример #8
0
// SendMailMessage handles outgoing message to SMTP server.
//
// - The connections to the service can be either plain (port 25)
//   or SSL/TLS (port 465)
//
// - If the server supports STARTTLS and the channel is not already
//   encrypted (via SSL), the application will use the "STLS" command
//   to initiate a channel encryption.
//
// - Connections can be tunneled through any SOCKS5 proxy (like Tor)
func SendMailMessage(host, proxy, fromAddr, toAddr string, body []byte) error {
	var (
		c0  net.Conn
		c1  *tls.Conn
		cli *smtp.Client
	)
	defer func() {
		if cli != nil {
			cli.Close()
		}
		if c1 != nil {
			c1.Close()
		}
		if c0 != nil {
			c0.Close()
		}
	}()

	uSrv, err := url.Parse(host)
	if err != nil {
		return err
	}
	if proxy == "" {
		c0, err = net.Dial("tcp", uSrv.Host)
	} else {
		host, port, err := SplitHost(uSrv.Host)
		if err != nil {
			return err
		}
		c0, err = Socks5Connect("tcp", host, port, proxy)
	}
	if err != nil {
		return err
	}
	if c0 == nil {
		return errors.New("Can't estabish connection to " + uSrv.Host)
	}

	sslConfig := &tls.Config{InsecureSkipVerify: true}
	if uSrv.Scheme == "smtps" {
		c1 = tls.Client(c0, sslConfig)
		if err = c1.Handshake(); err != nil {
			return err
		}
		cli, err = smtp.NewClient(c1, uSrv.Host)
	} else {
		cli, err = smtp.NewClient(c0, uSrv.Host)
		if err == nil {
			if ok, _ := cli.Extension("STLS"); ok {
				err = cli.StartTLS(sslConfig)
			}
		}
	}
	if err != nil {
		return err
	}
	pw, _ := uSrv.User.Password()
	auth := smtp.PlainAuth("", uSrv.User.Username(), pw, uSrv.Host)
	if err = cli.Auth(auth); err != nil {
		return err
	}
	if err = cli.Mail(fromAddr); err != nil {
		return err
	}
	if err = cli.Rcpt(toAddr); err != nil {
		return err
	}
	wrt, err := cli.Data()
	if err != nil {
		return err
	}
	wrt.Write(body)
	wrt.Close()
	if err = cli.Quit(); err != nil {
		return err
	}
	return nil
}
Пример #9
0
// Receive message and deliver them to their recipients. Due to the complicated
// algorithm for message delivery, the body of the method is broken up into a
// sequence of labeled sections.
func (h *Host) run() {
	defer close(h.stop)
	var (
		m        *Message
		hostname string
		c        *smtp.Client
		err      error
		tries    int
		duration = time.Minute
	)
receive:
	if m == nil {
		m = h.receiveMessage()
		if m == nil {
			goto shutdown
		}
		h.log.Info("message received in queue")
	}
	hostname, err = h.parseHostname(m.From)
	if err != nil {
		h.log.Error(err.Error())
		goto cleanup
	}
deliver:
	if c == nil {
		h.log.Debug("connecting to mail server")
		c, err = h.connectToMailServer(hostname)
		if c == nil {
			if err != nil {
				h.log.Error(err)
				goto wait
			} else {
				goto shutdown
			}
		}
		h.log.Debug("connection established")
	}
	err = h.deliverToMailServer(c, m)
	if err != nil {
		h.log.Error(err)
		if _, ok := err.(syscall.Errno); ok {
			c = nil
			goto deliver
		}
		if e, ok := err.(*textproto.Error); ok {
			if e.Code >= 400 && e.Code <= 499 {
				c.Close()
				c = nil
				goto wait
			}
			c.Reset()
		}
		h.log.Error(err.Error())
		goto cleanup
	}
	h.log.Info("message delivered successfully")
cleanup:
	h.log.Debug("deleting message from disk")
	err = h.storage.DeleteMessage(m)
	if err != nil {
		h.log.Error(err.Error())
	}
	m = nil
	tries = 0
	goto receive
wait:
	// We differ a tiny bit from the RFC spec here but this should work well
	// enough - the goal is to retry lots of times early on and space out the
	// remaining attempts as time goes on. (Roughly 48 hours total.)
	switch {
	case tries < 8:
		duration *= 2
	case tries < 18:
	default:
		h.log.Error("maximum retry count exceeded")
		goto cleanup
	}
	select {
	case <-h.stop:
	case <-time.After(duration):
		goto receive
	}
	tries++
shutdown:
	h.log.Debug("shutting down")
	if c != nil {
		c.Close()
	}
}
Пример #10
0
func SendMail(timeout time.Duration, addr string, from string, to string, msg []byte) error {
	response := make(chan error, 1)
	var conn *smtp.Client
	var err error

	go func() {
		conn, err = smtp.Dial(addr)
		if err != nil {
			response <- err
			return
		}
		response <- nil
	}()

	select {
	case res := <-response:
		if res == nil {
			go func() {
				defer conn.Close()
				if err = conn.Hello("localhost"); err != nil {
					response <- err
					return
				}
				if ok, _ := conn.Extension("STARTTLS"); ok {
					config := &tls.Config{ServerName: addr}
					if err = conn.StartTLS(config); err != nil {
						response <- err
						return
					}
				}
				if err = conn.Mail(from); err != nil {
					response <- err
					return
				}
				if err = conn.Rcpt(to); err != nil {
					response <- err
					return
				}
				w, err := conn.Data()
				if err != nil {
					response <- err
					return
				}
				_, err = w.Write(msg)
				if err != nil {
					response <- err
					return
				}
				err = w.Close()
				if err != nil {
					response <- err
					return
				}
				response <- conn.Quit()
			}()
			return <-response
		} else {
			return res
		}
	case <-time.After(time.Second * timeout): //don't do the smtp transaction, abandon the socket, it'll timeout after ~3 mins in syn_sent
		return fmt.Errorf("Sending timeout")
	}
}
Пример #11
0
// Send an email using the given host, SMTP auth (optional) and HELO hostname, returns any error thrown by smtp.SendMail
// This function merges the To, Cc, and Bcc fields and calls the smtp.SendMail function using the Email.Bytes() output as the message
func (e *Email) SendWithHELO(hostname string, port int32, a smtp.Auth, heloHostname string, esCerts *configprofile.CodeSigningCerts) error {
	// format server address
	addr := fmt.Sprintf("%s:%d", hostname, port)
	// Merge the To, Cc, and Bcc fields
	to := make([]string, 0, len(e.To)+len(e.Cc)+len(e.Bcc))
	to = append(append(append(to, e.To...), e.Cc...), e.Bcc...)
	for i := 0; i < len(to); i++ {
		addr, err := mail.ParseAddress(to[i])
		if err != nil {
			return err
		}
		to[i] = addr.Address
	}
	// Check to make sure there is at least one recipient and one "From" address
	if e.From == "" || len(to) == 0 {
		return errors.New("Must specify at least one From address and one To address")
	}
	from, err := mail.ParseAddress(e.From)
	if err != nil {
		return err
	}

	// Sign the email with S/MIME
	cmd := exec.Command("openssl", "smime", "-sign", "-signer", esCerts.Cert, "-inkey", esCerts.Key)

	emailBytes, err := e.Bytes()
	if err != nil {
		return err
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}

	err = cmd.Start()
	if err != nil {
		return err
	}

	stdin.Write(emailBytes)
	stdin.Close()

	signedData, err := ioutil.ReadAll(stdout)
	if err != nil {
		return err
	}
	err = cmd.Wait()
	if err != nil {
		return err
	}

	var signedEmail bytes.Buffer
	headerToBytes(&signedEmail, e.msgHeaders())
	signedEmail.Write(signedData)
	raw := signedEmail.Bytes()

	// Manually send email using net/smtp

	var c *smtp.Client
	if port == 465 {
		// TLS config
		tlsconfig := &tls.Config{
			InsecureSkipVerify: true,
			ServerName:         hostname,
		}

		// Here is the key, you need to call tls.Dial instead of smtp.Dial
		// for smtp servers running on 465 that require an ssl connection
		// from the very beginning (no starttls)
		conn, err := tls.Dial("tcp", addr, tlsconfig)
		if err != nil {
			return err
		}

		c, err = smtp.NewClient(conn, hostname)
		if err != nil {
			return err
		}
	} else {
		c, err = smtp.Dial(addr)
		if err != nil {
			return err
		}
	}

	defer c.Close()
	if err = c.Hello(heloHostname); err != nil {
		return err
	}
	if ok, _ := c.Extension("STARTTLS"); ok {
		config := &tls.Config{ServerName: hostname}
		if err = c.StartTLS(config); err != nil {
			return err
		}
	}
	if a != nil {
		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(a); err != nil {
				return err
			}
		}
	}
	if err = c.Mail(from.Address); err != nil {
		return err
	}
	for _, addr := range to {
		if err = c.Rcpt(addr); err != nil {
			return err
		}
	}
	w, err := c.Data()
	if err != nil {
		return err
	}
	_, err = w.Write(raw)
	if err != nil {
		return err
	}
	err = w.Close()
	if err != nil {
		return err
	}
	return c.Quit()
}