Esempio n. 1
0
// 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
}
Esempio n. 2
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()
	}
}
Esempio n. 3
0
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
}