Skip to content
Go library for sending mail with the Mailgun API.
Branch: master
Clone or download
thrawn01 Merge pull request #184 from thrawn01/thrawn/develop
Added support for sending with template using the new template API
Latest commit df42160 Apr 23, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
events Added Description and AttemptNo to DeliveryStatus Apr 1, 2019
examples Moved password into create domain options Apr 22, 2019
.gitignore Release Candidate 2.0 Oct 2, 2018
.travis.yml Updated travis to build with 1.11 and modules Jan 9, 2019
CHANGELOG Moved password into create domain options Apr 22, 2019
LICENSE Changed year - shouldn't this contain all the authors?! Aug 14, 2016
Makefile DomainList() now returns an iterator Jan 14, 2019
README.md Fixed issue with Next() for limit/skip based iterators Jan 23, 2019
acceptance_test.go ran gofmt on project Jan 15, 2019
bounces.go Fix function comments based on best practices from Effective Go Feb 28, 2019
bounces_test.go Merge branch 'thrawn/develop' of github.com:thrawn01/mailgun-go into … Apr 1, 2019
common_test.go mailing list tests now use the mock server Jan 7, 2019
credentials.go Fix function comments based on best practices from Effective Go Feb 28, 2019
credentials_test.go ListBounces() now returns a page iterator Jan 11, 2019
domains.go Moved password into create domain options Apr 22, 2019
domains_test.go Moved password into create domain options Apr 22, 2019
email_validation.go Fix function comments based on best practices from Effective Go Feb 28, 2019
email_validation_test.go Now using go modules for dependency management Jan 9, 2019
events.go Check for parsing errors Apr 17, 2019
events_test.go Merge branch 'thrawn/develop' of github.com:thrawn01/mailgun-go into … Apr 1, 2019
examples_test.go Fixed issue with Next() for limit/skip based iterators Jan 23, 2019
exports.go Fix function comments based on best practices from Effective Go Feb 28, 2019
exports_test.go Test suite will run without MG_ env vars defined Jan 10, 2019
go.mod GetStoredMessage() not accepts a URL instead of an id Feb 11, 2019
go.sum Removed mailgun cli from project Jan 14, 2019
httphelpers.go Address github issues Jan 15, 2019
ips.go Fix function comments based on best practices from Effective Go Feb 28, 2019
ips_test.go Test suite will run without MG_ env vars defined Jan 10, 2019
limits.go Fix function comments based on best practices from Effective Go Feb 28, 2019
limits_test.go Test suite will run without MG_ env vars defined Jan 10, 2019
mailgun.go Moved password into create domain options Apr 22, 2019
mailgun_test.go ListBounces() now returns a page iterator Jan 11, 2019
mailing_lists.go Fix function comments based on best practices from Effective Go Feb 28, 2019
mailing_lists_test.go DomainList() now returns an iterator Jan 14, 2019
members.go Fix function comments based on best practices from Effective Go Feb 28, 2019
messages.go Added support for sending with template using the new template API Apr 22, 2019
messages_test.go Added template send example Apr 22, 2019
mock.go Fix function comments based on best practices from Effective Go Feb 28, 2019
mock_domains.go Add /verify path to mailgun mock server Jan 24, 2019
mock_events.go Now using go modules for dependency management Jan 9, 2019
mock_exports.go Added GetDomainTracking() Jan 4, 2019
mock_ips.go Added GetDomainTracking() Jan 4, 2019
mock_mailing_list.go DomainList() now returns an iterator Jan 14, 2019
mock_messages.go GetStoredMessage() not accepts a URL instead of an id Feb 11, 2019
mock_routes.go Added support for Templates API Jan 12, 2019
mock_validation.go Implemented strongly typed events Jan 8, 2019
parse.go Added support for webhooks 2.0 Jan 21, 2019
parse_test.go Merge branch 'thrawn/develop' of github.com:thrawn01/mailgun-go into … Apr 1, 2019
recipients.go Add recipient struct with marshalling/unmarshalling Mar 17, 2017
rest_shim.go Now using go modules for dependency management Jan 9, 2019
rfc2822.go ListBounces() now returns a page iterator Jan 11, 2019
routes.go
routes_test.go DomainList() now returns an iterator Jan 14, 2019
spam_complaints.go Fix function comments based on best practices from Effective Go Feb 28, 2019
spam_complaints_test.go ListBounces() now returns a page iterator Jan 11, 2019
stats.go Fix function comments based on best practices from Effective Go Feb 28, 2019
stats_test.go ListBounces() now returns a page iterator Jan 11, 2019
storage_test.go GetStoredMessage() not accepts a URL instead of an id Feb 11, 2019
tags.go Fix function comments based on best practices from Effective Go Feb 28, 2019
tags_test.go CreateDomain now accepts CreateDomainOption{} Jan 10, 2019
template.go Moved password into create domain options Apr 22, 2019
template_test.go Updated template API to reflect latest changes Feb 7, 2019
template_versions.go Fix function comments based on best practices from Effective Go Feb 28, 2019
template_versions_test.go Updated template API to reflect latest changes Feb 7, 2019
unsubscribes.go Merge pull request #170 from CodeLingoBot/rewrite Mar 11, 2019
unsubscribes_test.go ListBounces() now returns a page iterator Jan 11, 2019
version.go Added UserVariables to all Message events Mar 28, 2019
webhooks.go Added support for webhooks 2.0 Jan 21, 2019
webhooks_test.go Added support for webhooks 2.0 Jan 21, 2019

