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() }
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 }
func addRcpt(c *smtp.Client, address []string) error { for _, addr := range address { if err := c.Rcpt(addr); err != nil { return err } } return nil }
func sendMail(c *conf.ConfigFile, e Envelope) error { var addr string var err error var conn *smtp.Client addr, _ = c.GetString("main", "smtp") conn, err = smtp.Dial(addr) if err != nil { return err } if err = conn.Mail(e.Sender); err != nil { return err } for _, addr := range e.Recipients { if err = conn.Rcpt(addr); err != nil { return err } } w, err := conn.Data() if err != nil { return err } io.Copy(w, serializeMail(e)) conn.Quit() return nil }
func handleDATA(rec *SMTPRecord, c *smtp.Client, proxy *SMTPSession) error { proxy.Reply(354, "Go Ahead.") setDeadline(proxy.base.Conn, proxy.base.Timeouts.DataTimeout) buf := &bytes.Buffer{} reader := textproto.NewReader(proxy.reader).DotReader() _, err := io.CopyN(buf, reader, int64(proxy.base.MaxSize)) if err == io.EOF || err == nil { proxy.Reply(250, "Thank you.") bu := buf.Bytes() datawriter, err := c.Data() if err != nil { return err } n, err := datawriter.Write(bu) log.Debug("Data Submitted total written %d!", n) if err != nil { return err } err = datawriter.Close() if err != nil { return err } proxy.Reset() return nil } if err != nil { proxy.Reply(254, "Unable to recieve data.") return err } _, err = io.Copy(ioutil.Discard, reader) proxy.Reply(552, fmt.Sprintf("Message exceeded max message size of %d bytes", proxy.base.MaxSize)) if err != nil { return err } return nil }
func SendEmail(address string, from string, toArray []string, subject string, message []byte) (string, *gkerr.GkErrDef) { var err error var conn *smtp.Client var dataWriter io.WriteCloser var gkErr *gkerr.GkErrDef var sendId string conn, err = smtp.Dial(address) if err != nil { gkErr = gkerr.GenGkErr("smtp.Dial", err, ERROR_ID_SMTP_DIAL) return "", gkErr } conn.Mail(from) for _, adr := range toArray { conn.Rcpt(adr) } dataWriter, err = conn.Data() if err != nil { gkErr = gkerr.GenGkErr("conn.Data", err, ERROR_ID_SMTP_DATA) return "", gkErr } defer dataWriter.Close() buf := bytes.NewBufferString("From: " + from + "\nTo: " + toArray[0] + "\nSubject: " + subject + "\n") _, err = buf.WriteTo(dataWriter) if err != nil { gkErr = gkerr.GenGkErr("buf.WriteTo", err, ERROR_ID_SMTP_WRITE) return "", gkErr } buf = bytes.NewBufferString(string(message)) _, err = buf.WriteTo(dataWriter) if err != nil { gkErr = gkerr.GenGkErr("buf.WriteTo", err, ERROR_ID_SMTP_WRITE) return "", gkErr } err = conn.Quit() if err != nil { localError := fmt.Sprintf("%v", err) if strings.Index(localError, "Ok") != -1 && strings.Index(localError, "queued as") != -1 { sendId = localError } else { gkErr = gkerr.GenGkErr("conn.Quit", err, ERROR_ID_SMTP_QUIT) //gklog.LogTrace(fmt.Sprintf("smtp quit %T [%v] %v",err, err, gkErr)) return "", gkErr } } return sendId, nil }
func send(c *smtp.Client, m *mail.Message) error { if err := c.Mail(config.Message_From); err != nil { return fmt.Errorf("while setting From `%s`: %s", config.Message_From, err) } if config.ScanMessage { for _, i := range []string{"To", "Cc", "Bcc"} { if 0 == len(m.Header[i]) { continue } if l, err := m.Header.AddressList(i); err != nil { fmt.Fprintf(os.Stderr, "ScanMessage: Could not parse recipients in %s `%s`; %s", i, l, err) } else { for _, v := range l { config.Message_To = append(config.Message_To, v.Address) } } } if 0 == len(config.Message_To) { fmt.Fprintln(os.Stderr, "ScanMessage: No recipients found in message-body") } } for _, to := range config.Message_To { if err := c.Rcpt(to); err != nil { return fmt.Errorf("while setting Recipient `%s`: %s", to, err) } } w, err := c.Data() if err != nil { return fmt.Errorf("while setting Data: %s", err) } var s = "" for k, h := range m.Header { for _, v := range h { s += k + ": " + v + "\r\n" } } b := bytes.Buffer{} b.ReadFrom(m.Body) if _, err := w.Write([]byte(s + "\r\n" + b.String())); err != nil { return fmt.Errorf("while sending message: %s", err) } if err = w.Close(); err != nil { return fmt.Errorf("while closing message: %s", err) } if err = c.Quit(); err != nil { return fmt.Errorf("while closing connection: %s", err) } return nil }
// rcpt parses the specified list of RFC 5322 addresses // and calls smtp.Client.Rcpt() with each one. func rcpt(c *smtp.Client, addresses []string) error { for _, rcptAddr := range addresses { parsedAddr, err := parseAddress(rcptAddr) if err != nil { return err } if err = c.Rcpt(parsedAddr); err != nil { return err } } return nil }
// 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 }
// Attempt to send the specified message to the specified client. func (h *Host) deliverToMailServer(c *smtp.Client, m *Message) error { r, err := h.storage.GetMessageBody(m) if err != nil { return err } defer r.Close() r, err = dkimSigned(m.From, r, h.config) if err != nil { return err } if err := c.Mail(m.From); err != nil { return err } for _, t := range m.To { if err := c.Rcpt(t); err != nil { return err } } w, err := c.Data() if err != nil { return err } defer w.Close() if _, err := io.Copy(w, r); err != nil { return err } return nil }
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 }
// Send send message through the client func Send(c *smtp.Client, message *Message) (err error) { data, err := message.RenderData() if err != nil { return } // if err = c.Reset(); err != nil { // return // } if err = c.Mail(message.From); err != nil { return } if err = addRcpt(c, message.To); err != nil { return } if err = addRcpt(c, message.Cc); err != nil { return } if err = addRcpt(c, message.Bcc); err != nil { return } w, err := c.Data() if err != nil { return } defer w.Close() _, err = w.Write(data) return }
func (mailer *RecMailer) processOneRecord(id string, email string, w io.Writer, smtpClient *smtp.Client, httpClient *http.Client) int { var ( recResponse RecResponse ) fullUrl := fmt.Sprintf(mailer.Config.RecUrl, id) resp, err := httpClient.Get(fullUrl) if err != nil { fmt.Fprintf(w, "Unable to get URL %s\n", fullUrl) fmt.Println(err) resp.Body.Close() return 1 } readBytes, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { fmt.Fprintf(w, "Unable to read from URL %s\n", fullUrl) return 1 } err = json.Unmarshal(readBytes, &recResponse) if err != nil { fmt.Fprintf(w, "Unable to parse JSON http resp for user %s\n", id) fmt.Println(err) return 1 } if len(recResponse.Suggestions) == 0 { fmt.Fprintf(w, "No recommendations for user %s\n", id) return 1 } // If there's no thumbnail, use a blank gif for recIndex := 0; recIndex < len(recResponse.Suggestions); recIndex++ { if len(recResponse.Suggestions[recIndex].Thumbnail.Url) == 0 { recResponse.Suggestions[recIndex].Thumbnail.Url = "http://graphics8.nytimes.com/images/misc/spacer.gif" } } //emails := make([]string, 1) //emails[0] = email localTime := time.Now() dateStr := localTime.Format(time.RFC1123Z) edata := new(EmailData) edata.FromAddress = mailer.Config.EnvelopeFrom edata.ToAddress = email edata.Subject = "Recommendations for you" edata.RecResponse = recResponse edata.Date = dateStr edata.HumanDate = fmt.Sprintf("%s %d, %d", localTime.Month(), localTime.Day(), localTime.Year()) buff := new(bytes.Buffer) mailer.Template.Execute(buff, edata) //err = smtp.SendMail(mailer.Config.SmtpServer, nil, mailer.Config.SmtpFrom, emails, buff.Bytes()) errReset := smtpClient.Reset() if errReset != nil { fmt.Printf("There was an error sending for user %s\n", id) fmt.Println(errReset) return 1 } errMail := smtpClient.Mail(mailer.Config.SmtpFrom) if errMail != nil { fmt.Printf("There was an error sending for user %s\n", id) fmt.Println(errMail) return 1 } errRcpt := smtpClient.Rcpt(email) if errRcpt != nil { fmt.Printf("There was an error sending for user %s\n", id) fmt.Println(errRcpt) return 1 } smtpWriter, errData := smtpClient.Data() if errData != nil { fmt.Printf("There was an error sending for user %s\n", id) fmt.Println(errData) return 1 } smtpWriter.Write(buff.Bytes()) smtpWriter.Close() /* if err != nil { fmt.Printf("There was an error sending for user %s\n", id) fmt.Println(err) return 1 } */ fmt.Fprintf(w, "Success for %s, %s\n", id, email) return 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() }
func (es *EmailDeliverer) Deliver(alertCtx AlertContext, alertConf model.AlertConfig) error { rcptRaw, ok := alertConf.Settings["recipient"] if !ok { return fmt.Errorf("missing email address") } evergreen.Logger.Logf(slogger.INFO, "Sending email to %v", rcptRaw) var rcpt string if rcpt, ok = rcptRaw.(string); !ok { return fmt.Errorf("email address must be a string") } var err error subject := getSubject(alertCtx) body, err := es.getBody(alertCtx) if err != nil { return err } var c *smtp.Client if es.UseSSL { tlsCon, err := tls.Dial("tcp", fmt.Sprintf("%v:%v", es.Server, es.Port), &tls.Config{}) if err != nil { return err } c, err = smtp.NewClient(tlsCon, es.Server) } else { c, err = smtp.Dial(fmt.Sprintf("%v:%v", es.Server, es.Port)) } if err != nil { return err } if es.Username != "" { err = c.Auth(smtp.PlainAuth("", es.Username, es.Password, es.Server)) if err != nil { return err } } // Set the sender from := mail.Address{"Evergreen Alerts", es.From} err = c.Mail(es.From) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error establishing mail sender (%v): %v", es.From, err) return err } err = c.Rcpt(rcpt) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error establishing mail recipient (%v): %v", rcpt, err) return err } // Send the email body. wc, err := c.Data() if err != nil { return err } defer wc.Close() // set header information header := make(map[string]string) header["From"] = from.String() header["To"] = rcpt header["Subject"] = encodeRFC2047(subject) header["MIME-Version"] = "1.0" header["Content-Type"] = "text/html; charset=\"utf-8\"" header["Content-Transfer-Encoding"] = "base64" message := "" for k, v := range header { message += fmt.Sprintf("%s: %s\r\n", k, v) } message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body)) // write the body buf := bytes.NewBufferString(message) if _, err = buf.WriteTo(wc); err != nil { return err } return nil }
// 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 }
/* Connects an SMTP server (usually localhost:25 in prod) and uses that to send an email with the body encoded in base64. */ func (self SmtpMailer) SendMail(recipients []string, subject, body string) error { // 'recipients' is expected a comma-separated list of emails in either of // these formats: // - [email protected] // - Bob Smith <*****@*****.**> var c *smtp.Client var err error if self.UseSSL { tlsCon, err := tls.Dial("tcp", fmt.Sprintf("%v:%v", self.Server, self.Port), &tls.Config{}) if err != nil { return err } c, err = smtp.NewClient(tlsCon, self.Server) } else { c, err = smtp.Dial(fmt.Sprintf("%v:%v", self.Server, self.Port)) } if err != nil { return err } if self.Username != "" { err = c.Auth(smtp.PlainAuth("", self.Username, self.Password, self.Server)) if err != nil { return err } } // Set the sender from := mail.Address{"Evergreen Alerts", self.From} err = c.Mail(self.From) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error establishing mail sender (%v): %v", self.From, err) return err } // Set the recipient for _, recipient := range recipients { err = c.Rcpt(recipient) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error establishing mail recipient (%v): %v", recipient, err) return err } } // Send the email body. wc, err := c.Data() if err != nil { return err } defer wc.Close() // set header information header := make(map[string]string) header["From"] = from.String() header["To"] = strings.Join(recipients, ", ") header["Subject"] = encodeRFC2047(subject) header["MIME-Version"] = "1.0" header["Content-Type"] = "text/html; charset=\"utf-8\"" header["Content-Transfer-Encoding"] = "base64" message := "" for k, v := range header { message += fmt.Sprintf("%s: %s\r\n", k, v) } message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body)) // write the body buf := bytes.NewBufferString(message) if _, err = buf.WriteTo(wc); err != nil { return err } return nil }
// 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() } }
// 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 }
// 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 }
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") } }
func SendMail(to []string, subject, body string) (err error) { if addr == "" { // skip if not configured return nil } // create client var conn net.Conn var client *smtp.Client if conn, err = net.Dial("tcp", addr+":25"); err != nil { return logError(err, to, subject, body) } if client, err = smtp.NewClient(conn, ""); err != nil { return logError(err, to, subject, body) } defer client.Quit() msg := fmt.Sprintf("From: %s\n", from) if err = client.Mail(from); err != nil { return logError(err, to, subject, body) } for _, addr := range to { msg += fmt.Sprintf("To: %s\n", addr) if err = client.Rcpt(addr); err != nil { return logError(err, to, subject, body) } } for _, addr := range cc { msg += fmt.Sprintf("Cc: %s\n", addr) if err = client.Rcpt(addr); err != nil { return logError(err, to, subject, body) } } msg += fmt.Sprintf("Date: %s\n", time.Now().String()) msg += fmt.Sprintf("Subject: %s\n\n", subject) msg += body w, err := client.Data() if err != nil { return logError(err, to, subject, body) } fmt.Fprintf(w, msg) w.Close() log.Printf("[SMTP] SENT: %v '%s'", to, subject) return nil }
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 := ¶mEmail{ 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 }
// 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() }
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 }