Skip to content

Instantly share code, notes, and snippets.

@c4milo
Last active August 29, 2015 14:22
Show Gist options
  • Save c4milo/9a94c1bd0583abe8c12e to your computer and use it in GitHub Desktop.
Save c4milo/9a94c1bd0583abe8c12e to your computer and use it in GitHub Desktop.
// Package mailer wraps Mandrill's REST API only for sending emails using templates.
package mailer
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
// Mandrill's REST API getting started guide: https://mandrillapp.com/api/docs/index.JSON.html
// Mandrill's
var (
endpoint = "https://mandrillapp.com/api/1.0/messages/send-template.json"
apikey = "FILL ME"
)
type Content struct {
Name string `json:"name"`
Content string `json:"content"`
}
type Recipient struct {
Email string `json:"email"`
Name string `json:"name,omitempty"`
}
type Message struct {
To []Recipient `json:"to"`
Variables []Content `json:"global_merge_vars,omitempty"`
}
// Request represents Mandrill's send-template request type.
type Request struct {
Key string `json:"key"`
TemplateName string `json:"template_name"`
TemplateContent []Content `json:"template_content"`
Message Message `json:"message"`
}
// Response defines Mandrill's non-error response type.
type Response struct {
Status string
Email string
RejectReason string `json:"reject_reason"`
ID string `json:"_id"`
}
// Error defines Mandrill's API error type.
type Error struct {
Status string
Code int
Name string
Message string
}
// Error returns a string representation of the error.
func (e *Error) Error() string {
return fmt.Sprintf("mailer: status=%s code=%d name=%s message=%s",
e.Status, e.Code, e.Name, e.Message)
}
// Send invokes Mandrill API to send an email.
func Send(message Request) ([]*Response, error) {
message.Key = apikey
// Mandrill API requires template content even if a template already provides it.
if len(message.TemplateContent) == 0 {
message.TemplateContent = []Content{{Name: "", Content: ""}}
}
b, err := json.Marshal(message)
if err != nil {
return nil, err
}
//log.Printf("[DEBUG] %s", string(b))
resp, err := http.Post(endpoint, "application/json", bytes.NewBuffer(b))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
apiError := new(Error)
err = json.NewDecoder(resp.Body).Decode(apiError)
if err != nil {
return nil, err
}
return nil, apiError
}
response := make([]*Response, len(message.Message.To))
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}
return response, nil
}
package mailer
import (
"testing"
"github.com/hooklift/assert"
)
func TestSend(t *testing.T) {
// Sets Mandrill test API Key
apikey = "fill me out"
r := Request{}
r.TemplateName = "test-template-use-for-integration-tests-in-uaa"
r.Message = Message{
To: []Recipient{
{Email: "[email protected]"},
},
Variables: []Content{
{Name: "USERNAME", Content: "c4milo"},
{Name: "VERIFICATION_CODE", Content: "ASDFAF123415"},
},
}
resp, err := Send(r)
assert.Ok(t, err)
assert.Cond(t, len(resp) > 0, "No responses received, there should be one response.")
rr := resp[0]
assert.Cond(t, rr.RejectReason == "", "Reject reason should be empty.")
assert.Equals(t, "[email protected]", rr.Email)
assert.Equals(t, "sent", rr.Status)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment