はじめてのGo言語 - 問い合わせ機能編 - 　

はじめてのGo言語シリーズ第3回目です。
1,2回目はこちらです↓↓
1回目：[はじめてのGo言語 - インストール〜nginx導入まで -](http://qiita.com/maruo327/items/59c9c1252739d47d9dd4)
2回目：[はじめてのGo言語 - revel導入編 - ](http://qiita.com/maruo327/items/3b1322b59f2e23cde57f)

3回目の今回は、簡易的な「問い合わせ機能」の実装を行います。

# POSTを行うためテンプレートを修正
app/views/App/Index.htmlを修正します。

```html:Index.html
<!-- 一部抜粋 -->
<form method="post" action="/contact/send" name="cform" id="cform">
  <input name="name" id="name" type="text" class="col-xs-12 col-sm-12 col-md-12 col-lg-12" placeholder="お名前" >
  <input name="email" id="email" type="email" class=" col-xs-12 col-sm-12 col-md-12 col-lg-12 noMarr" placeholder="メールアドレス" >
  <textarea name="comments" id="comments" cols="" rows="" class="col-xs-12 col-sm-12 col-md-12 col-lg-12" placeholder="お問い合わせ内容をご記入下さい。"></textarea>
  <input type="submit" id="submit" name="send" class="submitBnt" value="送信する">
  <div id="simple-msg">※返信までに数日お時間を頂く場合がございます。予めご了承下さい。</div>
</form>
```
# ajaxで通信を行うため、jsを作成します。

```js:contact.js
(function($) { 
	"use strict";

jQuery(document).ready(function(){
	$('#cform').submit(function(){

		var action = $(this).attr('action');

		$("#message").slideUp(750,function() {
		$('#message').hide();

 		$('#submit')
			.before('<img src="/public/img/ajax-loader.gif" class="contact-loader" width="30px" />')
			.attr('disabled','disabled');

		$.post(action, {
			name: $('#name').val(),
			email: $('#email').val(),
			comments: $('#comments').val(),
		},
			function(data, status){
				if (status == 'success') {
					data.message = data.message.replace(/\r\n/g, "<br />");
					data.message = data.message.replace(/(\n|\r)/g, "<br />");
					document.getElementById('message').innerHTML = data.message;
					var className = "text-success";
					if (data.status == "500") {
						className = "text-warning";
					} else {
						$('#name').val('');
						$('#email').val('');
						$('#comments').val('');
					}
					$('#message').slideDown('slow').removeClass().addClass(className);
					$('#cform img.contact-loader').fadeOut('slow',function(){$(this).remove()});
					$('#submit').removeAttr('disabled');
				} else {
					document.getElementById('message').innerHTML = '通信エラーが発生しました。しばらくお時間を置いて再度お試し下さい。';
					$('#message').slideDown('slow').removeClass().addClass("text-warning");
					$('#cform img.contact-loader').fadeOut('slow',function(){$(this).remove()});
					$('#submit').removeAttr('disabled');
				}
			}
		);

		});
		return false;
	});
});

}(jQuery));
```

# contact.goを新規作成します。

```go:contact.go
package controllers

import (
	"github.com/revel/revel"
	"net/smtp"
	"log"
)
/**
 * json形式の構造体
 */
type Send struct {
	Status string `json:"status"`
	Message string `json:"message"`
}

type Contact struct  {
	*revel.Controller
}

/**
 * postされたデータを受け取る所
 */
func (c Contact) Send(name string, email string, comments string) revel.Result {
	// Validation
	s := Send{}
	s.Status = "500"
	c.Validation.Required(name).Message("お名前が入力されていません。\n")
	c.Validation.Required(email).Message("メールアドレスが入力されていません。\n")
	c.Validation.Required(comments).Message("問い合わせ内容が入力されていません。\n")

	if c.Validation.HasErrors() {
		for _, v := range c.Validation.Errors {
			s.Message += v.Message
		}

		return c.RenderJson(s)
	}

	// メールで内容を送る
	if sendMail(name, email, comments) == true {
		s.Status = "200"
		s.Message = "問い合わせを行いました。ご返信までしばらくお時間を頂きます。ご了承ください。"
	} else {
		s.Status = "500"
		s.Message = "問い合わせに失敗しました。しばらく経ってから再度お試しください。"
	}
	return c.RenderJson(s)
}
/**
 * メール送信（gmail使ってます）
 */
func sendMail(name string, email string, comments string) bool {

	auth := smtp.PlainAuth(
		"",
		"xxxxxxx@gmail.com", //ユーザ名
		"xxxxxxxxxxx", //パスワード,
		"smtp.gmail.com",
	)
	// メッセージ
	msg := []byte("From: info@example.com\r\n" +
	"To: info@example.com\r\n" +
	"Subject: HPよりお問い合せがあります。\r\n" +
	"\r\n" +
	"名前: " + name +"\r\n" +
	"メールアドレス: " + email + "\r\n" +
	"問い合わせ内容: " + comments + "\r\n")

	err := smtp.SendMail(
		"smtp.gmail.com:587",
		auth,
		"info@example.com", //送信元
		[]string{"info@example.com"}, //宛先
		msg,
	)

	if err != nil {
		log.Fatal(err)
		return false;
	}

	return true;
}
```
解説します。

## メール送信を使うのでパッケージをimportします。
revelにメール送信が簡単にできるものがあると思ったのですが、無いようです。
※こちらを参照ください。
[revelマニュアル Is there an SMTP mailer ?](https://revel.github.io/manual/faq.html)

```go:contact.go
import (
	"github.com/revel/revel"
	"net/smtp"  // ←　これを追加
	"log"
)
```

## jsonレスポンスの構造を定義します。

```go:contact.go
type Send struct {
	Status string `json:"status"`
	Message string `json:"message"`
}
```

`Status string`のみだとjsonのキーが先頭大文字になります。小文字にした場合は`json:"status"`の記述を行う。

## Sendメソッドを作成。

```go:contact.go
func (c Contact) Send(name string, email string, comments string) revel.Result {
}
```
Index.htmlで記載したformのaction先になります。
```
<form action="/contact/send">　→　contact.goのsendメソッドの呼び出しです。
```

POSTされてきたデータは、引数にすることにより取得できます。
（でも、POSTデータが多い場合、全て記述するのか...??）

## Validation
revelにはValidation機能が付いているので簡単にできます。今回はrequiredだけ検証してます。

```Go:contact.go
c.Validation.Required(name).Message("お名前が入力されていません。\n")
c.Validation.Required(email).Message("メールアドレスが入力されていません。\n")
c.Validation.Required(comments).Message("問い合わせ内容が入力されていません。\n")
```
↑エラーメッセージは上記のように独自で設定できます。

```go:contact.go
if c.Validation.HasErrors() {
	for _, v := range c.Validation.Errors {
		s.Message += v.Message
	}
	return c.RenderJson(s)
}
```
エラーをチェックして、エラーメッセージをjsonのMessageに格納して返却してます。

# メール送信

```go:contact.go
func sendMail(name string, email string, comments string) bool {
}
```
このメソッドでメールを送信します。今回smtpを立てるのが面倒だったので（笑）、Gmailにお世話になりました。

以上で、簡易的な問い合わせ機能が出来ました！！
出来上がったサイトです。↓↓
[株式会社トリノ](http://torino-inc.jp)をよろしくお願いしますｗｗ