概要
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
以下コード内容
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)
}
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()))
}
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の値に指定したメールアドレスにメールが届いていれば成功。
ちなみにコマンドプロンプトの実行後の画面は以下の通り。