README.md

Mailgun with Go

GoDoc Build Status

Go library for interacting with the Mailgun API.

NOTE: Backward compatibility has been broken with the v3.0 release which includes versioned paths required by 1.11 go modules (See Releasing Modules). Pin your dependencies to the v1.1.1 or v2.0 tag if you are not ready for v3.0

Usage

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/mailgun/mailgun-go/v3"
)

// Your available domain names can be found here:
// (https://app.mailgun.com/app/domains)
var yourDomain string = "your-domain-name" // e.g. mg.yourcompany.com

// You can find the Private API Key in your Account Menu, under "Settings":
// (https://app.mailgun.com/app/account/security)
var privateAPIKey string = "your-private-key"


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

    sender := "sender@example.com"
    subject := "Fancy subject!"
    body := "Hello from Mailgun Go!"
    recipient := "recipient@example.com"

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

    ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
    defer cancel()

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

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("ID: %s Resp: %s\n", id, resp)
}

Get Events

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/mailgun/mailgun-go/v3"
    "github.com/mailgun/mailgun-go/v3/events"
)

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

	it := mg.ListEvents(&mailgun.ListEventOptions{Limit: 100})

	var page []mailgun.Event

	// The entire operation should not take longer than 30 seconds
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
	defer cancel()

	// For each page of 100 events
	for it.Next(ctx, &page) {
		for _, e := range page {
			// You can access some fields via the interface
			fmt.Printf("Event: '%s' TimeStamp: '%s'\n", e.GetName(), e.GetTimestamp())

			// and you can act upon each event by type
			switch event := e.(type) {
			case *events.Accepted:
				fmt.Printf("Accepted: auth: %t\n", event.Flags.IsAuthenticated)
			case *events.Delivered:
				fmt.Printf("Delivered transport: %s\n", event.Envelope.Transport)
			case *events.Failed:
				fmt.Printf("Failed reason: %s\n", event.Reason)
			case *events.Clicked:
				fmt.Printf("Clicked GeoLocation: %s\n", event.GeoLocation.Country)
			case *events.Opened:
				fmt.Printf("Opened GeoLocation: %s\n", event.GeoLocation.Country)
			case *events.Rejected:
				fmt.Printf("Rejected reason: %s\n", event.Reject.Reason)
			case *events.Stored:
				fmt.Printf("Stored URL: %s\n", event.Storage.URL)
			case *events.Unsubscribed:
				fmt.Printf("Unsubscribed client OS: %s\n", event.ClientInfo.ClientOS)
			}
		}
	}
}

