Example #1
0
func main() {
	to := []string{
		"*****@*****.**",
		"*****@*****.**",
	}
	headerTo := strings.Join(to, ",")

	cc := []string{
		"*****@*****.**",
		"*****@*****.**",
	}

	bcc := []string{
		"*****@*****.**",
		"*****@*****.**",
	}

	content := sp.Content{
		From:    "*****@*****.**",
		Subject: "cc/bcc example message",
		Text:    "This is a cc/bcc example",
	}

	tx := &sp.Transmission{
		Recipients: []sp.Recipient{},
	}

	if len(to) > 0 {
		for _, t := range to {
			tx.Recipients = append(tx.Recipients.([]sp.Recipient), sp.Recipient{
				Address: sp.Address{Email: t, HeaderTo: headerTo},
			})
		}
	}

	if len(cc) > 0 {
		for _, c := range cc {
			tx.Recipients = append(tx.Recipients.([]sp.Recipient), sp.Recipient{
				Address: sp.Address{Email: c, HeaderTo: headerTo},
			})
		}
		// add cc header to content
		if content.Headers == nil {
			content.Headers = map[string]string{}
		}
		content.Headers["cc"] = strings.Join(cc, ",")
	}

	if len(bcc) > 0 {
		for _, b := range bcc {
			tx.Recipients = append(tx.Recipients.([]sp.Recipient), sp.Recipient{
				Address: sp.Address{Email: b, HeaderTo: headerTo},
			})
		}
	}

	tx.Content = content

	jsonBytes, err := json.Marshal(tx)
	if err != nil {
		panic(err)
	}
	fmt.Fprintln(os.Stdout, string(jsonBytes))

}
Example #2
0
func main() {
	flag.Parse()

	if *help {
		flag.Usage()
		os.Exit(0)
	}

	if len(to) <= 0 {
		log.Fatal("SUCCESS: send mail to nobody!\n")
	}

	apiKey := os.Getenv("SPARKPOST_API_KEY")
	if strings.TrimSpace(apiKey) == "" && *dryrun == false {
		log.Fatal("FATAL: API key not found in environment!\n")
	}

	hasHtml := strings.TrimSpace(*htmlFlag) != ""
	hasText := strings.TrimSpace(*textFlag) != ""
	hasRFC822 := strings.TrimSpace(*rfc822Flag) != ""
	hasSubs := strings.TrimSpace(*subsFlag) != ""

	// rfc822 must be specified by itself, i.e. no text or html
	if hasRFC822 && (hasHtml || hasText) {
		log.Fatal("FATAL: --rfc822 cannot be combined with --html or --text!\n")
	} else if !hasRFC822 && !hasHtml && !hasText {
		log.Fatal("FATAL: must specify one of --html or --text!\n")
	}

	cfg := &sp.Config{ApiKey: apiKey}
	if strings.TrimSpace(*url) != "" {
		if !strings.HasPrefix(*url, "https://") {
			log.Fatal("FATAL: base url must be https!\n")
		}
		cfg.BaseUrl = *url
	}
	if *httpDump {
		cfg.Verbose = true
	}

	var sparky sp.Client
	err := sparky.Init(cfg)
	if err != nil {
		log.Fatalf("SparkPost client init failed: %s\n", err)
	}

	content := sp.Content{
		From:    *from,
		Subject: *subject,
	}

	if hasRFC822 {
		// these are pulled from the raw message
		content.From = nil
		content.Subject = ""
		if strings.HasPrefix(*rfc822Flag, "/") || strings.HasPrefix(*rfc822Flag, "./") {
			// read file to get raw message
			rfc822Bytes, err := ioutil.ReadFile(*rfc822Flag)
			if err != nil {
				log.Fatal(err)
			}
			content.EmailRFC822 = string(rfc822Bytes)
		} else {
			// raw message string passed on command line
			content.EmailRFC822 = *rfc822Flag
		}
	}

	if hasHtml {
		if strings.HasPrefix(*htmlFlag, "/") || strings.HasPrefix(*htmlFlag, "./") {
			// read file to get html
			htmlBytes, err := ioutil.ReadFile(*htmlFlag)
			if err != nil {
				log.Fatal(err)
			}
			content.HTML = string(htmlBytes)
		} else {
			// html string passed on command line
			content.HTML = *htmlFlag
		}
	}

	if hasText {
		if strings.HasPrefix(*textFlag, "/") || strings.HasPrefix(*textFlag, "./") {
			// read file to get text
			textBytes, err := ioutil.ReadFile(*textFlag)
			if err != nil {
				log.Fatal(err)
			}
			content.Text = string(textBytes)
		} else {
			// text string passed on command line
			content.Text = *textFlag
		}
	}

	if len(images) > 0 {
		for _, imgStr := range images {
			img := strings.SplitN(imgStr, ":", 3)
			if len(img) != 3 {
				log.Fatalf("--img format is mimetype:cid:path")
			}
			imgBytes, err := ioutil.ReadFile(img[2])
			if err != nil {
				log.Fatal(err)
			}
			iimg := sp.InlineImage{
				MIMEType: img[0],
				Filename: img[1],
				B64Data:  base64.StdEncoding.EncodeToString(imgBytes),
			}
			content.InlineImages = append(content.InlineImages, iimg)
		}
	}

	if len(attachments) > 0 {
		for _, attStr := range attachments {
			att := strings.SplitN(attStr, ":", 3)
			if len(att) != 3 {
				log.Fatalf("--attach format is mimetype:name:path")
			}
			attBytes, err := ioutil.ReadFile(att[2])
			if err != nil {
				log.Fatal(err)
			}
			attach := sp.Attachment{
				MIMEType: att[0],
				Filename: att[1],
				B64Data:  base64.StdEncoding.EncodeToString(attBytes),
			}
			content.Attachments = append(content.Attachments, attach)
		}
	}

	tx := &sp.Transmission{}

	var subJson *json.RawMessage
	if hasSubs {
		var subsBytes []byte
		if strings.HasPrefix(*subsFlag, "/") || strings.HasPrefix(*subsFlag, "./") {
			// read file to get substitution data
			subsBytes, err = ioutil.ReadFile(*subsFlag)
			if err != nil {
				log.Fatal(err)
			}
		} else {
			subsBytes = []byte(*subsFlag)
		}

		subJson = &json.RawMessage{}
		err = json.Unmarshal(subsBytes, subJson)
		if err != nil {
			log.Fatal(err)
		}
	}

	headerTo := strings.Join(to, ",")

	tx.Recipients = []sp.Recipient{}
	for _, r := range to {
		var recip sp.Recipient = sp.Recipient{Address: sp.Address{Email: r, HeaderTo: headerTo}}
		if hasSubs {
			recip.SubstitutionData = subJson
		}
		tx.Recipients = append(tx.Recipients.([]sp.Recipient), recip)
	}

	if len(cc) > 0 {
		for _, r := range cc {
			var recip sp.Recipient = sp.Recipient{Address: sp.Address{Email: r, HeaderTo: headerTo}}
			if hasSubs {
				recip.SubstitutionData = subJson
			}
			tx.Recipients = append(tx.Recipients.([]sp.Recipient), recip)
		}
		if content.Headers == nil {
			content.Headers = map[string]string{}
		}
		content.Headers["cc"] = strings.Join(cc, ",")
	}

	if len(bcc) > 0 {
		for _, r := range bcc {
			var recip sp.Recipient = sp.Recipient{Address: sp.Address{Email: r, HeaderTo: headerTo}}
			if hasSubs {
				recip.SubstitutionData = subJson
			}
			tx.Recipients = append(tx.Recipients.([]sp.Recipient), recip)
		}
	}

	if len(headers) > 0 {
		if content.Headers == nil {
			content.Headers = map[string]string{}
		}
		hb := regexp.MustCompile(`:\s*`)
		for _, hstr := range headers {
			hra := hb.Split(hstr, 2)
			content.Headers[hra[0]] = hra[1]
		}
	}

	tx.Content = content

	if strings.TrimSpace(*sendDelay) != "" {
		if tx.Options == nil {
			tx.Options = &sp.TxOptions{}
		}
		dur, err := time.ParseDuration(*sendDelay)
		if err != nil {
			log.Fatal(err)
		}
		start := sp.RFC3339(time.Now().Add(dur))
		tx.Options.StartTime = &start
	}

	if *inline != false {
		if tx.Options == nil {
			tx.Options = &sp.TxOptions{}
		}
		tx.Options.InlineCSS = true
	}

	if *dryrun != false {
		jsonBytes, err := json.Marshal(tx)
		if err != nil {
			log.Fatal(err)
		}
		os.Stdout.Write(jsonBytes)
		os.Exit(0)
	}

	id, req, err := sparky.Send(tx)
	if err != nil {
		log.Fatal(err)
	}

	if *httpDump {
		if reqDump, ok := req.Verbose["http_requestdump"]; ok {
			os.Stdout.Write([]byte(reqDump))
		} else {
			os.Stdout.Write([]byte("*** No request dump available! ***\n\n"))
		}

		if resDump, ok := req.Verbose["http_responsedump"]; ok {
			os.Stdout.Write([]byte(resDump))
			os.Stdout.Write([]byte("\n"))
		} else {
			os.Stdout.Write([]byte("*** No response dump available! ***\n"))
		}
	} else {
		log.Printf("HTTP [%s] TX %s\n", req.HTTP.Status, id)
	}
}