[firebase] Cloud Functionsを利用したお問い合わせ機能の実装 [react.js]

#Cloud Functionsを利用したお問い合わせ機能の実装[react.js]

今回、react.js*firebaseなプロダクトを開発している際に、
お問い合わせフォームの実装が必要だったのでこちらに実装の手順を置いておきます。
一般的なgmailをメールサーバーとしてメールの送信機能を実現させます。

また実装にあたり、[こちらの記事](https://qiita.com/ryo2132/items/7cdd6c86dd418095f74a)を参考にさせていただきました。なんなら全てこちらに記載されております。


## 1.firebase projectの設定

[こちらの記事](https://qiita.com/yoshi0518/items/25af102845ba05545f98)をご確認ください。


## 2.functionの設定
```javascript:functions/index.js
const functions = require("firebase-functions");
const nodemailer = require("nodemailer");
const gmailEmail = functions.config().gmail.email;
const gmailPassword = functions.config().gmail.password;
const adminEmail = functions.config().admin.email;

// 送信に使用するメールサーバーの設定
const mailTransport = nodemailer.createTransport({
  service: "gmail",
  auth: {
    user: gmailEmail,
    pass: gmailPassword
  }
});

// 管理者用のメールテンプレート
const adminContents = data => {
  return `以下内容でホームページよりお問い合わせを受けました。
お名前：
${data.name}
メールアドレス：
${data.email}
内容：
${data.content}
`;
};

exports.sendMail = functions.https.onCall((data, context) => {
  // メール設定
  let adminMail = {
    from: gmailEmail,
    to: adminEmail,
    subject: "ホームページお問い合わせ",
    text: adminContents(data)
  };

  // 管理者へのメール送信
  mailTransport.sendMail(adminMail, (err, info) => {
    if (err) {
      return console.error(`send failed. ${err}`);
    }
    return console.log("send success.");
  });
});
```


## 3. フロント(react.js)の設定

reactプロジェクト内で、firebase(Cloud Functions)を利用できるようにするために、下記の記述を忘れないようにしましょう。

```react:firebase/firebase.js
import firebase from 'firebase';
import 'firebase/auth';

const config = {
    apiKey: "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊",
    authDomain: "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊",
    databaseURL: "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊",
    projectId: "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊",
    storageBucket: "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊",
    messagingSenderId: "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊"
}

firebase.initializeApp(config);

```

下記が、お問い合わせフォームになります。

```react:お問い合わせフォーム

import React, { Component } from 'react';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button'

const firebase = require("firebase");
require("firebase/functions");


class ContactForm extends Component {
  constructor(){
    super()
    this.onSubmit = this.onSubmit.bind(this)
  }

  onSubmit(e){
    e.preventDefault()
    let data = {}
    data.name = e.target.name.value
    data.email = e.target.email.value
    data.content = e.target.content.value
    let sendMail = firebase.functions().httpsCallable('sendMail');
    sendMail(data)
    e.target.name.value = ""
    e.target.email.value = ""
    e.target.content.value = ""
    e.target.value = ""
  }

  render() {
    const textFieldStyle = {
      display: "flex",
      width: "300px",
    }

    const contactForm = {
      display: "flex",
      flexDirection: "column", 
      alignItems: "center",
      marginTop: "100px",
    }


    return (
      <React.Fragment>
        <div style={contactForm}>
          <h2>お問い合わせ</h2>
          <form onSubmit={this.onSubmit}>
            <TextField name="name" label="お名前" type="text" required style={textFieldStyle}  />
            <TextField name="email" label="メールアドレス" type="mail" required style={textFieldStyle}   />
            <TextField
              required
              name="content"
              label="お問い合わせ内容"
              multiline
              rows="8"
              margin="normal"
              variant="outlined"
              style={textFieldStyle} 
            />
            <Button variant="contained" color="primary" type="submit" style={textFieldStyle} >
              送信
            </Button>
          </form>
        </div>
      </React.Fragment>
    )
  }   
}

export default ContactForm

```


material-uiを追加していない方は、こちら

```
$ npm install @material-ui
```



<img width="352" alt="スクリーンショット 2019-06-04 21.30.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270696/86d0afed-7753-05ef-2e7f-66dd68bffbe1.png">


以上になります。