前書き
特に意味はないけれどメールフォームを設置してみたかったので、
GoogleAppEngineでAPI作って、GihubPagesのポートフォリオに設置してみました
準備
まず、reCAPTCHAに登録する必要があります
reCAPTCAの画面を開いて
Labelに適当な名前を入れて、Domainsに一行ごとにreCAPTCHAを利用するドメインを入れます(エイリアス用のドメインなど)
そしてRegister
をクリック
GithubPages側の記述
ふつうに<form>
を書いてjsを貼り付けるだけです
さっき登録したあとに表示されたページの
Adding reCAPTCHA to your site
の中のStep 1: client-side integration
の<script src='https://www.google.com/recaptcha/api.js'></script>
をheadタグ内に、<div class="g-recaptcha" data-sitekey="~~~"></div>
を
そして、POSTでGoogleAppEngine側をたたくように
<form method="POST" action="~~GoogleAppEngineにつくるAPIのURL~~">
と書きますform内のそれぞれの入力箇所に
name
属性がついていることを確認します(ないとAPI側で受け取れません)
GoogleAppEngine側の記述
まず、ルーティングを適当に設定して、POSTを受け取り、その中のデータを取り出します
そうしたら、https://www.google.com/recaptcha/api/siteverify
にsecret さっきの登録したあとのページのStep2の中のsecret
,response POSTで受け取ったg-recaptcha-response
をつけてPOSTします
そうすると、有効かどうかの結果が返ってきます(ex. {"success": true}
,{"success": false, "error-codes": [~]}
)
(GETでもできるみたいです ex.https://www.google.com/recaptcha/api/siteverify?secret=~&g-recaptcha-response=~
)
これで有効かどうか受け取れたので、その結果を返すならページにパラメータつけてリダイレクトなどしてGithubPages側でページを書き換えるなどできます
ソース
自分はreCAPTCHAのあとで自分にメールを送りつけています(メールフォームなので…)
GoogleAppEngine側はGo、GitHubPages側はhaml(MaterialDesignLite使用)で書いています
GoogleAppEngine側
ルーティングの部分などは省略します
Goですが、おそらくほかの言語でもおんなじ感じでかけると思います
package s4naxyz
import(
"fmt"
"net/http"
"io/ioutil"
"encoding/json"
"google.golang.org/appengine"
"google.golang.org/appengine/log"
"google.golang.org/appengine/urlfetch"
"google.golang.org/appengine/mail"
)
const secretkey = "~~~~secret~~~~"
type googleResponse struct {
Success bool `json:success`
ErrorCodes []string `json:error-codes`
}
func mailSendHandler(w http.ResponseWriter, r *http.Request) {
ctx := appengine.NewContext(r)
r.ParseForm()
if r.Form.Get("g-recaptcha-response") == "" {
log.Errorf(ctx, "Couldnt send email<recaptcha response error>")
fmt.Fprint(w, "{error: true, message: \"recaptcha response error\"}")
return
}
client := urlfetch.Client(ctx)
res, err := client.Get("https://www.google.com/recaptcha/api/siteverify?secret="+secretkey+"&response="+r.Form.Get("g-recaptcha-response"))
if err != nil {
log.Errorf(ctx, "Couldnt send email<http getting error>: %v", err)
fmt.Fprint(w, "{error: true, message: \"http getting error\"}")
return
}
defer res.Body.Close()
resByte, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Errorf(ctx, "Couldnt send email<body transforming error>: %v", err)
fmt.Fprint(w, "{error: true, message: \"body transforming error\"}")
return
}
parsed := googleResponse{}
err = json.Unmarshal(resByte, &parsed)
if err != nil {
log.Errorf(ctx, "Couldnt send email<json parsing error>: %v", err)
fmt.Fprint(w, "{error: true, message: \"json parsing error\"}")
return
}
if !parsed.Success {
log.Errorf(ctx, "Couldnt send email<recaptcha authorize error>")
fmt.Fprint(w, "{error: true, message: \"recaptcha authorize error\"}")
return
}
msg := &mail.Message{
Sender: "api.4na.xyz <~~~GMailのアドレス~~~>",
To: []string{"~~~普段使いのアドレス~~~"},
Subject: r.Form.Get("title"),
Body: "From: "+r.Form.Get("name")+" ("+r.Form.Get("email")+")\n----------\nMessage:\n"+r.Form.Get("message"),
}
if err := mail.Send(ctx, msg); err != nil {
log.Errorf(ctx, "Couldnt send email<mail sending error>: %v", err)
fmt.Fprint(w, "{error: true, message: \"mail sending error\"}}")
return
}
w.Header().Set("Content-Type", "text/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
//fmt.Fprint(w, "{error: false}")
http.Redirect(w, r, "https://s.4na.xyz/contact/", 301)
}
fmt.Fprintしてリダイレクトみたいなことになってますが、
まだ作り途中なので…
GithubPages側
関連個所のみ抜粋で
#form.mdl-cell.mdl-cell--8-col
.mdl-card.mdl-shadow--3dp
.mdl-card__title
%h2.h4.mdl-card__title-text Contact
.mdl-card__supporting-text
%form#form-main{method: "POST", action: "https://api.4na.xyz/mail/send"}
.mdl-textfield.mdl-js-textfield.mdl-textfield--floating-label
%input.mdl-textfield__input#name{name: "name", type: "text", required: true}
%label.mdl-textfield__label{for: "name"} Name
%br
.mdl-textfield.mdl-js-textfield.mdl-textfield--floating-label
%input.mdl-textfield__input#email{name: "email", type: "email", required: true}
%label.mdl-textfield__label{for: "email"} Email Address
%br
.mdl-textfield.mdl-js-textfield.mdl-textfield--floating-label
%input.mdl-textfield__input#title{name: "title", type: "text", required: true}
%label.mdl-textfield__label{for: "title"} Title
%br
.mdl-textfield.mdl-js-textfield.mdl-textfield--floating-label
%textarea.mdl-textfield__input#message{name: "message", type: "text", rows: "5", required: true}
%label.mdl-textfield__label{for: "message"} Message
%br
.g-recaptcha{"data-sitekey": "~~~sitekey~~~"}
%input#submit.mdl-button.mdl-js-button.mdl-button--raised.mdl-button--colored.mdl-js-ripple-effect{type: "submit"}
%script{type: "text/javascript", src: "https://www.google.com/recaptcha/api.js?hl=ja", defer: true, async: true}