func generateApiUrlWithTarget(m Mailgun, endpoint, target string) string {
	tail := ""
	if target != "" {
		tail = fmt.Sprintf("/%s", target)
	}
	return fmt.Sprintf("%s%s", generateApiUrl(m, endpoint), tail)
}
generateApiUrlWithTarget works as generateApiUrl,
but consumes an additional resource parameter called 'target'.
package mailgun
import (
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)
var Debug = false
const (
	ApiBase                 = "https://api.mailgun.net/v3"
	messagesEndpoint        = "messages"
	mimeMessagesEndpoint    = "messages.mime"
	addressValidateEndpoint = "address/validate"
	addressParseEndpoint    = "address/parse"
	bouncesEndpoint         = "bounces"
	statsEndpoint           = "stats"
	domainsEndpoint         = "domains"
	tagsEndpoint            = "tags"
	campaignsEndpoint       = "campaigns"
	eventsEndpoint          = "events"
	credentialsEndpoint     = "credentials"
	unsubscribesEndpoint    = "unsubscribes"
	routesEndpoint          = "routes"
	webhooksEndpoint        = "webhooks"
	listsEndpoint           = "lists"
	basicAuthUser           = "api"
)
type Mailgun interface {
	ApiBase() string
	Domain() string
	ApiKey() string
	PublicApiKey() string
	Client() *http.Client
	SetClient(client *http.Client)
	Send(m *Message) (string, string, error)
	ValidateEmail(email string) (EmailVerification, error)
	ParseAddresses(addresses ...string) ([]string, []string, error)
	GetBounces(limit, skip int) (int, []Bounce, error)
	GetSingleBounce(address string) (Bounce, error)
	AddBounce(address, code, error string) error
	DeleteBounce(address string) error
	GetStats(limit int, skip int, startDate *time.Time, event ...string) (int, []Stat, error)
	GetTag(tag string) (TagItem, error)
	DeleteTag(tag string) error
	ListTags(*TagOptions) *TagIterator
	GetDomains(limit, skip int) (int, []Domain, error)
	GetSingleDomain(domain string) (Domain, []DNSRecord, []DNSRecord, error)
	CreateDomain(name string, smtpPassword string, spamAction string, wildcard bool) error
	DeleteDomain(name string) error
	GetCampaigns() (int, []Campaign, error)
	CreateCampaign(name, id string) error
	UpdateCampaign(oldId, name, newId string) error
	DeleteCampaign(id string) error
	GetComplaints(limit, skip int) (int, []Complaint, error)
	GetSingleComplaint(address string) (Complaint, error)
	GetStoredMessage(id string) (StoredMessage, error)
	GetStoredMessageRaw(id string) (StoredMessageRaw, error)
	DeleteStoredMessage(id string) error
	GetCredentials(limit, skip int) (int, []Credential, error)
	CreateCredential(login, password string) error
	ChangeCredentialPassword(id, password string) error
	DeleteCredential(id string) error
	GetUnsubscribes(limit, skip int) (int, []Unsubscription, error)
	GetUnsubscribesByAddress(string) (int, []Unsubscription, error)
	Unsubscribe(address, tag string) error
	RemoveUnsubscribe(string) error
	RemoveUnsubscribeWithTag(a, t string) error
	CreateComplaint(string) error
	DeleteComplaint(string) error
	GetRoutes(limit, skip int) (int, []Route, error)
	GetRouteByID(string) (Route, error)
	CreateRoute(Route) (Route, error)
	DeleteRoute(string) error
	UpdateRoute(string, Route) (Route, error)
	GetWebhooks() (map[string]string, error)
	CreateWebhook(kind, url string) error
	DeleteWebhook(kind string) error
	GetWebhookByType(kind string) (string, error)
	UpdateWebhook(kind, url string) error
	VerifyWebhookRequest(req *http.Request) (verified bool, err error)
	GetLists(limit, skip int, filter string) (int, []List, error)
	CreateList(List) (List, error)
	DeleteList(string) error
	GetListByAddress(string) (List, error)
	UpdateList(string, List) (List, error)
	GetMembers(limit, skip int, subfilter *bool, address string) (int, []Member, error)
	GetMemberByAddress(MemberAddr, listAddr string) (Member, error)
	CreateMember(merge bool, addr string, prototype Member) error
	CreateMemberList(subscribed *bool, addr string, newMembers []interface{}) error
	UpdateMember(Member, list string, prototype Member) (Member, error)
	DeleteMember(Member, list string) error
	NewMessage(from, subject, text string, to ...string) *Message
	NewMIMEMessage(body io.ReadCloser, to ...string) *Message
	NewEventIterator() *EventIterator
	ListEvents(*EventsOptions) *EventIterator
	PollEvents(*EventsOptions) *EventPoller
	SetAPIBase(url string)
}
type MailgunImpl struct {
	apiBase      string
	domain       string
	apiKey       string
	publicApiKey string
	client       *http.Client
	baseURL      string
}
func NewMailgun(domain, apiKey, publicApiKey string) Mailgun {
	m := MailgunImpl{
		apiBase:      ApiBase,
		domain:       domain,
		apiKey:       apiKey,
		publicApiKey: publicApiKey,
		client:       http.DefaultClient,
	}
	return &m
}
func NewMailgunFromEnv() (Mailgun, error) {
	apiKey := os.Getenv("MG_API_KEY")
	if apiKey == "" {
		return nil, errors.New("required environment variable MG_API_KEY not defined")
	}
	domain := os.Getenv("MG_DOMAIN")
	if domain == "" {
		return nil, errors.New("required environment variable MG_DOMAIN not defined")
	}
	mg := MailgunImpl{
		domain:       domain,
		apiKey:       apiKey,
		publicApiKey: os.Getenv("MG_PUBLIC_API_KEY"),
		client:       http.DefaultClient,
	}
	url := os.Getenv("MG_URL")
	if url != "" {
		mg.SetAPIBase(url)
	}
	return &mg, nil
}
func (m *MailgunImpl) ApiBase() string {
	return m.apiBase
}
func (m *MailgunImpl) Domain() string {
	return m.domain
}
func (m *MailgunImpl) ApiKey() string {
	return m.apiKey
}
func (m *MailgunImpl) PublicApiKey() string {
	return m.publicApiKey
}
func (m *MailgunImpl) Client() *http.Client {
	return m.client
}
func (m *MailgunImpl) SetClient(c *http.Client) {
	m.client = c
}
func (m *MailgunImpl) SetAPIBase(address string) {
	m.apiBase = address
}
func generateApiUrl(m Mailgun, endpoint string) string {
	return fmt.Sprintf("%s/%s/%s", m.ApiBase(), m.Domain(), endpoint)
}
func generateMemberApiUrl(m Mailgun, endpoint, address string) string {
	return fmt.Sprintf("%s/%s/%s/members", m.ApiBase(), endpoint, address)
}