Exemplo n.º 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()
}
Exemplo n.º 2
0
// Attempt to connect to the specified server. The connection attempt is
// performed in a separate goroutine, allowing it to be aborted if the host
// queue is shut down.
func (h *Host) tryMailServer(server, hostname string) (*smtp.Client, error) {
	var (
		c    *smtp.Client
		err  error
		done = make(chan bool)
	)
	go func() {
		c, err = smtp.Dial(fmt.Sprintf("%s:25", server))
		close(done)
	}()
	select {
	case <-done:
	case <-h.stop:
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	if err := c.Hello(hostname); err != nil {
		return nil, err
	}
	if ok, _ := c.Extension("STARTTLS"); ok {
		config := &tls.Config{ServerName: server}
		if h.config.DisableSSLVerification {
			config.InsecureSkipVerify = true
		}
		if err := c.StartTLS(config); err != nil {
			return nil, err
		}
	}
	return c, nil
}
Exemplo n.º 3
0
func NewSmtpClient(addr string, a smtp.Auth, concurrency int) (client *SmtpClient, err error) {
	pool := make(chan *smtp.Client, concurrency)
	for i := 0; i < concurrency; i++ {
		var c *smtp.Client
		c, err = smtp.Dial(addr)
		if err != nil {
			return
		}
		if err = c.Hello("localhost"); err != nil {
			return
		}
		if ok, _ := c.Extension("STARTTLS"); ok {
			if err = c.StartTLS(nil); err != nil {
				return
			}
		}

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(a); err != nil {
				return
			}
		}

		pool <- c
	}

	client = &SmtpClient{pool, &sync.Mutex{}, false}

	return
}
Exemplo n.º 4
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")
	}
}
Exemplo n.º 5
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()
}