From 9d46f334679cf8cfe41a48adaccfe80c65f9674e Mon Sep 17 00:00:00 2001 From: "Derrick J. Wippler" Date: Fri, 4 Jan 2019 07:54:11 -0600 Subject: [PATCH] Added GetDomainTracking() --- domains.go | 34 ++++++++++++++++++++++++++++++---- domains_test.go | 25 ++++++++++++++++++++++--- ips.go | 8 ++++---- mailgun.go | 1 + mock.go | 2 +- mock_domains.go | 45 +++++++++++++++++++++++++++++++++++---------- mock_exports.go | 4 ++-- mock_ips.go | 10 +++++----- 8 files changed, 100 insertions(+), 29 deletions(-) diff --git a/domains.go b/domains.go index a4d4ad1a..85009359 100644 --- a/domains.go +++ b/domains.go @@ -43,14 +43,15 @@ type DNSRecord struct { Value string } -type SingleDomainResponse struct { +type domainResponse struct { Domain Domain `json:"domain"` ReceivingDNSRecords []DNSRecord `json:"receiving_dns_records"` SendingDNSRecords []DNSRecord `json:"sending_dns_records"` Connection *DomainConnection `json:"connection,omitempty"` + Tracking *DomainTracking `json:"tracking,omitempty"` } -type DomainConnectionResponse struct { +type domainConnectionResponse struct { Connection DomainConnection `json:"connection"` } @@ -64,6 +65,22 @@ type DomainConnection struct { SkipVerification bool `json:"skip_verification"` } +type DomainTracking struct { + Click TrackingStatus `json:"click"` + Open TrackingStatus `json:"open"` + Unsubscribe TrackingStatus `json:"unsubscribe"` +} + +type TrackingStatus struct { + Active bool `json:"active"` + HTMLFooter string `json:"html_footer"` + TextFooter string `json:"text_footer"` +} + +type domainTrackingResponse struct { + Tracking DomainTracking `json:"tracking"` +} + // GetCreatedAt returns the time the domain was created as a normal Go time.Time type. func (d Domain) GetCreatedAt() (t time.Time, err error) { t, err = parseMailgunTime(d.CreatedAt) @@ -100,7 +117,7 @@ func (mg *MailgunImpl) GetSingleDomain(domain string) (Domain, []DNSRecord, []DN r := newHTTPRequest(generatePublicApiUrl(mg, domainsEndpoint) + "/" + domain) r.setClient(mg.Client()) r.setBasicAuth(basicAuthUser, mg.APIKey()) - var envelope SingleDomainResponse + var envelope domainResponse err := getResponseFromJSON(r, &envelope) return envelope.Domain, envelope.ReceivingDNSRecords, envelope.SendingDNSRecords, err } @@ -129,7 +146,7 @@ func (mg *MailgunImpl) GetDomainConnection(domain string) (DomainConnection, err r := newHTTPRequest(generatePublicApiUrl(mg, domainsEndpoint) + "/" + domain + "/connection") r.setClient(mg.Client()) r.setBasicAuth(basicAuthUser, mg.APIKey()) - var resp DomainConnectionResponse + var resp domainConnectionResponse err := getResponseFromJSON(r, &resp) return resp.Connection, err } @@ -155,6 +172,15 @@ func (mg *MailgunImpl) DeleteDomain(name string) error { return err } +func (mg *MailgunImpl) GetDomainTracking(domain string) (DomainTracking, error) { + r := newHTTPRequest(generatePublicApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking") + r.setClient(mg.Client()) + r.setBasicAuth(basicAuthUser, mg.APIKey()) + var resp domainTrackingResponse + err := getResponseFromJSON(r, &resp) + return resp.Tracking, err +} + func boolToString(b bool) string { if b { return "true" diff --git a/domains_test.go b/domains_test.go index 3043cad3..e00683d1 100644 --- a/domains_test.go +++ b/domains_test.go @@ -8,6 +8,10 @@ import ( "github.com/mailgun/mailgun-go" ) +const ( + sampleDomain = "samples.mailgun.org" +) + func TestGetDomains(t *testing.T) { mg, err := mailgun.NewMailgunFromEnv() mg.SetAPIBase(server.URL()) @@ -74,18 +78,33 @@ func TestDomainConnection(t *testing.T) { mg.SetAPIBase(server.URL()) ensure.Nil(t, err) - info, err := mg.GetDomainConnection("samples.mailgun.org") + info, err := mg.GetDomainConnection(sampleDomain) ensure.Nil(t, err) ensure.DeepEqual(t, info.RequireTLS, true) ensure.DeepEqual(t, info.SkipVerification, true) info.RequireTLS = false - err = mg.UpdateDomainConnection("samples.mailgun.org", info) + err = mg.UpdateDomainConnection(sampleDomain, info) ensure.Nil(t, err) - info, err = mg.GetDomainConnection("samples.mailgun.org") + info, err = mg.GetDomainConnection(sampleDomain) ensure.Nil(t, err) ensure.DeepEqual(t, info.RequireTLS, false) ensure.DeepEqual(t, info.SkipVerification, true) } + +func TestDomainTracking(t *testing.T) { + mg, err := mailgun.NewMailgunFromEnv() + mg.SetAPIBase(server.URL()) + ensure.Nil(t, err) + + info, err := mg.GetDomainTracking(sampleDomain) + ensure.Nil(t, err) + + ensure.DeepEqual(t, info.Unsubscribe.Active, false) + ensure.DeepEqual(t, len(info.Unsubscribe.HTMLFooter) != 0, true) + ensure.DeepEqual(t, len(info.Unsubscribe.TextFooter) != 0, true) + ensure.DeepEqual(t, info.Click.Active, true) + ensure.DeepEqual(t, info.Open.Active, true) +} diff --git a/ips.go b/ips.go index fe56fb25..e37fffef 100644 --- a/ips.go +++ b/ips.go @@ -1,6 +1,6 @@ package mailgun -type IPAddressList struct { +type ipAddressListResponse struct { TotalCount int `json:"total_count"` Items []string `json:"items"` } @@ -11,7 +11,7 @@ type IPAddress struct { Dedicated bool `json:"dedicated"` } -type OK struct { +type okResp struct { Message string `json:"message"` } @@ -24,7 +24,7 @@ func (mg *MailgunImpl) ListIPS(dedicated bool) ([]IPAddress, error) { } r.setBasicAuth(basicAuthUser, mg.APIKey()) - var resp IPAddressList + var resp ipAddressListResponse if err := getResponseFromJSON(r, &resp); err != nil { return nil, err } @@ -51,7 +51,7 @@ func (mg *MailgunImpl) ListDomainIPS() ([]IPAddress, error) { r.setClient(mg.Client()) r.setBasicAuth(basicAuthUser, mg.APIKey()) - var resp IPAddressList + var resp ipAddressListResponse if err := getResponseFromJSON(r, &resp); err != nil { return nil, err } diff --git a/mailgun.go b/mailgun.go index a5c3dd26..9e784c6c 100644 --- a/mailgun.go +++ b/mailgun.go @@ -214,6 +214,7 @@ type Mailgun interface { GetExportLink(id string) (string, error) UpdateDomainConnection(domain string, settings DomainConnection) error GetDomainConnection(domain string) (DomainConnection, error) + GetDomainTracking(domain string) (DomainTracking, error) } // MailgunImpl bundles data needed by a large number of methods in order to interact with the Mailgun API. diff --git a/mock.go b/mock.go index afb716e7..ccc0a26a 100644 --- a/mock.go +++ b/mock.go @@ -12,7 +12,7 @@ type MockServer struct { srv *httptest.Server domainIPS []string - domainList []SingleDomainResponse + domainList []domainResponse exportList []Export } diff --git a/mock_domains.go b/mock_domains.go index aacfda4b..1a8a5c39 100644 --- a/mock_domains.go +++ b/mock_domains.go @@ -10,7 +10,7 @@ import ( func (ms *MockServer) addDomainRoutes(r chi.Router) { - ms.domainList = append(ms.domainList, SingleDomainResponse{ + ms.domainList = append(ms.domainList, domainResponse{ Domain: Domain{ CreatedAt: "Wed, 10 Jul 2013 19:26:52 GMT", Name: "samples.mailgun.org", @@ -24,6 +24,15 @@ func (ms *MockServer) addDomainRoutes(r chi.Router) { RequireTLS: true, SkipVerification: true, }, + Tracking: &DomainTracking{ + Click: TrackingStatus{Active: true}, + Open: TrackingStatus{Active: true}, + Unsubscribe: TrackingStatus{ + Active: false, + HTMLFooter: "\n
\n

unsubscribe

\n", + TextFooter: "\n\nTo unsubscribe click: <%unsubscribe_url%>\n\n", + }, + }, ReceivingDNSRecords: []DNSRecord{ { Priority: "10", @@ -71,6 +80,8 @@ func (ms *MockServer) addDomainRoutes(r chi.Router) { //r.Delete("/domains/{domain}/credentials/{login}", ms.deleteCredentials) r.Get("/domains/{domain}/connection", ms.getConnection) r.Put("/domains/{domain}/connection", ms.updateConnection) + r.Get("/domains/{domain}/tracking", ms.getTracking) + //r.Put("/domains/{domain}/tracking/{type}", ms.updateTracking) } func (ms *MockServer) listDomains(w http.ResponseWriter, _ *http.Request) { @@ -94,12 +105,12 @@ func (ms *MockServer) getDomain(w http.ResponseWriter, r *http.Request) { } } w.WriteHeader(http.StatusNotFound) - toJSON(w, OK{Message: "domain not found"}) + toJSON(w, okResp{Message: "domain not found"}) } func (ms *MockServer) createDomain(w http.ResponseWriter, r *http.Request) { now := time.Now() - ms.domainList = append(ms.domainList, SingleDomainResponse{ + ms.domainList = append(ms.domainList, domainResponse{ Domain: Domain{ CreatedAt: formatMailgunTime(&now), Name: r.FormValue("name"), @@ -110,7 +121,7 @@ func (ms *MockServer) createDomain(w http.ResponseWriter, r *http.Request) { State: "active", }, }) - toJSON(w, OK{Message: "Domain has been created"}) + toJSON(w, okResp{Message: "Domain has been created"}) } func (ms *MockServer) deleteDomain(w http.ResponseWriter, r *http.Request) { @@ -123,19 +134,19 @@ func (ms *MockServer) deleteDomain(w http.ResponseWriter, r *http.Request) { } if len(result) != len(ms.domainList) { - toJSON(w, OK{Message: "success"}) + toJSON(w, okResp{Message: "success"}) ms.domainList = result return } w.WriteHeader(http.StatusNotFound) - toJSON(w, OK{Message: "domain not found"}) + toJSON(w, okResp{Message: "domain not found"}) } func (ms *MockServer) getConnection(w http.ResponseWriter, r *http.Request) { for _, d := range ms.domainList { if d.Domain.Name == chi.URLParam(r, "domain") { - resp := DomainConnectionResponse{ + resp := domainConnectionResponse{ Connection: *d.Connection, } toJSON(w, resp) @@ -143,7 +154,7 @@ func (ms *MockServer) getConnection(w http.ResponseWriter, r *http.Request) { } } w.WriteHeader(http.StatusNotFound) - toJSON(w, OK{Message: "domain not found"}) + toJSON(w, okResp{Message: "domain not found"}) } func (ms *MockServer) updateConnection(w http.ResponseWriter, r *http.Request) { @@ -153,12 +164,26 @@ func (ms *MockServer) updateConnection(w http.ResponseWriter, r *http.Request) { RequireTLS: stringToBool(r.FormValue("require_tls")), SkipVerification: stringToBool(r.FormValue("skip_verification")), } - toJSON(w, OK{Message: "Domain connection settings have been updated, may take 10 minutes to fully propagate"}) + toJSON(w, okResp{Message: "Domain connection settings have been updated, may take 10 minutes to fully propagate"}) + return + } + } + w.WriteHeader(http.StatusNotFound) + toJSON(w, okResp{Message: "domain not found"}) +} + +func (ms *MockServer) getTracking(w http.ResponseWriter, r *http.Request) { + for _, d := range ms.domainList { + if d.Domain.Name == chi.URLParam(r, "domain") { + resp := domainTrackingResponse{ + Tracking: *d.Tracking, + } + toJSON(w, resp) return } } w.WriteHeader(http.StatusNotFound) - toJSON(w, OK{Message: "domain not found"}) + toJSON(w, okResp{Message: "domain not found"}) } func stringToBool(b string) bool { diff --git a/mock_exports.go b/mock_exports.go index df9bfbe4..1a0ae345 100644 --- a/mock_exports.go +++ b/mock_exports.go @@ -22,7 +22,7 @@ func (ms *MockServer) postExports(w http.ResponseWriter, r *http.Request) { } ms.exportList = append(ms.exportList, e) - toJSON(w, OK{Message: "success"}) + toJSON(w, okResp{Message: "success"}) } func (ms *MockServer) listExports(w http.ResponseWriter, _ *http.Request) { @@ -39,7 +39,7 @@ func (ms *MockServer) getExport(w http.ResponseWriter, r *http.Request) { } } w.WriteHeader(http.StatusNotFound) - toJSON(w, OK{Message: "export not found"}) + toJSON(w, okResp{Message: "export not found"}) } func (ms *MockServer) getExportLink(w http.ResponseWriter, r *http.Request) { diff --git a/mock_ips.go b/mock_ips.go index 7f1feb81..493ca746 100644 --- a/mock_ips.go +++ b/mock_ips.go @@ -18,7 +18,7 @@ func (ms *MockServer) addIPRoutes(r chi.Router) { } func (ms *MockServer) listIPS(w http.ResponseWriter, _ *http.Request) { - toJSON(w, IPAddressList{ + toJSON(w, ipAddressListResponse{ TotalCount: 2, Items: []string{"172.0.0.1", "192.168.1.1"}, }) @@ -33,7 +33,7 @@ func (ms *MockServer) getIPAddress(w http.ResponseWriter, r *http.Request) { } func (ms *MockServer) listDomainIPS(w http.ResponseWriter, _ *http.Request) { - toJSON(w, IPAddressList{ + toJSON(w, ipAddressListResponse{ TotalCount: 2, Items: ms.domainIPS, }) @@ -41,7 +41,7 @@ func (ms *MockServer) listDomainIPS(w http.ResponseWriter, _ *http.Request) { func (ms *MockServer) postDomainIPS(w http.ResponseWriter, r *http.Request) { ms.domainIPS = append(ms.domainIPS, r.FormValue("ip")) - toJSON(w, OK{Message: "success"}) + toJSON(w, okResp{Message: "success"}) } func (ms *MockServer) deleteDomainIPS(w http.ResponseWriter, r *http.Request) { @@ -54,12 +54,12 @@ func (ms *MockServer) deleteDomainIPS(w http.ResponseWriter, r *http.Request) { } if len(result) != len(ms.domainIPS) { - toJSON(w, OK{Message: "success"}) + toJSON(w, okResp{Message: "success"}) ms.domainIPS = result return } // Not the actual error returned by the mailgun API w.WriteHeader(http.StatusNotFound) - toJSON(w, OK{Message: "ip not found"}) + toJSON(w, okResp{Message: "ip not found"}) }