• Stars
    star
    698
  • Rank 64,841 (Top 2 %)
  • Language
    Go
  • License
    BSD 3-Clause "New...
  • Created over 10 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Go library for sending mail with the Mailgun API.

Mailgun with Go

GoDoc Build Status

Go library for interacting with the Mailgun API.

Usage

package main

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

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

// 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)
	
	//When you have an EU-domain, you must specify the endpoint:
	//mg.SetAPIBase("https://api.eu.mailgun.net/v3")

	sender := "[email protected]"
	subject := "Fancy subject!"
	body := "Hello from Mailgun Go!"
	recipient := "[email protected]"

	// 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/v4"
	"github.com/mailgun/mailgun-go/v4/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"
	"log"
	"time"

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

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 {
			log.Printf("Got an event: %q (%q)", e.GetName(), e.GetID())
			// Do something with event
		}
	}
}

Email Validations

package main

import (
	"context"
	"fmt"
	"time"

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

// 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() {
	// To use the /v4 version of validations define MG_URL in the environment
	// as `https://api.mailgun.net/v4` or set `v.SetAPIBase("https://api.mailgun.net/v4")`

	// 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, "[email protected]", false)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Valid: %t\n", email.IsValid)
}

Webhook Handling

package main

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

	"github.com/mailgun/mailgun-go/v4"
	"github.com/mailgun/mailgun-go/v4/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)
	}
}

Sending HTML templates

package main

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

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

// 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 := "[email protected]"
	subject := "HTML email!"
	recipient := "[email protected]"

	message := mg.NewMessage(sender, subject, "", recipient)
	body := `
<html>
<body>
	<h1>Sending HTML emails with Mailgun</h1>
	<p style="color:blue; font-size:30px;">Hello world</p>
	<p style="font-size:30px;">More examples can be found <a href="https://documentation.mailgun.com/en/latest/api-sending.html#examples">here</a></p>
</body>
</html>
`

	message.SetHtml(body)

	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)
}

Using Templates

Templates enable you to create message templates on your Mailgun account and then populate the data variables at send-time. This allows you to have your layout and design managed on the server and handle the data on the client. The template variables are added as a JSON stringified X-Mailgun-Variables header. For example, if you have a template to send a password reset link, you could do the following:

package main

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

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

// 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 := "[email protected]"
	subject := "Fancy subject!"
	body := ""
	recipient := "[email protected]"

	// The message object allows you to add attachments and Bcc recipients
	message := mg.NewMessage(sender, subject, body, recipient)
	message.SetTemplate("passwordReset")
	err := message.AddTemplateVariable("passwordResetLink", "some link to your site unique to your user")
	if err != nil {
		log.Fatal(err)
	}

	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)
}

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

EU Region

European customers will need to change the default API Base to access your domains

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

Installation

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

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

If you are not using golang modules, you can drop the /v4 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 /v4 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

NOTE for go dep users

Using version 3 of the mailgun-go library with go dep currently results in the following error

"github.com/mailgun/mailgun-go/v4/events", which contains malformed code: no package exists at ...

This is a known bug in go dep. You can follow the PR to fix this bug here Until this bug is fixed, the best way to use version 3 of the mailgun-go library is to use the golang community supported golang modules.

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.

More Repositories

1

transactional-email-templates

Responsive transactional HTML email templates
HTML
6,820
star
2

godebug

DEPRECATED! https://github.com/derekparker/delve
Go
2,507
star
3

flanker

Python email address and Mime parsing library
Python
1,633
star
4

talon

Python
1,235
star
5

mailgun-php

Mailgun's Official SDK for PHP
PHP
1,091
star
6

gubernator

High Performance Rate Limiting MicroService and Library
Go
944
star
7

mailgun-js-boland

A simple Node.js helper module for Mailgun API.
JavaScript
896
star
8

kafka-pixy

gRPC/REST proxy for Kafka
Go
752
star
9

mailgun.js

Javascript SDK for Mailgun
TypeScript
519
star
10

mailgun-ruby

Mailgun's Official Ruby Library
Ruby
468
star
11

groupcache

Clone of golang/groupcache with TTL and Item Removal support
Go
424
star
12

expiringdict

Dictionary with auto-expiring values for caching purposes.
Python
331
star
13

holster

A place to keep useful golang functions and small libraries
Go
277
star
14

validator-demo

Mailgun email address jquery validation plugin http://mailgun.github.io/validator-demo/
JavaScript
259
star
15

node-prelaunch

A Mailgun powered landing page to capture early sign ups
JavaScript
230
star
16

dnsq

DNS Query Tool
Python
107
star
17

documentation

Mailgun Documentation
CSS
79
star
18

scroll

Scroll is a lightweight library for building Go HTTP services at Mailgun.
Go
61
star
19

kafka-http

Kafka http endpoint
Scala
51
star
20

forge

email dataset for email signature parsing
51
star
21

wordpress-plugin

Mailgun's Wordpress Plugin
PHP
49
star
22

lemma

Mailgun Cryptographic Tools
Go
39
star
23

multibuf

Bytes buffer that implements seeking and partially persisting to disk
Go
37
star
24

ttlmap

In memory dictionary with TTLs
Go
22
star
25

frontend-best-practices

Guides for React and Javascript coding style and best practices
21
star
26

pong

Generates http servers that respond in predefined manner
Go
20
star
27

proxyproto

High performance implementation of V1 and V2 Proxy Protocol
Go
19
star
28

log

Go logging library used at Mailgun.
Go
19
star
29

mailgun-java

Java SDK for integrating with Mailgun
Java
16
star
30

mailgun-meteor-demo

Simple meteor-based emailer with geolocation and UA tracking
JavaScript
16
star
31

timetools

Go library with various time utilities used at Mailgun.
Go
11
star
32

pelican-protocol

In ancient Egypt the pelican was believed to possess the ability to prophesy safe passage in the underworld. Pelicans are ferocious eaters of fish.
Go
11
star
33

metrics

Go library for emitting metrics to StatsD.
Go
11
star
34

roman

Obtain, cache, and automatically reload TLS certificates from an ACME server
Go
10
star
35

sandra

Go library providing some convenience wrappers around gocql.
Go
10
star
36

iptools

Go library providing utilities for working with hosts' IP addresses.
Go
9
star
37

cfg

Go library for working with app's configuration files used at Mailgun.
Go
9
star
38

logrus-hooks

Go
8
star
39

minheap

Slightly more user-friendly heap on top of containers/heap
Go
8
star
40

pebblezgo

go example of the pebblez transport: protocol buffers over zeromq
Go
7
star
41

glogutils

Utils for working with google logging library
Go
7
star
42

pylemma

Mailgun Cryptographic Tools
Python
5
star
43

media

Logos and brand guidelines
4
star
44

callqueue

Serialized call queues
Go
4
star
45

sneakercopy

A tool for creating encrypted tar archives for transferring sensitive data.
Rust
4
star
46

scripts

Example scripts that show how to interact with the Mailgun API
Python
1
star
47

etcd3-slim

Thin wrapper around Etcd3 gRPC stubs
Python
1
star