func yesNo(b bool) string {
	if b {
		return "yes"
	} else {
		return "no"
	}
}
yesNo translates a true/false boolean value into a yes/no setting suitable for the Mailgun API.
package mailgun
import (
	"encoding/json"
	"errors"
	"io"
	"time"
)
const MaxNumberOfRecipients = 1000
type Message struct {
	to                []string
	tags              []string
	campaigns         []string
	dkim              bool
	deliveryTime      *time.Time
	attachments       []string
	readerAttachments []ReaderAttachment
	inlines           []string
	readerInlines     []ReaderAttachment
	testMode           bool
	tracking           bool
	trackingClicks     bool
	trackingOpens      bool
	headers            map[string]string
	variables          map[string]string
	recipientVariables map[string]map[string]interface{}
	dkimSet           bool
	trackingSet       bool
	trackingClicksSet bool
	trackingOpensSet  bool
	specific features
	mg       Mailgun
}
type ReaderAttachment struct {
	Filename   string
	ReadCloser io.ReadCloser
}
type StoredMessage struct {
	Recipients        string             `json:"recipients"`
	Sender            string             `json:"sender"`
	From              string             `json:"from"`
	Subject           string             `json:"subject"`
	BodyPlain         string             `json:"body-plain"`
	StrippedText      string             `json:"stripped-text"`
	StrippedSignature string             `json:"stripped-signature"`
	BodyHtml          string             `json:"body-html"`
	StrippedHtml      string             `json:"stripped-html"`
	Attachments       []StoredAttachment `json:"attachments"`
	MessageUrl        string             `json:"message-url"`
	ContentIDMap      map[string]struct {
		Url         string `json:"url"`
		ContentType string `json:"content-type"`
		Name        string `json:"name"`
		Size        int64  `json:"size"`
	} `json:"content-id-map"`
	MessageHeaders [][]string `json:"message-headers"`
}
type StoredAttachment struct {
	Size        int    `json:"size"`
	Url         string `json:"url"`
	Name        string `json:"name"`
	ContentType string `json:"content-type"`
}
type StoredMessageRaw struct {
	Recipients string `json:"recipients"`
	Sender     string `json:"sender"`
	From       string `json:"from"`
	Subject    string `json:"subject"`
	BodyMime   string `json:"body-mime"`
}
type plainMessage struct {
	from    string
	cc      []string
	bcc     []string
	subject string
	text    string
	html    string
}
type mimeMessage struct {
	body io.ReadCloser
}
type sendMessageResponse struct {
	Message string `json:"message"`
	Id      string `json:"id"`
}
type features interface {
	addCC(string)
	addBCC(string)
	setHtml(string)
	addValues(*formDataPayload)
	isValid() bool
	endpoint() string
	recipientCount() int
}
func NewMessage(from string, subject string, text string, to ...string) *Message {
	return &Message{
		specific: &plainMessage{
			from:    from,
			subject: subject,
			text:    text,
		},
		to: to,
	}
}
func (mg *MailgunImpl) NewMessage(from, subject, text string, to ...string) *Message {
	return &Message{
		specific: &plainMessage{
			from:    from,
			subject: subject,
			text:    text,
		},
		to: to,
		mg: mg,
	}
}
func NewMIMEMessage(body io.ReadCloser, to ...string) *Message {
	return &Message{
		specific: &mimeMessage{
			body: body,
		},
		to: to,
	}
}
func (mg *MailgunImpl) NewMIMEMessage(body io.ReadCloser, to ...string) *Message {
	return &Message{
		specific: &mimeMessage{
			body: body,
		},
		to: to,
		mg: mg,
	}
}
func (m *Message) AddReaderAttachment(filename string, readCloser io.ReadCloser) {
	ra := ReaderAttachment{Filename: filename, ReadCloser: readCloser}
	m.readerAttachments = append(m.readerAttachments, ra)
}
func (m *Message) AddAttachment(attachment string) {
	m.attachments = append(m.attachments, attachment)
}
func (m *Message) AddReaderInline(filename string, readCloser io.ReadCloser) {
	ra := ReaderAttachment{Filename: filename, ReadCloser: readCloser}
	m.readerInlines = append(m.readerInlines, ra)
}
func (m *Message) AddInline(inline string) {
	m.inlines = append(m.inlines, inline)
}
func (m *Message) AddRecipient(recipient string) error {
	return m.AddRecipientAndVariables(recipient, nil)
}
func (m *Message) AddRecipientAndVariables(r string, vars map[string]interface{}) error {
	if m.RecipientCount() >= MaxNumberOfRecipients {
		_, _, err := m.send()
		if err != nil {
			return err
		}
		m.to = make([]string, len(m.to))
		m.recipientVariables = make(map[string]map[string]interface{}, len(m.recipientVariables))
	}
	m.to = append(m.to, r)
	if vars != nil {
		if m.recipientVariables == nil {
			m.recipientVariables = make(map[string]map[string]interface{})
		}
		m.recipientVariables[r] = vars
	}
	return nil
}
func (m *Message) RecipientCount() int {
	return len(m.to) + m.specific.recipientCount()
}
func (pm *plainMessage) recipientCount() int {
	return len(pm.bcc) + len(pm.cc)
}
func (mm *mimeMessage) recipientCount() int {
	return 10
}
func (m *Message) send() (string, string, error) {
	return m.mg.Send(m)
}
func (m *Message) SetReplyTo(recipient string) {
	m.AddHeader("Reply-To", recipient)
}
func (m *Message) AddCC(recipient string) {
	m.specific.addCC(recipient)
}
func (pm *plainMessage) addCC(r string) {
	pm.cc = append(pm.cc, r)
}
func (mm *mimeMessage) addCC(_ string) {}
func (m *Message) AddBCC(recipient string) {
	m.specific.addBCC(recipient)
}
func (pm *plainMessage) addBCC(r string) {
	pm.bcc = append(pm.bcc, r)
}
func (mm *mimeMessage) addBCC(_ string) {}
func (m *Message) SetHtml(html string) {
	m.specific.setHtml(html)
}
func (pm *plainMessage) setHtml(h string) {
	pm.html = h
}
func (mm *mimeMessage) setHtml(_ string) {}
func (m *Message) AddTag(tag string) {
	m.tags = append(m.tags, tag)
}
func (m *Message) AddCampaign(campaign string) {
	m.campaigns = append(m.campaigns, campaign)
}
func (m *Message) SetDKIM(dkim bool) {
	m.dkim = dkim
	m.dkimSet = true
}
func (m *Message) EnableTestMode() {
	m.testMode = true
}
func (m *Message) SetDeliveryTime(dt time.Time) {
	pdt := new(time.Time)
	*pdt = dt
	m.deliveryTime = pdt
}
func (m *Message) SetTracking(tracking bool) {
	m.tracking = tracking
	m.trackingSet = true
}
func (m *Message) SetTrackingClicks(trackingClicks bool) {
	m.trackingClicks = trackingClicks
	m.trackingClicksSet = true
}
func (m *Message) SetTrackingOpens(trackingOpens bool) {
	m.trackingOpens = trackingOpens
	m.trackingOpensSet = true
}
func (m *Message) AddHeader(header, value string) {
	if m.headers == nil {
		m.headers = make(map[string]string)
	}
	m.headers[header] = value
}
func (m *Message) AddVariable(variable string, value interface{}) error {
	j, err := json.Marshal(value)
	if err != nil {
		return err
	}
	if m.variables == nil {
		m.variables = make(map[string]string)
	}
	m.variables[variable] = string(j)
	return nil
}
func (m *MailgunImpl) Send(message *Message) (mes string, id string, err error) {
	if !isValid(message) {
		err = errors.New("Message not valid")
	} else {
		payload := newFormDataPayload()
		message.specific.addValues(payload)
		for _, to := range message.to {
			payload.addValue("to", to)
		}
		for _, tag := range message.tags {
			payload.addValue("o:tag", tag)
		}
		for _, campaign := range message.campaigns {
			payload.addValue("o:campaign", campaign)
		}
		if message.dkimSet {
			payload.addValue("o:dkim", yesNo(message.dkim))
		}
		if message.deliveryTime != nil {
			payload.addValue("o:deliverytime", formatMailgunTime(message.deliveryTime))
		}
		if message.testMode {
			payload.addValue("o:testmode", "yes")
		}
		if message.trackingSet {
			payload.addValue("o:tracking", yesNo(message.tracking))
		}
		if message.trackingClicksSet {
			payload.addValue("o:tracking-clicks", yesNo(message.trackingClicks))
		}
		if message.trackingOpensSet {
			payload.addValue("o:tracking-opens", yesNo(message.trackingOpens))
		}
		if message.headers != nil {
			for header, value := range message.headers {
				payload.addValue("h:"+header, value)
			}
		}
		if message.variables != nil {
			for variable, value := range message.variables {
				payload.addValue("v:"+variable, value)
			}
		}
		if message.recipientVariables != nil {
			j, err := json.Marshal(message.recipientVariables)
			if err != nil {
				return "", "", err
			}
			payload.addValue("recipient-variables", string(j))
		}
		if message.attachments != nil {
			for _, attachment := range message.attachments {
				payload.addFile("attachment", attachment)
			}
		}
		if message.readerAttachments != nil {
			for _, readerAttachment := range message.readerAttachments {
				payload.addReadCloser("attachment", readerAttachment.Filename, readerAttachment.ReadCloser)
			}
		}
		if message.inlines != nil {
			for _, inline := range message.inlines {
				payload.addFile("inline", inline)
			}
		}
		if message.readerInlines != nil {
			for _, readerAttachment := range message.readerInlines {
				payload.addReadCloser("inline", readerAttachment.Filename, readerAttachment.ReadCloser)
			}
		}
		r := newHTTPRequest(generateApiUrl(m, message.specific.endpoint()))
		r.setClient(m.Client())
		r.setBasicAuth(basicAuthUser, m.ApiKey())
		var response sendMessageResponse
		err = postResponseFromJSON(r, payload, &response)
		if err == nil {
			mes = response.Message
			id = response.Id
		}
	}
	return
}
func (pm *plainMessage) addValues(p *formDataPayload) {
	p.addValue("from", pm.from)
	p.addValue("subject", pm.subject)
	p.addValue("text", pm.text)
	for _, cc := range pm.cc {
		p.addValue("cc", cc)
	}
	for _, bcc := range pm.bcc {
		p.addValue("bcc", bcc)
	}
	if pm.html != "" {
		p.addValue("html", pm.html)
	}
}
func (mm *mimeMessage) addValues(p *formDataPayload) {
	p.addReadCloser("message", "message.mime", mm.body)
}
func (pm *plainMessage) endpoint() string {
	return messagesEndpoint
}
func (mm *mimeMessage) endpoint() string {
	return mimeMessagesEndpoint
}