🤖

GoでMailgunを使ってみた

2022/02/16に公開

はじめに

sweeep株式会社エンジニアの関田です。

弊社では請求書などを簡単に保管できるサービス、sweeep-Boxを開発しています。
sweeep Box - 電子帳簿保存法対応のビジネス書類保管サービス

sweeep-Box開発の際に、元々Pythonで書いていたメール機能をGoで書き直すことになり、
せっかくなので使ったライブラリを紹介しようと思います。

説明しないこと

以下のことについては他にたくさんの記事があるので今回は説明を省かせていただきます。

  • Mailgunアカウントの作成方法
  • Goの基本文法

準備

以下の環境があることが前提になります。

  • Go環境
  • Mailgunのドメイン
  • Mailgunのプライベートキー

実装

以下のライブラリを使って実装しました。
https://github.com/mailgun/mailgun-go

まずはmailgunのインスタンス化を行う必要があります。

mg := mailgun.NewMailgun(yourDomain, privateAPIKey)

以降ではmailgunインスタンスは取得済みとします。

メール送信

こちらはreadmeにサンプルがありますので、そのまま使わせていただきます。

func main() {
	sender := "sender@example.com"
	subject := "HTML email!"
	recipient := "recipient@example.com"
	body := "Hello from Mailgun Go!"

	message := mg.NewMessage(sender, subject, body, recipient)

	// コンテキストの取得
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()
	
	// メール送信
	mg.Send(ctx, message)
}

本文にHTMLを使いたい場合は以下のようにSetHtml()を呼び出す必要があります。

	message := mg.NewMessage(sender, subject, "", recipient)
	message.SetHtml(body)

イベント取得

イベントの取得はListEvents()を使います。


func main() {
	// イベント取得
	it := mg.ListEvents(&mailgun.ListEventOptions{Limit: 100})

ListEventsに渡すパラメータはGithubにコメントがあります。

mailgun-go/events.go L12-L29

type ListEventOptions struct {
	// Limits the results to a specific start and end time
	Begin, End time.Time
	// ForceAscending and ForceDescending are used to force Mailgun to use a given
	// traversal order of the events. If both ForceAscending and ForceDescending are
	// true, an error will result. If none, the default will be inferred from the Begin
	// and End parameters.
	ForceAscending, ForceDescending bool
	// Compact, if true, compacts the returned JSON to minimize transmission bandwidth.
	Compact bool
	// Limit caps the number of results returned.  If left unspecified, MailGun assumes 100.
	Limit int
	// Filter allows the caller to provide more specialized filters on the query.
	// Consult the Mailgun documentation for more details.
	Filter       map[string]string
	PollInterval time.Duration
}

パラメータは以下のようになっています。

フィールド 説明
Begin, End time.Time 開始時刻と終了時刻。
ForceAscending, ForceDescending bool 探索順序。両方がtrueの場合はエラー。デフォルトはBeginとEndから推測される。
Compact bool 結果のサイズを小さくするかどうか。
Limit int 取得結果数の上限。デフォルトは100。
Filter map[string]string 詳細なフィルタ。ドキュメント

例えばstoredイベントでフィルタして取得したい場合は以下のように修正します。

	it := mg.ListEvents(&mailgun.ListEventOptions{
		Limit: 100
		Filter: map[string]string{
			"event": "stored",
		},
	})

ListEventsで取得したStoredEventは以下のようになっています。

mailgun-go/events/events.go L122-L132

type Stored struct {
	Generic

	Message Message `json:"message"`
	Storage Storage `json:"storage"`
	Flags   Flags   `json:"flags"`

	Tags          []string    `json:"tags"`
	Campaigns     []Campaign  `json:"campaigns"`
	UserVariables interface{} `json:"user-variables"`
}

mailgun-go/events/objects.go L25-L30

type Message struct {
	Headers     MessageHeaders `json:"headers"`
	Attachments []Attachment   `json:"attachments"`
	Recipients  []string       `json:"recipients"`
	Size        int            `json:"size"`
}

mailgun-go/events/objects.go L41-L44

type Storage struct {
	Key string `json:"key"`
	URL string `json:"url"`
}

メール詳細取得

上記でmailgunのログの取得はできますが、まだメール本体の情報が足りません。

Mailgunにはメール情報をStored.Storage.URLに保存してあるので、
そちらを使って取得することができます。
メール詳細情報を取得するにはGetStoredMessage()を使います。


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

	res, err := mg.GetStoredMessage(ctx, url)

GetStoredMessageの応答値は以下のような形になっています。

mailgun-go/messages.go L74-L93

type StoredMessage struct {
	Recipients        string             `json:"recipients"`
	Sender            string             `json:"sender"`
	From              string             `json:"from"`
	Subject           string             `json:"subject"`
	BodyPlain         string             `json:"body-plain"`
	StrippedText      string             `json:"stripped-text"`
	StrippedSignature string             `json:"stripped-signature"`
	BodyHtml          string             `json:"body-html"`
	StrippedHtml      string             `json:"stripped-html"`
	Attachments       []StoredAttachment `json:"attachments"`
	MessageUrl        string             `json:"message-url"`
	ContentIDMap      map[string]struct {
		Url         string `json:"url"`
		ContentType string `json:"content-type"`
		Name        string `json:"name"`
		Size        int64  `json:"size"`
	} `json:"content-id-map"`
	MessageHeaders [][]string `json:"message-headers"`
}

添付ファイルデータ取得

上記でメール本体の情報は取得できました。
最後の添付ファイルデータの取得を行います。

StoredMessageのAttachmentsは以下のようになっていて、
その中のUrlから添付ファイル情報が取得できます。

mailgun-go/messages.go L96-L101

type StoredAttachment struct {
	Size        int    `json:"size"`
	Url         string `json:"url"`
	Name        string `json:"name"`
	ContentType string `json:"content-type"`
}

添付ファイルデータ取得にはGetStoredAttachment()を使います。


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

	byteData, err := mg.GetStoredAttachment(ctx, url)

おわりに

こちらのライブラリのおかげでメール機能を楽に実装することができました。
一部Readmeに書いていないことは実際のソースなどを見てメソッドを見つけたりしたので、
内部のコードを見る機会にもなって勉強になりました。

sweeepでは一緒に働くエンジニアを募集しています!
https://corp.sweeep.ai/recruit

GitHubで編集を提案

Discussion