Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DE-1387 Release v5 #367

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
52 changes: 25 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Mailgun with Go

[![GoDoc](https://godoc.org/github.com/mailgun/mailgun-go?status.svg)](https://godoc.org/github.com/mailgun/mailgun-go/v4)
[![GoDoc](https://godoc.org/github.com/mailgun/mailgun-go?status.svg)](https://godoc.org/github.com/mailgun/mailgun-go/v5)
[![Build Status](https://github.com/mailgun/mailgun-go/workflows/CI/badge.svg)](https://github.com/mailgun/mailgun-go/actions/workflows/main.yml?query=branch%3Amaster)

Go library for interacting with the [Mailgun](https://mailgun.com/) [API](https://documentation.mailgun.com/en/latest/api_reference.html).

## Installation

If you are using [Go Modules](https://go.dev/wiki/Modules) make sure you
include the `/v4` at the end of your import paths
include the `/v5` at the end of your import paths
```bash
$ go get github.com/mailgun/mailgun-go/v4
$ go get github.com/mailgun/mailgun-go/v5
```

## Usage
Expand All @@ -23,7 +23,7 @@ import (
"log"
"time"

"github.com/mailgun/mailgun-go/v4"
"github.com/mailgun/mailgun-go/v5"
)

// Your available domain names can be found here:
Expand All @@ -36,7 +36,7 @@ var privateAPIKey = "your-private-key"

func main() {
// Create an instance of the Mailgun Client
mg := mailgun.NewMailgun(yourDomain, privateAPIKey)
mg := mailgun.NewMailgun(privateAPIKey)

//When you have an EU-domain, you must specify the endpoint:
//mg.SetAPIBase("https://api.eu.mailgun.net/v3")
Expand All @@ -47,7 +47,7 @@ func main() {
recipient := "[email protected]"

// The message object allows you to add attachments and Bcc recipients
message := mailgun.NewMessage(sender, subject, body, recipient)
message := mailgun.NewMessage(yourDomain, sender, subject, body, recipient)

ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
Expand All @@ -72,16 +72,16 @@ import (
"fmt"
"time"

"github.com/mailgun/mailgun-go/v4"
"github.com/mailgun/mailgun-go/v4/events"
"github.com/mailgun/mailgun-go/v5"
"github.com/mailgun/mailgun-go/v5/events"
)

func main() {
// You can find the Private API Key in your Account Menu, under "Settings":
// (https://app.mailgun.com/settings/api_security)
mg := mailgun.NewMailgun("your-domain.com", "your-private-key")
mg := mailgun.NewMailgun("your-private-key")

it := mg.ListEvents(&mailgun.ListEventOptions{Limit: 100})
it := mg.ListEvents("your-domain.com", &mailgun.ListEventOptions{Limit: 100})

var page []mailgun.Event

Expand Down Expand Up @@ -129,18 +129,18 @@ import (
"log"
"time"

"github.com/mailgun/mailgun-go/v4"
"github.com/mailgun/mailgun-go/v5"
)

func main() {
// You can find the Private API Key in your Account Menu, under "Settings":
// (https://app.mailgun.com/settings/api_security)
mg := mailgun.NewMailgun("your-domain.com", "your-private-key")
mg := mailgun.NewMailgun("your-private-key")

begin := time.Now().Add(time.Second * -3)

// Very short poll interval
it := mg.PollEvents(&mailgun.ListEventOptions{
it := mg.PollEvents("your-domain.com", &mailgun.ListEventOptions{
// Only events with a timestamp after this date/time will be returned
Begin: begin,
// How often we poll the api for new events
Expand Down Expand Up @@ -170,7 +170,7 @@ import (
"fmt"
"time"

"github.com/mailgun/mailgun-go/v4"
"github.com/mailgun/mailgun-go/v5"
)

// Your plan should include email validations.
Expand Down Expand Up @@ -203,18 +203,17 @@ import (
"net/http"
"os"

"github.com/mailgun/mailgun-go/v4"
"github.com/mailgun/mailgun-go/v4/events"
"github.com/mailgun/mailgun-go/v5"
"github.com/mailgun/mailgun-go/v5/events"
)

func main() {
// You can find the Private API Key in your Account Menu, under "Settings":
// (https://app.mailgun.com/settings/api_security)
mg := mailgun.NewMailgun("your-domain.com", "private-api-key")
mg := mailgun.NewMailgun("private-api-key")
mg.SetWebhookSigningKey("webhook-signing-key")

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

var payload mailgun.WebhookPayload
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
fmt.Printf("decode JSON error: %s", err)
Expand Down Expand Up @@ -271,7 +270,7 @@ import (
"log"
"time"

"github.com/mailgun/mailgun-go/v4"
"github.com/mailgun/mailgun-go/v5"
)

// Your available domain names can be found here:
Expand All @@ -284,13 +283,13 @@ var privateAPIKey = "your-private-key"

func main() {
// Create an instance of the Mailgun Client
mg := mailgun.NewMailgun(yourDomain, privateAPIKey)
mg := mailgun.NewMailgun(privateAPIKey)

sender := "[email protected]"
subject := "HTML email!"
recipient := "[email protected]"

message := mailgun.NewMessage(sender, subject, "", recipient)
message := mailgun.NewMessage(yourDomain, sender, subject, "", recipient)
body := `
<html>
<body>
Expand All @@ -306,7 +305,7 @@ func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

// Send the message with a 10 second timeout
// Send the message with a 10-second timeout
resp, id, err := mg.Send(ctx, message)

if err != nil {
Expand All @@ -330,7 +329,7 @@ import (
"log"
"time"

"github.com/mailgun/mailgun-go/v4"
"github.com/mailgun/mailgun-go/v5"
)

// Your available domain names can be found here:
Expand All @@ -343,15 +342,15 @@ var privateAPIKey = "your-private-key"

func main() {
// Create an instance of the Mailgun Client
mg := mailgun.NewMailgun(yourDomain, privateAPIKey)
mg := mailgun.NewMailgun(privateAPIKey)

sender := "[email protected]"
subject := "Fancy subject!"
body := ""
recipient := "[email protected]"

// The message object allows you to add attachments and Bcc recipients
message := mailgun.NewMessage(sender, subject, body, recipient)
message := mailgun.NewMessage(yourDomain, sender, subject, body, recipient)
message.SetTemplate("passwordReset")
err := message.AddTemplateVariable("passwordResetLink", "some link to your site unique to your user")
if err != nil {
Expand Down Expand Up @@ -379,7 +378,7 @@ and click on the "Go" button at the top of the page.
European customers will need to change the default API Base to access your domains

```go
mg := mailgun.NewMailgun("your-domain.com", "private-api-key")
mg := mailgun.NewMailgun("private-api-key")
mg.SetAPIBase(mailgun.APIBaseEU)
```

Expand All @@ -390,7 +389,6 @@ mg.SetAPIBase(mailgun.APIBaseEU)
To run the tests various environment variables must be set. These are:

* `MG_DOMAIN` is the domain name - this is a value registered in the Mailgun admin interface.
* `MG_PUBLIC_API_KEY` is the Public Validation API key - you can get this value from the Mailgun [security page](https://app.mailgun.com/settings/api_security)
* `MG_API_KEY` is the Private API key - you can get this value from the Mailgun [security page](https://app.mailgun.com/settings/api_security)
* `MG_EMAIL_TO` is the email address used in various sending tests.

Expand Down
2 changes: 1 addition & 1 deletion acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

// Return the variable missing which caused the test to be skipped
func SkipNetworkTest() string {
for _, env := range []string{"MG_DOMAIN", "MG_API_KEY", "MG_EMAIL_TO", "MG_PUBLIC_API_KEY"} {
for _, env := range []string{"MG_DOMAIN", "MG_API_KEY", "MG_EMAIL_TO"} {
if os.Getenv(env) == "" {
return fmt.Sprintf("'%s' missing from environment skipping...", env)
}
Expand Down
23 changes: 10 additions & 13 deletions analytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ type MetricsPagination struct {

// ListMetrics returns domain/account metrics.
//
// To filter by domain:
//
// opts.Filter.BoolGroupAnd = []mailgun.MetricsFilterPredicate{{
// Attribute: "domain",
// Comparator: "=",
// LabeledValues: []mailgun.MetricsLabeledValue{{Label: "example.com", Value: "example.com"}},
// }}
//
// NOTE: Only for v1 API. To use the /v1 version define MG_URL in the environment variable
// as `https://api.mailgun.net/v1` or set `mg.SetAPIBase("https://api.mailgun.net/v1")`
//
Expand All @@ -31,23 +39,12 @@ func (mg *MailgunImpl) ListMetrics(opts MetricsOptions) (*MetricsIterator, error
return nil, errors.New("only v1 API is supported")
}

domain := mg.Domain()
if domain != "" {
domainFilter := MetricsFilterPredicate{
Attribute: "domain",
Comparator: "=",
LabeledValues: []MetricsLabeledValue{{Label: domain, Value: domain}},
}

opts.Filter.BoolGroupAnd = append(opts.Filter.BoolGroupAnd, domainFilter)
}

if opts.Pagination.Limit == 0 {
opts.Pagination.Limit = 10
}

req := newHTTPRequest(generatePublicApiUrl(mg, metricsEndpoint))
req.setClient(mg.Client())
req := newHTTPRequest(generateApiUrl(mg, metricsEndpoint))
req.setClient(mg.HTTPClient())
req.setBasicAuth(basicAuthUser, mg.APIKey())

return &MetricsIterator{
Expand Down
8 changes: 7 additions & 1 deletion analytics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

func TestListMetrics(t *testing.T) {
mg := mailgun.NewMailgun(testDomain, testKey)
mg := mailgun.NewMailgun(testKey)
mg.SetAPIBase(server.URL1())

start, _ := mailgun.NewRFC2822Time("Tue, 24 Sep 2024 00:00:00 +0000")
Expand All @@ -23,6 +23,12 @@ func TestListMetrics(t *testing.T) {
Limit: 10,
},
}
// filter by domain
opts.Filter.BoolGroupAnd = []mailgun.MetricsFilterPredicate{{
Attribute: "domain",
Comparator: "=",
LabeledValues: []mailgun.MetricsLabeledValue{{Label: testDomain, Value: testDomain}},
}}

wantResp := mailgun.MetricsResponse{
Start: start,
Expand Down
8 changes: 4 additions & 4 deletions attachments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ func createAttachment(t *testing.T) string {
}

func TestMultipleAttachments(t *testing.T) {
mg := mailgun.NewMailgun(testDomain, testKey)
mg.SetAPIBase(server.URL())
mg := mailgun.NewMailgun(testKey)
mg.SetAPIBase(server.URL3())

var ctx = context.Background()

m := mailgun.NewMessage("root@"+testDomain, "Subject", "Text Body", "attachment@"+testDomain)
m := mailgun.NewMessage(testDomain, "root@"+testDomain, "Subject", "Text Body", "attachment@"+testDomain)

// Add 2 attachments
m.AddAttachment(createAttachment(t))
Expand All @@ -56,7 +56,7 @@ func TestMultipleAttachments(t *testing.T) {
}

func findAcceptedMessage(mg mailgun.Mailgun, id string) (*events.Accepted, error) {
it := mg.ListEvents(nil)
it := mg.ListEvents(testDomain, nil)

var page []mailgun.Event
for it.Next(context.Background(), &page) {
Expand Down
38 changes: 19 additions & 19 deletions bounces.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ type bouncesListResponse struct {
// The results include the total number of bounces (regardless of skip or limit settings),
// 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(opts *ListOptions) *BouncesIterator {
r := newHTTPRequest(generateApiUrl(mg, bouncesEndpoint))
r.setClient(mg.Client())
func (mg *MailgunImpl) ListBounces(domain string, opts *ListOptions) *BouncesIterator {
r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain))
r.setClient(mg.HTTPClient())
r.setBasicAuth(basicAuthUser, mg.APIKey())
if opts != nil {
if opts.Limit != 0 {
Expand Down Expand Up @@ -139,16 +139,16 @@ func (ci *BouncesIterator) Previous(ctx context.Context, items *[]Bounce) bool {
func (ci *BouncesIterator) fetch(ctx context.Context, url string) error {
ci.Items = nil
r := newHTTPRequest(url)
r.setClient(ci.mg.Client())
r.setClient(ci.mg.HTTPClient())
r.setBasicAuth(basicAuthUser, ci.mg.APIKey())

return getResponseFromJSON(ctx, r, &ci.bouncesListResponse)
}

// GetBounce retrieves a single bounce record, if any exist, for the given recipient address.
func (mg *MailgunImpl) GetBounce(ctx context.Context, address string) (Bounce, error) {
r := newHTTPRequest(generateApiUrl(mg, bouncesEndpoint) + "/" + address)
r.setClient(mg.Client())
func (mg *MailgunImpl) GetBounce(ctx context.Context, domain, address string) (Bounce, error) {
r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address)
r.setClient(mg.HTTPClient())
r.setBasicAuth(basicAuthUser, mg.APIKey())

var response Bounce
Expand All @@ -172,9 +172,9 @@ func (mg *MailgunImpl) GetBounce(ctx context.Context, address string) (Bounce, e
//
// Note that both code and error exist as strings, even though
// code will report as a number.
func (mg *MailgunImpl) AddBounce(ctx context.Context, address, code, bounceError string) error {
r := newHTTPRequest(generateApiUrl(mg, bouncesEndpoint))
r.setClient(mg.Client())
func (mg *MailgunImpl) AddBounce(ctx context.Context, domain, address, code, bounceError string) error {
r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain))
r.setClient(mg.HTTPClient())
r.setBasicAuth(basicAuthUser, mg.APIKey())

payload := newUrlEncodedPayload()
Expand All @@ -190,9 +190,9 @@ func (mg *MailgunImpl) AddBounce(ctx context.Context, address, code, bounceError
}

// Add Bounces adds a list of bounces to the bounce list
func (mg *MailgunImpl) AddBounces(ctx context.Context, bounces []Bounce) error {
r := newHTTPRequest(generateApiUrl(mg, bouncesEndpoint))
r.setClient(mg.Client())
func (mg *MailgunImpl) AddBounces(ctx context.Context, domain string, bounces []Bounce) error {
r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain))
r.setClient(mg.HTTPClient())
r.setBasicAuth(basicAuthUser, mg.APIKey())

payload := newJSONEncodedPayload(bounces)
Expand All @@ -202,18 +202,18 @@ func (mg *MailgunImpl) AddBounces(ctx context.Context, bounces []Bounce) error {
}

// DeleteBounce removes all bounces associted with the provided e-mail address.
func (mg *MailgunImpl) DeleteBounce(ctx context.Context, address string) error {
r := newHTTPRequest(generateApiUrl(mg, bouncesEndpoint) + "/" + address)
r.setClient(mg.Client())
func (mg *MailgunImpl) DeleteBounce(ctx context.Context, domain, address string) error {
r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address)
r.setClient(mg.HTTPClient())
r.setBasicAuth(basicAuthUser, mg.APIKey())
_, err := makeDeleteRequest(ctx, r)
return err
}

// DeleteBounceList removes all bounces in the bounce list
func (mg *MailgunImpl) DeleteBounceList(ctx context.Context) error {
r := newHTTPRequest(generateApiUrl(mg, bouncesEndpoint))
r.setClient(mg.Client())
func (mg *MailgunImpl) DeleteBounceList(ctx context.Context, domain string) error {
r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain))
r.setClient(mg.HTTPClient())
r.setBasicAuth(basicAuthUser, mg.APIKey())
_, err := makeDeleteRequest(ctx, r)
return err
Expand Down
Loading
Loading