Created
November 2, 2012 18:09
-
-
Save larzconwell/4003269 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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