Event Polling

The mailgun library has built-in support for polling the events api

package main

import (
    "context"
    "time"

    "github.com/mailgun/mailgun-go/v3"
)

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

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

	// Very short poll interval
	it := mg.PollEvents(&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
		PollInterval: time.Second * 30,
	})

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

    // Poll until our email event arrives
    var page []mailgun.Event
    for it.Poll(ctx, &page) {
        for _, e := range page {
            // Do something with event
        }
    }
}

Email Validations

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/mailgun/mailgun-go/v3"
)

// If your plan does not include email validations but you have an account,
// use your Public Validation api key. If your plan does include email validations,
// use your Private API key. You can find both the Private and
// Public Validation API Keys in your Account Menu, under "Settings":
// (https://app.mailgun.com/app/account/security)
var apiKey string = "your-api-key"

func main() {
    // Create an instance of the Validator
    v := mailgun.NewEmailValidator(apiKey)

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()

    email, err := v.ValidateEmail(ctx, "recipient@example.com", false)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Valid: %t\n", email.IsValid)
}

Webhook Handling

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "time"

    "github.com/mailgun/mailgun-go/v3"
    "github.com/mailgun/mailgun-go/v3/events"
)

func main() {

    // You can find the Private API Key in your Account Menu, under "Settings":
    // (https://app.mailgun.com/app/account/security)
    mg := mailgun.NewMailgun("your-domain.com", "private-api-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)
			w.WriteHeader(http.StatusNotAcceptable)
			return
		}

		verified, err := mg.VerifyWebhookSignature(payload.Signature)
		if err != nil {
			fmt.Printf("verify error: %s\n", err)
			w.WriteHeader(http.StatusNotAcceptable)
			return
		}

		if !verified {
			w.WriteHeader(http.StatusNotAcceptable)
			fmt.Printf("failed verification %+v\n", payload.Signature)
			return
		}

		fmt.Printf("Verified Signature\n")

		// Parse the event provided by the webhook payload
		e, err := mailgun.ParseEvent(payload.EventData)
		if err != nil {
			fmt.Printf("parse event error: %s\n", err)
			return
		}

		switch event := e.(type) {
		case *events.Accepted:
			fmt.Printf("Accepted: auth: %t\n", event.Flags.IsAuthenticated)
		case *events.Delivered:
			fmt.Printf("Delivered transport: %s\n", event.Envelope.Transport)
		}
	})

	fmt.Println("Serve on :9090...")
	if err := http.ListenAndServe(":9090", nil); err != nil {
		fmt.Printf("serve error: %s\n", err)
		os.Exit(1)
	}
}

The official mailgun documentation includes examples using this library. Go here and click on the "Go" button at the top of the page.

Installation

If you are using golang modules make sure you include the /v3 at the end of your import paths

$ go get github.com/mailgun/mailgun-go/v3

If you are not using golang modules, you can drop the /v3 at the end of the import path. As long as you are using the latest 1.10 or 1.11 golang release, import paths that end in /v3 in your code should work fine even if you do not have golang modules enabled for your project.

$ go get github.com/mailgun/mailgun-go

Testing

WARNING - running the tests will cost you money!

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
  • MG_API_KEY is the Private API key - you can get this value from the Mailgun security page
  • MG_EMAIL_TO is the email address used in various sending tests.

and finally

  • MG_SPEND_MONEY if this value is set the part of the test that use the API to actually send email will be run - be aware this will count on your quota and this will cost you money.

The code is released under a 3-clause BSD license. See the LICENSE file for more information.

You can’t perform that action at this time.