diff --git a/README.md b/README.md index beb7485..aa7cbcd 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ func main() { // Create an instance of the Mailgun Client mg := mailgun.NewMailgun(privateAPIKey) - //When you have an EU-domain, you must specify the endpoint: - //mg.SetAPIBase("https://api.eu.mailgun.net/v3") + // When you have an EU domain, you must specify the endpoint: + // err := mg.SetAPIBase(mailgun.APIBaseEU) sender := "sender@example.com" subject := "Fancy subject!" diff --git a/analytics.go b/analytics.go index 7a421cf..25d5271 100644 --- a/analytics.go +++ b/analytics.go @@ -2,7 +2,6 @@ package mailgun import ( "context" - "strings" "github.com/mailgun/errors" ) @@ -35,15 +34,11 @@ type MetricsPagination struct { // // https://documentation.mailgun.com/docs/mailgun/api-reference/openapi-final/tag/Metrics/ func (mg *MailgunImpl) ListMetrics(opts MetricsOptions) (*MetricsIterator, error) { - if !strings.HasSuffix(mg.APIBase(), "/v1") { - return nil, errors.New("only v1 API is supported") - } - if opts.Pagination.Limit == 0 { opts.Pagination.Limit = 10 } - req := newHTTPRequest(generateApiUrl(mg, metricsEndpoint)) + req := newHTTPRequest(generateApiUrl(mg, 1, metricsEndpoint)) req.setClient(mg.HTTPClient()) req.setBasicAuth(basicAuthUser, mg.APIKey()) diff --git a/analytics_test.go b/analytics_test.go index abe86d9..dcb81d5 100644 --- a/analytics_test.go +++ b/analytics_test.go @@ -11,7 +11,8 @@ import ( func TestListMetrics(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL1()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) start, _ := mailgun.NewRFC2822Time("Tue, 24 Sep 2024 00:00:00 +0000") end, _ := mailgun.NewRFC2822Time("Tue, 24 Oct 2024 00:00:00 +0000") diff --git a/attachments_test.go b/attachments_test.go index 8e1de0a..964f8d8 100644 --- a/attachments_test.go +++ b/attachments_test.go @@ -27,7 +27,8 @@ func createAttachment(t *testing.T) string { func TestMultipleAttachments(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) var ctx = context.Background() diff --git a/bounces.go b/bounces.go index 405d861..cba6713 100644 --- a/bounces.go +++ b/bounces.go @@ -35,7 +35,7 @@ type bouncesListResponse struct { // and the slice of bounces specified, if successful. // Note that the length of the slice may be smaller than the total number of bounces. func (mg *MailgunImpl) ListBounces(domain string, opts *ListOptions) *BouncesIterator { - r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) if opts != nil { @@ -147,7 +147,7 @@ func (ci *BouncesIterator) fetch(ctx context.Context, url string) error { // GetBounce retrieves a single bounce record, if any exist, for the given recipient address. func (mg *MailgunImpl) GetBounce(ctx context.Context, domain, address string) (Bounce, error) { - r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -173,7 +173,7 @@ func (mg *MailgunImpl) GetBounce(ctx context.Context, domain, address string) (B // Note that both code and error exist as strings, even though // code will report as a number. func (mg *MailgunImpl) AddBounce(ctx context.Context, domain, address, code, bounceError string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -191,7 +191,7 @@ func (mg *MailgunImpl) AddBounce(ctx context.Context, domain, address, code, bou // Add Bounces adds a list of bounces to the bounce list func (mg *MailgunImpl) AddBounces(ctx context.Context, domain string, bounces []Bounce) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -203,7 +203,7 @@ func (mg *MailgunImpl) AddBounces(ctx context.Context, domain string, bounces [] // DeleteBounce removes all bounces associted with the provided e-mail address. func (mg *MailgunImpl) DeleteBounce(ctx context.Context, domain, address string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -212,7 +212,7 @@ func (mg *MailgunImpl) DeleteBounce(ctx context.Context, domain, address string) // DeleteBounceList removes all bounces in the bounce list func (mg *MailgunImpl) DeleteBounceList(ctx context.Context, domain string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) diff --git a/bounces_test.go b/bounces_test.go index 048311c..9329f45 100644 --- a/bounces_test.go +++ b/bounces_test.go @@ -15,7 +15,8 @@ import ( func TestGetBounces(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() it := mg.ListBounces(testDomain, nil) @@ -31,12 +32,13 @@ func TestGetBounces(t *testing.T) { func TestGetSingleBounce(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() exampleEmail := fmt.Sprintf("%s@%s", strings.ToLower(randomString(64, "")), os.Getenv("MG_DOMAIN")) - _, err := mg.GetBounce(ctx, testDomain, exampleEmail) + _, err = mg.GetBounce(ctx, testDomain, exampleEmail) require.NotNil(t, err) var ure *mailgun.UnexpectedResponseError @@ -46,7 +48,9 @@ func TestGetSingleBounce(t *testing.T) { func TestAddDelBounces(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() findBounce := func(address string) bool { @@ -71,7 +75,7 @@ func TestAddDelBounces(t *testing.T) { exampleEmail := fmt.Sprintf("%s@%s", strings.ToLower(randomString(8, "bounce")), domain) // Add the bounce for our address. - err := mg.AddBounce(ctx, testDomain, exampleEmail, "550", "TestAddDelBounces-generated error") + err = mg.AddBounce(ctx, testDomain, exampleEmail, "550", "TestAddDelBounces-generated error") require.NoError(t, err) // Give API some time to refresh cache @@ -104,7 +108,8 @@ func TestAddDelBounces(t *testing.T) { func TestAddDelBounceList(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() diff --git a/credentials_test.go b/credentials_test.go index 4accc29..8d81106 100644 --- a/credentials_test.go +++ b/credentials_test.go @@ -12,7 +12,8 @@ import ( func TestGetCredentials(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() it := mg.ListCredentials(testDomain, nil) @@ -29,7 +30,8 @@ func TestGetCredentials(t *testing.T) { func TestCreateDeleteCredentials(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) randomPassword := randomString(16, "pw") randomID := strings.ToLower(randomString(16, "usr")) diff --git a/domains.go b/domains.go index cb01562..15acac5 100644 --- a/domains.go +++ b/domains.go @@ -92,7 +92,7 @@ func (mg *MailgunImpl) ListDomains(opts *ListOptions) *DomainsIterator { } return &DomainsIterator{ mg: mg, - url: generateApiUrl(mg, domainsEndpoint), + url: generateApiUrl(mg, 3, domainsEndpoint), domainsListResponse: domainsListResponse{TotalCount: -1}, limit: limit, } @@ -233,7 +233,7 @@ func (ri *DomainsIterator) fetch(ctx context.Context, skip, limit int) error { // GetDomain retrieves detailed information about the named domain. func (mg *MailgunImpl) GetDomain(ctx context.Context, domain string) (DomainResponse, error) { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain) + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var resp DomainResponse @@ -242,7 +242,7 @@ func (mg *MailgunImpl) GetDomain(ctx context.Context, domain string) (DomainResp } func (mg *MailgunImpl) VerifyDomain(ctx context.Context, domain string) (string, error) { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/verify") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/verify") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -254,7 +254,7 @@ func (mg *MailgunImpl) VerifyDomain(ctx context.Context, domain string) (string, // VerifyAndReturnDomain verifies & retrieves detailed information about the named domain. func (mg *MailgunImpl) VerifyAndReturnDomain(ctx context.Context, domain string) (DomainResponse, error) { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/verify") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/verify") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -282,7 +282,7 @@ type CreateDomainOptions struct { // The wildcard parameter instructs Mailgun to treat all subdomains of this domain uniformly if true, // and as different domains if false. func (mg *MailgunImpl) CreateDomain(ctx context.Context, name string, opts *CreateDomainOptions) (DomainResponse, error) { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint)) + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -319,7 +319,7 @@ func (mg *MailgunImpl) CreateDomain(ctx context.Context, name string, opts *Crea // GetDomainConnection returns delivery connection settings for the defined domain func (mg *MailgunImpl) GetDomainConnection(ctx context.Context, domain string) (DomainConnection, error) { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/connection") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/connection") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var resp domainConnectionResponse @@ -327,9 +327,9 @@ func (mg *MailgunImpl) GetDomainConnection(ctx context.Context, domain string) ( return resp.Connection, err } -// Updates the specified delivery connection settings for the defined domain +// UpdateDomainConnection updates the specified delivery connection settings for the defined domain func (mg *MailgunImpl) UpdateDomainConnection(ctx context.Context, domain string, settings DomainConnection) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/connection") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/connection") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -342,7 +342,7 @@ func (mg *MailgunImpl) UpdateDomainConnection(ctx context.Context, domain string // DeleteDomain instructs Mailgun to dispose of the named domain name func (mg *MailgunImpl) DeleteDomain(ctx context.Context, name string) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + name) + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + name) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -351,7 +351,7 @@ func (mg *MailgunImpl) DeleteDomain(ctx context.Context, name string) error { // GetDomainTracking returns tracking settings for a domain func (mg *MailgunImpl) GetDomainTracking(ctx context.Context, domain string) (DomainTracking, error) { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/tracking") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var resp domainTrackingResponse @@ -360,7 +360,7 @@ func (mg *MailgunImpl) GetDomainTracking(ctx context.Context, domain string) (Do } func (mg *MailgunImpl) UpdateClickTracking(ctx context.Context, domain, active string) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/click") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/tracking/click") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -371,7 +371,7 @@ func (mg *MailgunImpl) UpdateClickTracking(ctx context.Context, domain, active s } func (mg *MailgunImpl) UpdateUnsubscribeTracking(ctx context.Context, domain, active, htmlFooter, textFooter string) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/unsubscribe") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/tracking/unsubscribe") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -384,7 +384,7 @@ func (mg *MailgunImpl) UpdateUnsubscribeTracking(ctx context.Context, domain, ac } func (mg *MailgunImpl) UpdateOpenTracking(ctx context.Context, domain, active string) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/open") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/tracking/open") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -396,7 +396,7 @@ func (mg *MailgunImpl) UpdateOpenTracking(ctx context.Context, domain, active st // Update the DKIM selector for a domain func (mg *MailgunImpl) UpdateDomainDkimSelector(ctx context.Context, domain, dkimSelector string) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/dkim_selector") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/dkim_selector") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -408,7 +408,7 @@ func (mg *MailgunImpl) UpdateDomainDkimSelector(ctx context.Context, domain, dki // Update the CNAME used for tracking opens and clicks func (mg *MailgunImpl) UpdateDomainTrackingWebPrefix(ctx context.Context, domain, webPrefix string) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/web_prefix") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/web_prefix") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -426,7 +426,7 @@ type UpdateDomainOptions struct { // UpdateDomain updates a domain's attributes. // Currently only the web_scheme update is supported, spam_action and wildcard are to be added. func (mg *MailgunImpl) UpdateDomain(ctx context.Context, name string, opts *UpdateDomainOptions) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + name) + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + name) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) diff --git a/domains_test.go b/domains_test.go index 87388b1..c7a4fb2 100644 --- a/domains_test.go +++ b/domains_test.go @@ -18,7 +18,9 @@ const ( func TestListDomains(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() it := mg.ListDomains(nil) @@ -35,7 +37,9 @@ func TestListDomains(t *testing.T) { func TestGetSingleDomain(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() it := mg.ListDomains(nil) @@ -59,10 +63,11 @@ func TestGetSingleDomain(t *testing.T) { func TestGetSingleDomainNotExist(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() - _, err := mg.GetDomain(ctx, "unknown.domain") + _, err = mg.GetDomain(ctx, "unknown.domain") if err == nil { t.Fatal("Did not expect a domain to exist") } @@ -73,11 +78,13 @@ func TestGetSingleDomainNotExist(t *testing.T) { func TestAddUpdateDeleteDomain(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() // First, we need to add the domain. - _, err := mg.CreateDomain(ctx, "mx.mailgun.test", + _, err = mg.CreateDomain(ctx, "mx.mailgun.test", &mailgun.CreateDomainOptions{SpamAction: mailgun.SpamActionTag, Password: "supersecret", WebScheme: "http"}) require.NoError(t, err) @@ -92,7 +99,9 @@ func TestAddUpdateDeleteDomain(t *testing.T) { func TestDomainConnection(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() info, err := mg.GetDomainConnection(ctx, testDomain) @@ -113,7 +122,9 @@ func TestDomainConnection(t *testing.T) { func TestDomainTracking(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() info, err := mg.GetDomainTracking(ctx, testDomain) @@ -154,38 +165,46 @@ func TestDomainTracking(t *testing.T) { func TestDomainVerify(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() - _, err := mg.VerifyDomain(ctx, testDomain) + _, err = mg.VerifyDomain(ctx, testDomain) require.NoError(t, err) } func TestDomainVerifyAndReturn(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() - _, err := mg.VerifyAndReturnDomain(ctx, testDomain) + _, err = mg.VerifyAndReturnDomain(ctx, testDomain) require.NoError(t, err) } func TestDomainDkimSelector(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() // Update Domain DKIM selector - err := mg.UpdateDomainDkimSelector(ctx, testDomain, "gotest") + err = mg.UpdateDomainDkimSelector(ctx, testDomain, "gotest") require.NoError(t, err) } func TestDomainTrackingWebPrefix(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() // Update Domain Tracking Web Prefix - err := mg.UpdateDomainTrackingWebPrefix(ctx, testDomain, "gotest") + err = mg.UpdateDomainTrackingWebPrefix(ctx, testDomain, "gotest") require.NoError(t, err) } diff --git a/email_validation.go b/email_validation.go index d9b484a..123e3ce 100644 --- a/email_validation.go +++ b/email_validation.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "os" - "strings" "github.com/mailgun/errors" ) @@ -22,6 +21,7 @@ type EmailVerificationParts struct { // EmailVerification records basic facts about a validated e-mail address. // See the ValidateEmail method and example for more details. +// TODO(v5): remove /v3 validations fields(Reason) type EmailVerification struct { // Indicates whether an email address conforms to IETF RFC standards. IsValid bool `json:"is_valid"` @@ -148,16 +148,11 @@ func (m *EmailValidatorImpl) APIKey() string { // It may also be used to break an email address into its sub-components. If user has set the // TODO(v5): move to *MailgunImpl? func (m *EmailValidatorImpl) ValidateEmail(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error) { - // TODO(DE-1383): remove check: - if strings.HasSuffix(m.APIBase(), "/v4") { - return m.validateV4(ctx, email, mailBoxVerify) - } - - return EmailVerification{}, errors.New("ValidateEmail: only v4 is supported") + return m.validateV4(ctx, email, mailBoxVerify) } func (m *EmailValidatorImpl) validateV4(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error) { - r := newHTTPRequest(fmt.Sprintf("%s/address/validate", m.APIBase())) + r := newHTTPRequest(fmt.Sprintf("%s/v4/address/validate", m.APIBase())) r.setClient(m.Client()) r.addParameter("address", email) if mailBoxVerify { diff --git a/email_validation_test.go b/email_validation_test.go index 53d4c0c..2049bd1 100644 --- a/email_validation_test.go +++ b/email_validation_test.go @@ -13,7 +13,8 @@ import ( func TestEmailValidationV4(t *testing.T) { v := mailgun.NewEmailValidator(testKey) // API Base is set to `http://server/v4` - v.SetAPIBase(server.URL4()) + v.SetAPIBase(server.URL()) + ctx := context.Background() ev, err := v.ValidateEmail(ctx, "foo@mailgun.com", false) diff --git a/events.go b/events.go index d17e63a..ee311d8 100644 --- a/events.go +++ b/events.go @@ -38,7 +38,7 @@ type EventIterator struct { // ListEvents creates a new iterator to fetch a page of events from the events api func (mg *MailgunImpl) ListEvents(domain string, opts *ListEventOptions) *EventIterator { - url := generateApiUrlWithDomain(mg, eventsEndpoint, domain) + url := generateApiV3UrlWithDomain(mg, eventsEndpoint, domain) return mg.listEvents(url, opts) } diff --git a/events_test.go b/events_test.go index 6589c09..f89b389 100644 --- a/events_test.go +++ b/events_test.go @@ -14,7 +14,8 @@ import ( func TestEventIteratorGetNext(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) it := mg.ListEvents(testDomain, &mailgun.ListEventOptions{Limit: 5}) @@ -63,7 +64,8 @@ func TestEventIteratorGetNext(t *testing.T) { func TestEventPoller(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) // Very short poll interval it := mg.PollEvents(testDomain, &mailgun.ListEventOptions{ @@ -113,7 +115,7 @@ func TestEventPoller(t *testing.T) { func ExampleMailgunImpl_ListEvents() { mg := mailgun.NewMailgun("your-api-key") - mg.SetAPIBase(server.URL3()) + _ = mg.SetAPIBase(server.URL()) it := mg.ListEvents("your-domain.com", &mailgun.ListEventOptions{Limit: 100}) diff --git a/exports.go b/exports.go index dc0a4db..c222374 100644 --- a/exports.go +++ b/exports.go @@ -19,7 +19,7 @@ type Export struct { // Create an export based on the URL given func (mg *MailgunImpl) CreateExport(ctx context.Context, url string) error { - r := newHTTPRequest(generateApiUrl(mg, exportsEndpoint)) + r := newHTTPRequest(generateApiUrl(mg, 3, exportsEndpoint)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -31,7 +31,7 @@ func (mg *MailgunImpl) CreateExport(ctx context.Context, url string) error { // List all exports created within the past 24 hours func (mg *MailgunImpl) ListExports(ctx context.Context, url string) ([]Export, error) { - r := newHTTPRequest(generateApiUrl(mg, exportsEndpoint)) + r := newHTTPRequest(generateApiUrl(mg, 3, exportsEndpoint)) r.setClient(mg.HTTPClient()) if url != "" { r.addParameter("url", url) @@ -52,7 +52,7 @@ func (mg *MailgunImpl) ListExports(ctx context.Context, url string) ([]Export, e // GetExport gets an export by id func (mg *MailgunImpl) GetExport(ctx context.Context, id string) (Export, error) { - r := newHTTPRequest(generateApiUrl(mg, exportsEndpoint) + "/" + id) + r := newHTTPRequest(generateApiUrl(mg, 3, exportsEndpoint) + "/" + id) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var resp Export @@ -63,7 +63,7 @@ func (mg *MailgunImpl) GetExport(ctx context.Context, id string) (Export, error) // Download an export by ID. This will respond with a '302 Moved' // with the Location header of temporary S3 URL if it is available. func (mg *MailgunImpl) GetExportLink(ctx context.Context, id string) (string, error) { - r := newHTTPRequest(generateApiUrl(mg, exportsEndpoint) + "/" + id + "/download_url") + r := newHTTPRequest(generateApiUrl(mg, 3, exportsEndpoint) + "/" + id + "/download_url") c := mg.HTTPClient() // Ensure the client doesn't attempt to retry diff --git a/exports_test.go b/exports_test.go index 0fe9cf6..6554a63 100644 --- a/exports_test.go +++ b/exports_test.go @@ -11,7 +11,8 @@ import ( func TestExports(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() list, err := mg.ListExports(ctx, "") @@ -38,7 +39,8 @@ func TestExports(t *testing.T) { func TestExportsLink(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() url, err := mg.GetExportLink(ctx, "12") diff --git a/httphelpers.go b/httphelpers.go index f2212bd..c6cf049 100644 --- a/httphelpers.go +++ b/httphelpers.go @@ -17,7 +17,7 @@ import ( "github.com/mailgun/errors" ) -var validURL = regexp.MustCompile(`/v[1-5].*`) +var invalidURL = regexp.MustCompile(`/v\d+.*`) type httpRequest struct { URL string @@ -370,10 +370,6 @@ func (r *httpRequest) generateUrlWithParameters() (string, error) { return "", err } - if !validURL.MatchString(uri.Path) { - return "", errors.New(`APIBase must end with a /v1, /v2, /v3 or /v4; SetAPIBase("https://host/v3")`) - } - q := uri.Query() if len(r.Parameters) > 0 { for name, values := range r.Parameters { diff --git a/ips.go b/ips.go index 6cb37fb..7a94457 100644 --- a/ips.go +++ b/ips.go @@ -20,7 +20,7 @@ type okResp struct { // ListIPS returns a list of IPs assigned to your account func (mg *MailgunImpl) ListIPS(ctx context.Context, dedicated bool) ([]IPAddress, error) { - r := newHTTPRequest(generateApiUrl(mg, ipsEndpoint)) + r := newHTTPRequest(generateApiUrl(mg, 3, ipsEndpoint)) r.setClient(mg.HTTPClient()) if dedicated { r.addParameter("dedicated", "true") @@ -40,7 +40,7 @@ func (mg *MailgunImpl) ListIPS(ctx context.Context, dedicated bool) ([]IPAddress // GetIP returns information about the specified IP func (mg *MailgunImpl) GetIP(ctx context.Context, ip string) (IPAddress, error) { - r := newHTTPRequest(generateApiUrl(mg, ipsEndpoint) + "/" + ip) + r := newHTTPRequest(generateApiUrl(mg, 3, ipsEndpoint) + "/" + ip) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var resp IPAddress @@ -50,7 +50,7 @@ func (mg *MailgunImpl) GetIP(ctx context.Context, ip string) (IPAddress, error) // ListDomainIPS returns a list of IPs currently assigned to the specified domain. func (mg *MailgunImpl) ListDomainIPS(ctx context.Context, domain string) ([]IPAddress, error) { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/ips") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/ips") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -67,7 +67,7 @@ func (mg *MailgunImpl) ListDomainIPS(ctx context.Context, domain string) ([]IPAd // Assign a dedicated IP to the domain specified. func (mg *MailgunImpl) AddDomainIP(ctx context.Context, domain, ip string) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/ips") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/ips") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -79,7 +79,7 @@ func (mg *MailgunImpl) AddDomainIP(ctx context.Context, domain, ip string) error // Unassign an IP from the domain specified. func (mg *MailgunImpl) DeleteDomainIP(ctx context.Context, domain, ip string) error { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/ips/" + ip) + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/ips/" + ip) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) diff --git a/ips_test.go b/ips_test.go index fa4fd03..6e28208 100644 --- a/ips_test.go +++ b/ips_test.go @@ -21,7 +21,8 @@ func TestMain(m *testing.M) { func TestListIPS(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() list, err := mg.ListIPS(ctx, false) @@ -38,10 +39,11 @@ func TestListIPS(t *testing.T) { func TestDomainIPS(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() - err := mg.AddDomainIP(ctx, testDomain, "192.172.1.1") + err = mg.AddDomainIP(ctx, testDomain, "192.172.1.1") require.NoError(t, err) list, err := mg.ListDomainIPS(ctx, testDomain) diff --git a/limits.go b/limits.go index 4bff2e2..2e73ead 100644 --- a/limits.go +++ b/limits.go @@ -9,7 +9,7 @@ type TagLimits struct { // GetTagLimits returns tracking settings for a domain func (mg *MailgunImpl) GetTagLimits(ctx context.Context, domain string) (TagLimits, error) { - r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/limits/tag") + r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/limits/tag") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var resp TagLimits diff --git a/limits_test.go b/limits_test.go index 32642ad..7204704 100644 --- a/limits_test.go +++ b/limits_test.go @@ -11,7 +11,8 @@ import ( func TestLimits(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() limits, err := mg.GetTagLimits(ctx, testDomain) diff --git a/mailgun.go b/mailgun.go index 6e8ddfd..cfe7950 100644 --- a/mailgun.go +++ b/mailgun.go @@ -88,9 +88,10 @@ var Debug = false const ( // APIBase - base URL the library uses to contact mailgun. Use SetAPIBase() to override - APIBase = "https://api.mailgun.net/v3" - APIBaseUS = APIBase - APIBaseEU = "https://api.eu.mailgun.net/v3" + APIBase = "https://api.mailgun.net" + APIBaseUS = APIBase + APIBaseEU = "https://api.eu.mailgun.net" + messagesEndpoint = "messages" mimeMessagesEndpoint = "messages.mime" bouncesEndpoint = "bounces" @@ -108,7 +109,8 @@ const ( templatesEndpoint = "templates" accountsEndpoint = "accounts" subaccountsEndpoint = "subaccounts" - OnBehalfOfHeader = "X-Mailgun-On-Behalf-Of" + + OnBehalfOfHeader = "X-Mailgun-On-Behalf-Of" ) // Mailgun defines the supported subset of the Mailgun API. @@ -124,7 +126,7 @@ type Mailgun interface { APIKey() string HTTPClient() *http.Client SetHTTPClient(client *http.Client) - SetAPIBase(url string) + SetAPIBase(url string) error AddOverrideHeader(k string, v string) // Send attempts to queue a message (see CommonMessage, NewMessage, and its methods) for delivery. @@ -274,7 +276,10 @@ func NewMailgunFromEnv() (*MailgunImpl, error) { url := os.Getenv("MG_URL") if url != "" { - mg.SetAPIBase(url) + err := mg.SetAPIBase(url) + if err != nil { + return nil, err + } } webhookSigningKey := os.Getenv("MG_WEBHOOK_SIGNING_KEY") @@ -339,9 +344,14 @@ func (mg *MailgunImpl) RemoveOnBehalfOfSubaccount() { // mg.SetAPIBase(mailgun.APIBaseUS) // // // Set a custom base API -// mg.SetAPIBase("https://localhost/v3") -func (mg *MailgunImpl) SetAPIBase(address string) { +// mg.SetAPIBase("https://localhost") +func (mg *MailgunImpl) SetAPIBase(address string) error { + if invalidURL.MatchString(address) { + return errors.New(`APIBase must not contain a version; SetAPIBase("https://host")`) + } + mg.apiBase = address + return nil } // AddOverrideHeader allows the user to specify additional headers that will be included in the HTTP request @@ -358,48 +368,54 @@ type ListOptions struct { Limit int } -// generateApiUrlWithDomain renders a URL for an API endpoint using the domain and endpoint name. -func generateApiUrlWithDomain(m Mailgun, endpoint, domain string) string { - return fmt.Sprintf("%s/%s/%s", m.APIBase(), domain, endpoint) +// TODO(vtopc): sort all these generate URL functions(some are generateApi...Url, other are generate...ApiUrl) + +func generateApiUrlWithDomain(m Mailgun, version int, endpoint, domain string) string { + return fmt.Sprintf("%s/v%d/%s/%s", m.APIBase(), version, domain, endpoint) +} + +// generateApiV3UrlWithDomain renders a URL for an API endpoint using the domain and endpoint name. +func generateApiV3UrlWithDomain(m Mailgun, endpoint, domain string) string { + return generateApiUrlWithDomain(m, 3, endpoint, domain) } // generateMemberApiUrl renders a URL relevant for specifying mailing list members. // The address parameter refers to the mailing list in question. func generateMemberApiUrl(m Mailgun, endpoint, address string) string { - return fmt.Sprintf("%s/%s/%s/members", m.APIBase(), endpoint, address) + return fmt.Sprintf("%s/v3/%s/%s/members", m.APIBase(), endpoint, address) } -// generateApiUrlWithTarget works as generateApiUrl +// generateApiV3UrlWithTarget works as generateApiV3UrlWithDomain // but consumes an additional resource parameter called 'target'. -func generateApiUrlWithTarget(m Mailgun, endpoint, domain, target string) string { +func generateApiV3UrlWithTarget(m Mailgun, endpoint, domain, target string) string { tail := "" if target != "" { tail = fmt.Sprintf("/%s", target) } - return fmt.Sprintf("%s%s", generateApiUrlWithDomain(m, endpoint, domain), tail) + return fmt.Sprintf("%s%s", generateApiV3UrlWithDomain(m, endpoint, domain), tail) } -// generateDomainsApiUrl renders a URL as generateApiUrlWithDomain, but +// generateV3DomainsApiUrl renders a URL as generateApiV3UrlWithDomain, but // addresses a family of functions which have a non-standard URL structure. // Most URLs consume a domain in the 2nd position, but some endpoints // require the word "domains" to be there instead. -func generateDomainsApiUrl(m Mailgun, endpoint, domain string) string { - return fmt.Sprintf("%s/domains/%s/%s", m.APIBase(), domain, endpoint) +func generateV3DomainsApiUrl(m Mailgun, endpoint, domain string) string { + return fmt.Sprintf("%s/v3/domains/%s/%s", m.APIBase(), domain, endpoint) } -// generateCredentialsUrl renders a URL as generateDomainsApiUrl, +// generateCredentialsUrl renders a URL as generateV3DomainsApiUrl, // but focuses on the SMTP credentials family of API functions. func generateCredentialsUrl(m Mailgun, domain, login string) string { tail := "" if login != "" { tail = fmt.Sprintf("/%s", login) } - return generateDomainsApiUrl(m, fmt.Sprintf("credentials%s", tail), domain) + return generateV3DomainsApiUrl(m, fmt.Sprintf("credentials%s", tail), domain) } // generateApiUrl returns domain agnostic URL. -func generateApiUrl(m Mailgun, endpoint string) string { - return fmt.Sprintf("%s/%s", m.APIBase(), endpoint) +func generateApiUrl(m Mailgun, version int, endpoint string) string { + return fmt.Sprintf("%s/v%d/%s", m.APIBase(), version, endpoint) } // formatMailgunTime translates a timestamp into a human-readable form. diff --git a/mailgun_test.go b/mailgun_test.go index d3ff512..6f2647b 100644 --- a/mailgun_test.go +++ b/mailgun_test.go @@ -1,9 +1,7 @@ package mailgun_test import ( - "context" "encoding/json" - "fmt" "net/http" "net/http/httptest" "testing" @@ -29,11 +27,8 @@ func TestMailgun(t *testing.T) { func TestInvalidBaseAPI(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase("https://localhost") - - ctx := context.Background() - _, err := mg.GetDomain(ctx, "unknown.domain") - assert.EqualError(t, err, `APIBase must end with a /v1, /v2, /v3 or /v4; SetAPIBase("https://host/v3")`) + err := mg.SetAPIBase("https://localhost/v3") + assert.EqualError(t, err, `APIBase must not contain a version; SetAPIBase("https://host")`) } func TestValidBaseAPI(t *testing.T) { @@ -47,17 +42,17 @@ func TestValidBaseAPI(t *testing.T) { })) apiBases := []string{ - fmt.Sprintf("%s/v3", testServer.URL), - fmt.Sprintf("%s/proxy/v3", testServer.URL), + mailgun.APIBase, + mailgun.APIBaseEU, + testServer.URL, } for _, apiBase := range apiBases { - mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(apiBase) - - ctx := context.Background() - _, err := mg.GetDomain(ctx, "unknown.domain") - require.NoError(t, err) + t.Run(apiBase, func(t *testing.T) { + mg := mailgun.NewMailgun(testKey) + err := mg.SetAPIBase(apiBase) + require.NoError(t, err) + }) } } diff --git a/mailing_lists.go b/mailing_lists.go index ccaa0c3..a1f3613 100644 --- a/mailing_lists.go +++ b/mailing_lists.go @@ -63,7 +63,7 @@ type ListsIterator struct { // ListMailingLists returns the specified set of mailing lists administered by your account. func (mg *MailgunImpl) ListMailingLists(opts *ListOptions) *ListsIterator { - r := newHTTPRequest(generateApiUrl(mg, listsEndpoint) + "/pages") + r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint) + "/pages") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) if opts != nil { @@ -174,7 +174,7 @@ func (li *ListsIterator) fetch(ctx context.Context, url string) error { // while AccessLevel defaults to Everyone // and ReplyPreference defaults to List. func (mg *MailgunImpl) CreateMailingList(ctx context.Context, prototype MailingList) (MailingList, error) { - r := newHTTPRequest(generateApiUrl(mg, listsEndpoint)) + r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() @@ -205,7 +205,7 @@ func (mg *MailgunImpl) CreateMailingList(ctx context.Context, prototype MailingL // DeleteMailingList removes all current members of the list, then removes the list itself. // Attempts to send e-mail to the list will fail subsequent to this call. func (mg *MailgunImpl) DeleteMailingList(ctx context.Context, addr string) error { - r := newHTTPRequest(generateApiUrl(mg, listsEndpoint) + "/" + addr) + r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint) + "/" + addr) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -215,7 +215,7 @@ func (mg *MailgunImpl) DeleteMailingList(ctx context.Context, addr string) error // GetMailingList allows your application to recover the complete List structure // representing a mailing list, so long as you have its e-mail address. func (mg *MailgunImpl) GetMailingList(ctx context.Context, addr string) (MailingList, error) { - r := newHTTPRequest(generateApiUrl(mg, listsEndpoint) + "/" + addr) + r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint) + "/" + addr) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) response, err := makeGetRequest(ctx, r) @@ -236,7 +236,7 @@ func (mg *MailgunImpl) GetMailingList(ctx context.Context, addr string) (Mailing // e-mail sent to the old address will not succeed. // Make sure you account for the change accordingly. func (mg *MailgunImpl) UpdateMailingList(ctx context.Context, addr string, prototype MailingList) (MailingList, error) { - r := newHTTPRequest(generateApiUrl(mg, listsEndpoint) + "/" + addr) + r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint) + "/" + addr) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() diff --git a/mailing_lists_test.go b/mailing_lists_test.go index 4d27cdc..03aead8 100644 --- a/mailing_lists_test.go +++ b/mailing_lists_test.go @@ -12,11 +12,12 @@ import ( func TestMailingListMembers(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() address := randomEmail("list", testDomain) - _, err := mg.CreateMailingList(ctx, mailgun.MailingList{ + _, err = mg.CreateMailingList(ctx, mailgun.MailingList{ Address: address, Name: address, Description: "TestMailingListMembers-related mailing list", @@ -96,7 +97,9 @@ func TestMailingListMembers(t *testing.T) { func TestMailingLists(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() address := randomEmail("list", testDomain) @@ -119,7 +122,7 @@ func TestMailingLists(t *testing.T) { return count } - _, err := mg.CreateMailingList(ctx, protoList) + _, err = mg.CreateMailingList(ctx, protoList) require.NoError(t, err) defer func() { require.NoError(t, mg.DeleteMailingList(ctx, address)) @@ -152,11 +155,13 @@ func TestMailingLists(t *testing.T) { func TestListMailingListRegression(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() address := "test@example.com" - _, err := mg.CreateMailingList(ctx, mailgun.MailingList{ + _, err = mg.CreateMailingList(ctx, mailgun.MailingList{ Address: address, Name: "paging", Description: "Test paging", diff --git a/messages.go b/messages.go index 0acc65c..a6ace90 100644 --- a/messages.go +++ b/messages.go @@ -684,7 +684,7 @@ func (mg *MailgunImpl) Send(ctx context.Context, m SendableMessage) (mes, id str return "", "", err } - r := newHTTPRequest(generateApiUrlWithDomain(mg, m.Endpoint(), m.Domain())) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, m.Endpoint(), m.Domain())) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) // Override any HTTP headers if provided diff --git a/messages_test.go b/messages_test.go index aae656c..626d8e6 100644 --- a/messages_test.go +++ b/messages_test.go @@ -305,12 +305,15 @@ func TestSendMGOffline(t *testing.T) { assert.Equal(t, exampleText, req.FormValue("text")) assert.Equal(t, toUser, req.FormValue("to")) rsp := fmt.Sprintf(`{"message":"%s", "id":"%s"}`, exampleMessage, exampleID) - fmt.Fprint(w, rsp) + _, err := fmt.Fprint(w, rsp) + require.NoError(t, err) })) defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) + ctx := context.Background() m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser) @@ -343,7 +346,8 @@ func TestSendMGSeparateDomain(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) ctx := context.Background() m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser) @@ -397,10 +401,11 @@ func TestSendMGMessageVariables(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser) - err := m.AddVariable(exampleStrVarKey, exampleStrVarVal) + err = m.AddVariable(exampleStrVarKey, exampleStrVarVal) require.NoError(t, err) err = m.AddVariable(exampleBoolVarKey, false) require.NoError(t, err) @@ -469,10 +474,12 @@ func TestSendDomainError(t *testing.T) { for _, c := range cases { ctx := context.Background() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) + m := mailgun.NewMessage(c.domain, fromUser, exampleSubject, exampleText, "test@test.com") - _, _, err := mg.Send(ctx, m) + _, _, err = mg.Send(ctx, m) if c.isValid { require.NoError(t, err) } else { @@ -494,10 +501,11 @@ func TestSendEOFError(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser) - _, _, err := mg.Send(context.Background(), m) + _, _, err = mg.Send(context.Background(), m) require.NotNil(t, err) // TODO(vtopc): do not compare strings, use errors.Is or errors.As: require.Contains(t, err.Error(), "remote server prematurely closed connection: Post ") @@ -519,11 +527,12 @@ func TestHasRecipient(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) // No recipient m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText) - _, _, err := mg.Send(context.Background(), m) + _, _, err = mg.Send(context.Background(), m) require.EqualError(t, err, "message not valid") // Provided Bcc @@ -558,9 +567,10 @@ func TestResendStored(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) - _, _, err := mg.ReSend(context.Background(), srv.URL+"/v3/some-url") + _, _, err = mg.ReSend(context.Background(), srv.URL+"/v3/some-url") require.NotNil(t, err) require.EqualError(t, err, "must provide at least one recipient") @@ -590,7 +600,8 @@ func TestAddOverrideHeader(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) mg.AddOverrideHeader("Host", "example.com") mg.AddOverrideHeader("CustomHeader", "custom-value") ctx := context.Background() @@ -626,7 +637,8 @@ func TestOnBehalfOfSubaccount(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) mg.AddOverrideHeader("Host", "example.com") mg.AddOverrideHeader("CustomHeader", "custom-value") mg.SetOnBehalfOfSubaccount("mailgun.subaccount") @@ -665,7 +677,9 @@ func TestSendTLSOptions(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) + ctx := context.Background() m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser) @@ -695,7 +709,9 @@ func TestSendTemplate(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) + ctx := context.Background() m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, "", toUser) @@ -728,7 +744,9 @@ func TestSendTemplateOptions(t *testing.T) { defer srv.Close() mg := mailgun.NewMailgun(exampleAPIKey) - mg.SetAPIBase(srv.URL + "/v3") + err := mg.SetAPIBase(srv.URL) + require.NoError(t, err) + ctx := context.Background() m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, "", toUser) diff --git a/messages_v5.go b/messages_v5.go index 1204f44..4a7c313 100644 --- a/messages_v5.go +++ b/messages_v5.go @@ -440,7 +440,7 @@ func (mg *MailgunImpl) sendV5(ctx context.Context, m SendableMessage) (mes, id s return "", "", err } - r := newHTTPRequest(generateApiUrlWithDomain(mg, m.Endpoint(), m.Domain())) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, m.Endpoint(), m.Domain())) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) // Override any HTTP headers if provided diff --git a/mock.go b/mock.go index 4d65e9a..343876e 100644 --- a/mock.go +++ b/mock.go @@ -17,9 +17,7 @@ import ( type MockServer interface { Stop() - URL1() string - URL4() string - URL3() string + URL() string DomainIPS() []string DomainList() []DomainContainer ExportList() []Export @@ -151,17 +149,8 @@ func (ms *mockServer) Stop() { ms.srv.Close() } -func (ms *mockServer) URL1() string { - return ms.srv.URL + "/v1" -} - -// URL3 returns the URL used to connect to the mock server -func (ms *mockServer) URL3() string { - return ms.srv.URL + "/v3" -} - -func (ms *mockServer) URL4() string { - return ms.srv.URL + "/v4" +func (ms *mockServer) URL() string { + return ms.srv.URL } func toJSON(w http.ResponseWriter, obj any) { diff --git a/mock_messages.go b/mock_messages.go index afb0e1d..539a73a 100644 --- a/mock_messages.go +++ b/mock_messages.go @@ -34,7 +34,7 @@ func (ms *mockServer) createMessages(w http.ResponseWriter, r *http.Request) { stored.Name = events.EventStored stored.Timestamp = TimeToFloat(time.Now().UTC()) stored.ID = id - stored.Storage.URL = ms.URL3() + "/se.storage.url/messages/" + id + stored.Storage.URL = ms.URL() + "/v3/se.storage.url/messages/" + id stored.Storage.Key = id stored.Message.Headers = events.MessageHeaders{ Subject: r.FormValue("subject"), diff --git a/routes.go b/routes.go index bbf2edd..4693f6e 100644 --- a/routes.go +++ b/routes.go @@ -118,7 +118,7 @@ func (mg *MailgunImpl) ListRoutes(opts *ListOptions) *RoutesIterator { return &RoutesIterator{ mg: mg, - url: generateApiUrl(mg, routesEndpoint), + url: generateApiUrl(mg, 3, routesEndpoint), routesListResponse: routesListResponse{TotalCount: -1}, limit: limit, } @@ -262,7 +262,7 @@ func (ri *RoutesIterator) fetch(ctx context.Context, skip, limit int) error { // only a subset of the fields influence the operation. // See the Route structure definition for more details. func (mg *MailgunImpl) CreateRoute(ctx context.Context, prototype Route) (_ignored Route, err error) { - r := newHTTPRequest(generateApiUrl(mg, routesEndpoint)) + r := newHTTPRequest(generateApiUrl(mg, 3, routesEndpoint)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() @@ -284,7 +284,7 @@ func (mg *MailgunImpl) CreateRoute(ctx context.Context, prototype Route) (_ignor // To avoid ambiguity, Mailgun identifies the route by unique ID. // See the Route structure definition and the Mailgun API documentation for more details. func (mg *MailgunImpl) DeleteRoute(ctx context.Context, id string) error { - r := newHTTPRequest(generateApiUrl(mg, routesEndpoint) + "/" + id) + r := newHTTPRequest(generateApiUrl(mg, 3, routesEndpoint) + "/" + id) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -293,7 +293,7 @@ func (mg *MailgunImpl) DeleteRoute(ctx context.Context, id string) error { // GetRoute retrieves the complete route definition associated with the unique route ID. func (mg *MailgunImpl) GetRoute(ctx context.Context, id string) (Route, error) { - r := newHTTPRequest(generateApiUrl(mg, routesEndpoint) + "/" + id) + r := newHTTPRequest(generateApiUrl(mg, 3, routesEndpoint) + "/" + id) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var envelope struct { @@ -312,7 +312,7 @@ func (mg *MailgunImpl) GetRoute(ctx context.Context, id string) (Route, error) { // Only those route fields which are non-zero or non-empty are updated. // All other fields remain as-is. func (mg *MailgunImpl) UpdateRoute(ctx context.Context, id string, route Route) (Route, error) { - r := newHTTPRequest(generateApiUrl(mg, routesEndpoint) + "/" + id) + r := newHTTPRequest(generateApiUrl(mg, 3, routesEndpoint) + "/" + id) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() diff --git a/routes_test.go b/routes_test.go index 6b6eea1..7b8a20a 100644 --- a/routes_test.go +++ b/routes_test.go @@ -11,7 +11,8 @@ import ( func TestRouteCRUD(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() var countRoutes = func() int { @@ -59,7 +60,8 @@ func TestRouteCRUD(t *testing.T) { func TestRoutesIterator(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) it := mg.ListRoutes(&mailgun.ListOptions{Limit: 2}) diff --git a/spam_complaints.go b/spam_complaints.go index 4494ace..dcaf50b 100644 --- a/spam_complaints.go +++ b/spam_complaints.go @@ -26,7 +26,7 @@ type complaintsResponse struct { // Recipients of your messages can click on a link which sends feedback to Mailgun // indicating that the message they received is, to them, spam. func (mg *MailgunImpl) ListComplaints(domain string, opts *ListOptions) *ComplaintsIterator { - r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) if opts != nil { @@ -139,7 +139,7 @@ func (ci *ComplaintsIterator) fetch(ctx context.Context, url string) error { // GetComplaint returns a single complaint record filed by a recipient at the email address provided. // If no complaint exists, the Complaint instance returned will be empty. func (mg *MailgunImpl) GetComplaint(ctx context.Context, domain, address string) (Complaint, error) { - r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain) + "/" + address) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain) + "/" + address) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -151,7 +151,7 @@ func (mg *MailgunImpl) GetComplaint(ctx context.Context, domain, address string) // CreateComplaint registers the specified address as a recipient who has complained of receiving spam // from your domain. func (mg *MailgunImpl) CreateComplaint(ctx context.Context, domain, address string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() @@ -161,7 +161,7 @@ func (mg *MailgunImpl) CreateComplaint(ctx context.Context, domain, address stri } func (mg *MailgunImpl) CreateComplaints(ctx context.Context, domain string, addresses []string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -179,7 +179,7 @@ func (mg *MailgunImpl) CreateComplaints(ctx context.Context, domain string, addr // DeleteComplaint removes a previously registered e-mail address from the list of people who complained // of receiving spam from your domain. func (mg *MailgunImpl) DeleteComplaint(ctx context.Context, domain, address string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain) + "/" + address) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain) + "/" + address) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) diff --git a/spam_complaints_test.go b/spam_complaints_test.go index 9f85d75..d0edac5 100644 --- a/spam_complaints_test.go +++ b/spam_complaints_test.go @@ -12,7 +12,8 @@ import ( func TestGetComplaints(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() @@ -25,10 +26,12 @@ func TestGetComplaints(t *testing.T) { func TestGetComplaintFromRandomNoComplaint(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() - _, err := mg.GetComplaint(ctx, testDomain, randomString(64, "")+"@example.com") + _, err = mg.GetComplaint(ctx, testDomain, randomString(64, "")+"@example.com") require.NotNil(t, err) var ure *mailgun.UnexpectedResponseError @@ -38,7 +41,9 @@ func TestGetComplaintFromRandomNoComplaint(t *testing.T) { func TestCreateDeleteComplaint(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() var hasComplaint = func(email string) bool { @@ -69,7 +74,9 @@ func TestCreateDeleteComplaint(t *testing.T) { func TestCreateDeleteComplaintList(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() var hasComplaint = func(email string) bool { diff --git a/storage_test.go b/storage_test.go index cd00dc0..249671b 100644 --- a/storage_test.go +++ b/storage_test.go @@ -14,7 +14,8 @@ import ( func TestStorage(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) var ctx = context.Background() diff --git a/subaccounts.go b/subaccounts.go index 199f05b..316b4cf 100644 --- a/subaccounts.go +++ b/subaccounts.go @@ -245,5 +245,5 @@ func (mg *MailgunImpl) DisableSubaccount(ctx context.Context, subaccountId strin } func generateSubaccountsApiUrl(m Mailgun) string { - return fmt.Sprintf("%s/%s/%s", m.APIBase(), accountsEndpoint, subaccountsEndpoint) + return fmt.Sprintf("%s/v3/%s/%s", m.APIBase(), accountsEndpoint, subaccountsEndpoint) } diff --git a/subaccounts_test.go b/subaccounts_test.go index acd14a5..5a76ba2 100644 --- a/subaccounts_test.go +++ b/subaccounts_test.go @@ -18,7 +18,8 @@ const ( func TestListSubaccounts(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) iterator := mg.ListSubaccounts(nil) require.NotNil(t, iterator) @@ -38,7 +39,8 @@ func TestListSubaccounts(t *testing.T) { func TestSubaccountDetails(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() @@ -56,11 +58,12 @@ func TestSubaccountDetails(t *testing.T) { func TestSubaccountDetailsStatusNotFound(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() - _, err := mg.SubaccountDetails(ctx, "unexisting.id") + _, err = mg.SubaccountDetails(ctx, "unexisting.id") if err == nil { t.Fatal("Did not expect a subaccount to exist") } @@ -71,7 +74,8 @@ func TestSubaccountDetailsStatusNotFound(t *testing.T) { func TestCreateSubaccount(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() @@ -82,17 +86,19 @@ func TestCreateSubaccount(t *testing.T) { func TestEnableSubaccountAlreadyEnabled(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() - _, err := mg.EnableSubaccount(ctx, testEnabledSubaccountId) + _, err = mg.EnableSubaccount(ctx, testEnabledSubaccountId) require.NoError(t, err) } func TestEnableSubaccount(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() @@ -103,7 +109,8 @@ func TestEnableSubaccount(t *testing.T) { func TestDisableSubaccount(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() @@ -114,10 +121,11 @@ func TestDisableSubaccount(t *testing.T) { func TestDisableSubaccountAlreadyDisabled(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() - _, err := mg.DisableSubaccount(ctx, testDisabledSubaccountId) + _, err = mg.DisableSubaccount(ctx, testDisabledSubaccountId) require.NoError(t, err) } diff --git a/tags.go b/tags.go index 72b6c83..f21e922 100644 --- a/tags.go +++ b/tags.go @@ -28,7 +28,7 @@ type ListTagOptions struct { // DeleteTag removes all counters for a particular tag, including the tag itself. func (mg *MailgunImpl) DeleteTag(ctx context.Context, domain, tag string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, tagsEndpoint, domain) + "/" + tag) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, tagsEndpoint, domain) + "/" + tag) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -37,7 +37,7 @@ func (mg *MailgunImpl) DeleteTag(ctx context.Context, domain, tag string) error // GetTag retrieves metadata about the tag from the api func (mg *MailgunImpl) GetTag(ctx context.Context, domain, tag string) (Tag, error) { - r := newHTTPRequest(generateApiUrlWithDomain(mg, tagsEndpoint, domain) + "/" + tag) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, tagsEndpoint, domain) + "/" + tag) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var tagItem Tag @@ -58,7 +58,7 @@ func (mg *MailgunImpl) GetTag(ctx context.Context, domain, tag string) (Tag, err // log.Fatal(it.Err()) // } func (mg *MailgunImpl) ListTags(domain string, opts *ListTagOptions) *TagIterator { - req := newHTTPRequest(generateApiUrlWithDomain(mg, tagsEndpoint, domain)) + req := newHTTPRequest(generateApiV3UrlWithDomain(mg, tagsEndpoint, domain)) if opts != nil { if opts.Limit != 0 { req.addParameter("limit", strconv.Itoa(opts.Limit)) diff --git a/tags_test.go b/tags_test.go index 50e4b31..9d890b0 100644 --- a/tags_test.go +++ b/tags_test.go @@ -19,7 +19,9 @@ const ( func TestTags(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + msg := mailgun.NewMessage(testDomain, fromUser, exampleSubject, exampleText, "test@example.com") require.NoError(t, msg.AddTag("newsletter")) require.NoError(t, msg.AddTag("homer")) @@ -29,7 +31,7 @@ func TestTags(t *testing.T) { ctx := context.Background() // Create an email with some tags attached - _, _, err := mg.Send(ctx, msg) + _, _, err = mg.Send(ctx, msg) require.NoError(t, err) // Wait for the tag to show up @@ -87,7 +89,9 @@ func waitForTag(mg mailgun.Mailgun, tag string) error { func TestDeleteTag(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() require.NoError(t, mg.DeleteTag(ctx, testDomain, "newsletter")) diff --git a/template.go b/template.go index ce96098..8951bea 100644 --- a/template.go +++ b/template.go @@ -33,7 +33,7 @@ type templateListResp struct { // Create a new template which can be used to attach template versions to func (mg *MailgunImpl) CreateTemplate(ctx context.Context, domain string, template *Template) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -69,7 +69,7 @@ func (mg *MailgunImpl) CreateTemplate(ctx context.Context, domain string, templa // GetTemplate gets a template given the template name func (mg *MailgunImpl) GetTemplate(ctx context.Context, domain, name string) (Template, error) { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + name) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + name) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) r.addParameter("active", "yes") @@ -88,7 +88,7 @@ func (mg *MailgunImpl) UpdateTemplate(ctx context.Context, domain string, templa return errors.New("UpdateTemplate() Template.Name cannot be empty") } - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + template.Name) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + template.Name) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() @@ -111,7 +111,7 @@ func (mg *MailgunImpl) UpdateTemplate(ctx context.Context, domain string, templa // Delete a template given a template name func (mg *MailgunImpl) DeleteTemplate(ctx context.Context, domain, name string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + name) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + name) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -131,7 +131,7 @@ type ListTemplateOptions struct { // List all available templates func (mg *MailgunImpl) ListTemplates(domain string, opts *ListTemplateOptions) *TemplatesIterator { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) if opts != nil { diff --git a/template_test.go b/template_test.go index 28cb6dd..0fbf3de 100644 --- a/template_test.go +++ b/template_test.go @@ -14,7 +14,9 @@ import ( func TestTemplateCRUD(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() findTemplate := func(name string) bool { diff --git a/template_versions.go b/template_versions.go index f4e50c5..65b9a0b 100644 --- a/template_versions.go +++ b/template_versions.go @@ -24,7 +24,7 @@ type templateVersionListResp struct { // AddTemplateVersion adds a template version to a template func (mg *MailgunImpl) AddTemplateVersion(ctx context.Context, domain, templateName string, version *TemplateVersion) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions") + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -54,7 +54,7 @@ func (mg *MailgunImpl) AddTemplateVersion(ctx context.Context, domain, templateN // GetTemplateVersion gets a specific version of a template func (mg *MailgunImpl) GetTemplateVersion(ctx context.Context, domain, templateName, tag string) (TemplateVersion, error) { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + tag) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + tag) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -68,7 +68,7 @@ func (mg *MailgunImpl) GetTemplateVersion(ctx context.Context, domain, templateN // Update the comment and mark a version of a template active func (mg *MailgunImpl) UpdateTemplateVersion(ctx context.Context, domain, templateName string, version *TemplateVersion) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + version.Tag) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + version.Tag) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() @@ -94,7 +94,7 @@ func (mg *MailgunImpl) UpdateTemplateVersion(ctx context.Context, domain, templa // Delete a specific version of a template func (mg *MailgunImpl) DeleteTemplateVersion(ctx context.Context, domain, templateName, tag string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + tag) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + tag) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -109,7 +109,7 @@ type TemplateVersionsIterator struct { // ListTemplateVersions lists all the versions of a specific template func (mg *MailgunImpl) ListTemplateVersions(domain, templateName string, opts *ListOptions) *TemplateVersionsIterator { - r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions") + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions") r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) if opts != nil { diff --git a/template_versions_test.go b/template_versions_test.go index f6c8467..39c1adf 100644 --- a/template_versions_test.go +++ b/template_versions_test.go @@ -11,7 +11,9 @@ import ( func TestTemplateVersionsCRUD(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() findVersion := func(templateName, tag string) bool { diff --git a/unsubscribes.go b/unsubscribes.go index 019b5c4..d76b419 100644 --- a/unsubscribes.go +++ b/unsubscribes.go @@ -19,7 +19,7 @@ type unsubscribesResponse struct { // Fetches the list of unsubscribes func (mg *MailgunImpl) ListUnsubscribes(domain string, opts *ListOptions) *UnsubscribesIterator { - r := newHTTPRequest(generateApiUrlWithDomain(mg, unsubscribesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, unsubscribesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) if opts != nil { @@ -131,7 +131,7 @@ func (ci *UnsubscribesIterator) fetch(ctx context.Context, url string) error { // Retreives a single unsubscribe record. Can be used to check if a given address is present in the list of unsubscribed users. func (mg *MailgunImpl) GetUnsubscribe(ctx context.Context, domain, address string) (Unsubscribe, error) { - r := newHTTPRequest(generateApiUrlWithTarget(mg, unsubscribesEndpoint, domain, address)) + r := newHTTPRequest(generateApiV3UrlWithTarget(mg, unsubscribesEndpoint, domain, address)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -143,7 +143,7 @@ func (mg *MailgunImpl) GetUnsubscribe(ctx context.Context, domain, address strin // Unsubscribe adds an e-mail address to the domain's unsubscription table. func (mg *MailgunImpl) CreateUnsubscribe(ctx context.Context, domain, address, tag string) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, unsubscribesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, unsubscribesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() @@ -155,7 +155,7 @@ func (mg *MailgunImpl) CreateUnsubscribe(ctx context.Context, domain, address, t // CreateUnsubscribes adds multiple e-mail addresses to the domain's unsubscription table. func (mg *MailgunImpl) CreateUnsubscribes(ctx context.Context, domain string, unsubscribes []Unsubscribe) error { - r := newHTTPRequest(generateApiUrlWithDomain(mg, unsubscribesEndpoint, domain)) + r := newHTTPRequest(generateApiV3UrlWithDomain(mg, unsubscribesEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) r.addHeader("Content-Type", "application/json") @@ -169,7 +169,7 @@ func (mg *MailgunImpl) CreateUnsubscribes(ctx context.Context, domain string, un // If passing in an ID (discoverable from, e.g., ListUnsubscribes()), the e-mail address associated // with the given ID will be removed. func (mg *MailgunImpl) DeleteUnsubscribe(ctx context.Context, domain, address string) error { - r := newHTTPRequest(generateApiUrlWithTarget(mg, unsubscribesEndpoint, domain, address)) + r := newHTTPRequest(generateApiV3UrlWithTarget(mg, unsubscribesEndpoint, domain, address)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -180,7 +180,7 @@ func (mg *MailgunImpl) DeleteUnsubscribe(ctx context.Context, domain, address st // If passing in an ID (discoverable from, e.g., ListUnsubscribes()), the e-mail address associated // with the given ID will be removed. func (mg *MailgunImpl) DeleteUnsubscribeWithTag(ctx context.Context, domain, a, t string) error { - r := newHTTPRequest(generateApiUrlWithTarget(mg, unsubscribesEndpoint, domain, a)) + r := newHTTPRequest(generateApiV3UrlWithTarget(mg, unsubscribesEndpoint, domain, a)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) r.addParameter("tag", t) diff --git a/unsubscribes_test.go b/unsubscribes_test.go index 7787f9d..deb04f6 100644 --- a/unsubscribes_test.go +++ b/unsubscribes_test.go @@ -11,7 +11,8 @@ import ( func TestCreateUnsubscriber(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) email := randomEmail("unsubcribe", os.Getenv("MG_DOMAIN")) ctx := context.Background() @@ -31,7 +32,9 @@ func TestCreateUnsubscribes(t *testing.T) { }, } mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() // Create unsubscription records @@ -40,7 +43,9 @@ func TestCreateUnsubscribes(t *testing.T) { func TestListUnsubscribes(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) + ctx := context.Background() it := mg.ListUnsubscribes(testDomain, nil) @@ -59,7 +64,8 @@ func TestListUnsubscribes(t *testing.T) { func TestGetUnsubscribe(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) email := randomEmail("unsubcribe", os.Getenv("MG_DOMAIN")) @@ -78,7 +84,8 @@ func TestGetUnsubscribe(t *testing.T) { func TestCreateDestroyUnsubscription(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) email := randomEmail("unsubcribe", os.Getenv("MG_DOMAIN")) @@ -87,7 +94,7 @@ func TestCreateDestroyUnsubscription(t *testing.T) { // Create unsubscription record require.NoError(t, mg.CreateUnsubscribe(ctx, testDomain, email, "*")) - _, err := mg.GetUnsubscribe(ctx, testDomain, email) + _, err = mg.GetUnsubscribe(ctx, testDomain, email) require.NoError(t, err) // Destroy the unsubscription record diff --git a/webhooks.go b/webhooks.go index 2bbfe52..81733c9 100644 --- a/webhooks.go +++ b/webhooks.go @@ -30,7 +30,7 @@ type WebHookResponse struct { // ListWebhooks returns the complete set of webhooks configured for your domain. // Note that a zero-length mapping is not an error. func (mg *MailgunImpl) ListWebhooks(ctx context.Context, domain string) (map[string][]string, error) { - r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain)) + r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -54,7 +54,7 @@ func (mg *MailgunImpl) ListWebhooks(ctx context.Context, domain string) (map[str // CreateWebhook installs a new webhook for your domain. func (mg *MailgunImpl) CreateWebhook(ctx context.Context, domain, id string, urls []string) error { - r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain)) + r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain)) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() @@ -68,7 +68,7 @@ func (mg *MailgunImpl) CreateWebhook(ctx context.Context, domain, id string, url // DeleteWebhook removes the specified webhook from your domain's configuration. func (mg *MailgunImpl) DeleteWebhook(ctx context.Context, domain, name string) error { - r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name) + r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) _, err := makeDeleteRequest(ctx, r) @@ -77,7 +77,7 @@ func (mg *MailgunImpl) DeleteWebhook(ctx context.Context, domain, name string) e // GetWebhook retrieves the currently assigned webhook URL associated with the provided type of webhook. func (mg *MailgunImpl) GetWebhook(ctx context.Context, domain, name string) ([]string, error) { - r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name) + r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) var body WebHookResponse @@ -96,7 +96,7 @@ func (mg *MailgunImpl) GetWebhook(ctx context.Context, domain, name string) ([]s // UpdateWebhook replaces one webhook setting for another. func (mg *MailgunImpl) UpdateWebhook(ctx context.Context, domain, name string, urls []string) error { - r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name) + r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name) r.setClient(mg.HTTPClient()) r.setBasicAuth(basicAuthUser, mg.APIKey()) p := newUrlEncodedPayload() diff --git a/webhooks_test.go b/webhooks_test.go index c7aa2d2..9f73aa6 100644 --- a/webhooks_test.go +++ b/webhooks_test.go @@ -20,7 +20,8 @@ import ( func TestGetWebhook(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() list, err := mg.ListWebhooks(ctx, testDomain) @@ -35,7 +36,8 @@ func TestGetWebhook(t *testing.T) { func TestWebhookCRUD(t *testing.T) { mg := mailgun.NewMailgun(testKey) - mg.SetAPIBase(server.URL3()) + err := mg.SetAPIBase(server.URL()) + require.NoError(t, err) ctx := context.Background() list, err := mg.ListWebhooks(ctx, testDomain)