Skip to content

Instantly share code, notes, and snippets.

@larzconwell
Created November 2, 2012 18:09
Show Gist options
  • Save larzconwell/4003269 to your computer and use it in GitHub Desktop.
Save larzconwell/4003269 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path"
"runtime"
"strings"
)
var apikey string
const emailContent string = `some email content here`
// A successful response
type ResponseSuccess struct {
Email string
Status string
}
type ResponsesSuccess []ResponseSuccess
// Implement stringer interface
func (res ResponsesSuccess) String() string {
str := ""
for _, r := range res {
str += fmt.Sprintf("%s: %s, ", r.Email, r.Status)
}
str = strings.Trim(str, ", ")
return str
}
// A unsuccessful response
type ResponseError struct {
Status string
Code int
Name string
Message string
}
// Implement error interface
func (res ResponseError) Error() string {
return fmt.Sprintf("%s[%d]: %s", res.Name, res.Code, res.Message)
}
// Contains a single email and name for a To address
type To struct {
Email string `json:"email"`
Name string `json:"name"`
}
// Contains a type, name and a byte slice for the attachment content
type Attachment struct {
Type string `json:"type"`
Name string `json:"name"`
Content []byte `json:"content"`
}
// Unexported struct containing main message information
type message struct {
Text string `json:"text"`
Subject string `json:"subject"`
FromEmail string `json:"from_email"`
FromName string `json:"from_name"`
To []To `json:"to"`
Attachments []Attachment `json:"attachments"`
}
// Contains API key for message and the message info
type Message struct {
Key string `json:"key"`
Data message `json:"message"`
Success chan ResponsesSuccess `json:"-"`
Error chan ResponseError `json:"-"`
}
// Return a new Message api with key, subject and body text set
func NewMessage(apikey, subject, text string) *Message {
msg := new(Message)
msg.Key = apikey
msg.Data.Subject = subject
msg.Data.Text = text
return msg
}
// Set the from address to the message
func (msg *Message) SetFrom(email, name string) {
msg.Data.FromEmail = email
msg.Data.FromName = name
}
// Add a To address to a message
func (msg *Message) AddTo(email, name string) (to To) {
to.Email = email
to.Name = name
msg.Data.To = append(msg.Data.To, to)
return
}
// Add a new Attachment to a message
func (msg *Message) AddAttachment(attachType, name string) (attach Attachment, err error) {
attach.Type = attachType
attach.Name = path.Base(name) // Just use the file name
contents, err := ioutil.ReadFile(name)
if err != nil {
return
}
attach.Content = contents
msg.Data.Attachments = append(msg.Data.Attachments, attach)
return
}
// Send the message to a request
func (msg *Message) Send(req *http.Request) {
// Create a client and make the given request
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
// Decode the response and send it to the corresponding channel
decoder := json.NewDecoder(res.Body)
if res.StatusCode == 200 {
success := ResponsesSuccess{}
decoder.Decode(&success)
msg.Success <- success
} else {
resErr := ResponseError{}
decoder.Decode(&resErr)
msg.Error <- resErr
}
}
// Parse flags
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
flag.StringVar(&apikey, "apikey", "", "API key to use")
flag.StringVar(&apikey, "a", "", "API key to use(shorthand)")
flag.Usage = func() {
fmt.Println("Usage:\n --apikey, -a <key> API key to use")
}
}
func main() {
flag.Parse()
// Ensure a API key is given somehow
if len(apikey) == 0 {
apikey = os.Getenv("MANDRILL_APIKEY")
if len(apikey) == 0 {
log.Fatal("Unable to retrieve API key for Mandrill")
}
}
// Create new message and set info
msg := NewMessage(apikey, "Junior Software Engineer position", emailContent)
msg.SetFrom("form email", "from name")
msg.AddTo("to email", "to name")
if _, err := msg.AddAttachment("text/plain", os.Args[0]+".go"); err != nil {
log.Fatal(err)
}
// Marshal message into JSON and create a reader for it
body, err := json.Marshal(msg)
if err != nil {
log.Fatal(err)
}
bodyReader := bytes.NewReader(body)
// Create new request
req, err := http.NewRequest("POST", "https://mandrillapp.com:443/api/1.0/messages/send.json", bodyReader)
if err != nil {
log.Fatal(err)
}
req.ContentLength = int64(len(body))
req.Header.Add("Content-Type", "application/json")
// Create buffered channels and send the message on a goroutine
msg.Success = make(chan ResponsesSuccess, 1)
msg.Error = make(chan ResponseError, 1)
go msg.Send(req)
// Block until we get a response and print it
select {
case success := <-msg.Success:
fmt.Println(success.String())
case resErr := <-msg.Error:
log.Fatal(resErr)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment