2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Go言語・SendGrid・REST APIでお問い合わせメール送信API

Last updated at Posted at 2022-02-16

概要

Go言語を使って、Jsonファイル形式で送られてきたデータをメールで送信する。
モバイル開発において、お問い合わせフォームの内容をWebを使って送信する必要があったので、モバイル側から送られてきたデータをWebを通してメール送信をするプログラムを作成した。
OSはWindows

参照した記事

事前準備

まずメール送信を肩代わりしてくれるサービスSendGridを登録する必要がある。
申請をして、早くて数時間、遅くても1営業日で審査は終わる。SendGridは月12,000通までのメール送信なら無料で使える。

審査が通ればログインしてAPIキーを所得。
Settings → API Keys → Create API Key(青いボタン)を押す。Permission はとりあえず Full Access で大丈夫。
API Key はどこかに保存しておく。API Key は生成時以外は確認できないので、忘れたら Key を作り直すことになる。(キーを失ったら作り直せばいい)

準備するファイル

ファイル構造
go_sendmail/
  ├ handler/
  │    └PostEmail.go
  ├ .env
  └ main.go

以下コード内容

PostEmail.go
package handler

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/sendgrid/sendgrid-go"
	"github.com/sendgrid/sendgrid-go/helpers/mail"
	"github.com/joho/godotenv"

	"github.com/ant0ine/go-json-rest/rest"
	"net/http"
	"sync"
)

//メールの構造体
type Mail struct {
	Name    string
	Subject string
	Text    string
	Email   string
}

var store = map[string]*Mail{}

var lock = sync.RWMutex{}

//送信する関数
func PostMail(w rest.ResponseWriter, r *rest.Request) {
	send := Mail{}
	err := r.DecodeJsonPayload(&send)//sendにpost値を入れる
	if err != nil {
			rest.Error(w, err.Error(), http.StatusInternalServerError)
			return
	}

	if send.Email == "" {
			rest.Error(w, "mail required", 400)
			return
	}
	
	lock.Lock()
	store[send.Name] = &send
	lock.Unlock()

	err_read := godotenv.Load()
	if err_read != nil {
		log.Fatalf("error: %v", err_read)
	}

	// .envから環境変数読み込み
	API_KEY := os.Getenv("API_KEY")
	TOS := strings.Split(os.Getenv("TOS"), ",")
	fr := send.Email//postした値に含めたメールアドレス(送信者のメアド)

	// メッセージの構築
	message := mail.NewV3Mail()
	// 送信元を設定
	from := mail.NewEmail("", fr)
	message.SetFrom(from)

	// 宛先と対応するSubstitutionタグを指定(宛先は複数指定可能)
	p := mail.NewPersonalization()
	to := mail.NewEmail("", TOS[0])
	p.AddTos(to)

	//残りのpostされた値を変数に格納
	name := send.Name
	subject := send.Subject
	text := send.Text

	p.SetSubstitution("%name%", name)
	p.SetSubstitution("%m_subject%", subject)
	p.SetSubstitution("%m_text%", text)
	message.AddPersonalizations(p)

	// 2つ目の宛先と、対応するSubstitutionタグを指定
	// p2 := mail.NewPersonalization()
	// to2 := mail.NewEmail("", TOS[1])
	// p2.AddTos(to2)
	// p2.SetSubstitution("%name%", name)
	// p2.SetSubstitution("%m_subject%", subject)
	// p2.SetSubstitution("%m_text%", text)
	// message.AddPersonalizations(p2)

	// 3つ目の宛先と、対応するSubstitutionタグを指定
	// p3 := mail.NewPersonalization()
	// to3 := mail.NewEmail("", TOS[2])
	// p3.AddTos(to3)
	// p3.SetSubstitution("%name%", name)
	// p3.SetSubstitution("%m_subject%", subject)
	// p3.SetSubstitution("%m_text%", text)
	// message.AddPersonalizations(p3)

	// 件名を設定
	message.Subject = "%m_subject%"
	// テキストパートを設定
	c := mail.NewContent("text/plain", "%m_text%\r\n")
	message.AddContent(c)
	// HTMLパートを設定
	//c = mail.NewContent("text/html", "<strong> %name% さんは何をしていますか?</strong><br> 文章ー--。")
	// message.AddContent(c)

	// カテゴリ情報を付加
	message.AddCategories("category1")
	// カスタムヘッダを指定
	message.SetHeader("X-Sent-Using", "SendGrid-API")
	// 画像ファイルを添付
	// a := mail.NewAttachment()
	// file, _ := os.OpenFile("./gif.gif", os.O_RDONLY, 0600)
	// defer file.Close()
	// data, _ := ioutil.ReadAll(file)
	// data_enc := base64.StdEncoding.EncodeToString(data)
	// a.SetContent(data_enc)
	// a.SetType("image/gif")
	// a.SetFilename("owl.gif")
	// a.SetDisposition("attachment")
	// message.AddAttachment(a)

	// メール送信を行い、レスポンスを表示
	client := sendgrid.NewSendClient(API_KEY)
	response, err := client.Send(message)
	if err != nil {
		log.Println(err)
	} else {
		fmt.Println(response.StatusCode)
		fmt.Println(response.Body)
		fmt.Println(response.Headers)
	}
	w.WriteJson(&send)
}
main.go
package main

import (
	"go_sendmail/handler"
	"log"
	"net/http"

	"github.com/ant0ine/go-json-rest/rest"
)

func main() {
	//REST APIでpost処理を実現
	api := rest.NewApi()
	api.Use(rest.DefaultDevStack...)
	router, err := rest.MakeRouter(
		rest.Post("/post", handler.PostEmail),
	)
	if err != nil {
		log.Fatal(err)
	}
	api.SetApp(router)
	log.Fatal(http.ListenAndServe(":8080", api.MakeHandler()))
}
.env
API_KEY=your_api_key #←ここにSendGridのAPIキーを入力
TOS=you@youremail.com,friend1@friendemail.com,friend2@friendemail.com
# TOSにはメールが届いてほしいメールアドレスを入れる。「,」で区切ることで複数指定できる。
# とりあえず「,」は使わずに、メールアドレスは一つでいい。

上記の.envファイルの1行目に、先ほど保存したSendGridのAPIキーを入れておく。
まだgoファイルのimportの部分でエラーが表示されている状態かと。

実行

まずGo言語お決まりのgo.modファイルを生成するために、カレントディレクトリがgo_sendmailの状態でコマンド

$ go mod init go_sendmail

を実行。
次にパッケージのインストール。以下のコマンドを1行ずつ実行。

$ go get "github.com/sendgrid/sendgrid-go"
$ go get "github.com/sendgrid/sendgrid-go/helpers/mail"
$ go get "github.com/joho/godotenv"
$ go get "github.com/ant0ine/go-json-rest/rest"

これができたら

$ go run main.go

で実行。もしlocalhostがアクセスの許可を聞いてきたら許可する。
そしてコマンドプロンプトを新たに開いて、カレントディレクトリはどこでもいいので

$ curl -i -H "Content-Type: application/json" -d "{\"Name\":\"taro\",\"Subject\":\"test\",\"Text\":\"hello\",\"Email\":\"example@email.com\"}" http://localhost:8080/post

を実行。
これはcurlコマンドでデータを、mail.goで立ち上げたサーバーにPostしている。最終的にはモバイル側がこの処理をすることを想定しているが、今はテスト段階なので手動でコマンドを使っているだけ。
example@email.comの部分はメール送信者(アプリユーザ)のメールアドレスだからなんでもいい。
「"(ダブルクォーテーション)」の前にいちいち「\(環境によっては¥)」を入れているのは、WindowsのコマンドプロンプトにおいてJson形式の中身の「"」を念のためエスケープしているため。
Windows以外を使ったりしていれば

$ curl -i -H "Content-Type: application/json" -d "{"Name":"taro","Subject":"test","Text":"hello","Email":"example@email.com"}" http://localhost:8080/post

で実行すればいいかも。
とにかくこれで、.envファイルのTOSの値に指定したメールアドレスにメールが届いていれば成功。
ちなみにコマンドプロンプトの実行後の画面は以下の通り。
2022-02-16.png

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?