【GAS】特定の未読のメールの内容をスプレッドシートに書き出すスクリプト

2018/10/10　内容について少し追記と修正

##はじめに
自社のホームページから職人募集のメールが飛んできた際に今まではエクセルにて手動ですべて書き写していたのだが、
いちいち書き写すのが面倒になったためメールからスプレッドシートに全自動で書き込むようにした。

##諸注意とスプレッドシートの初期設定
A列にはメールの改行コードを除いた文字列がすべて格納されるスクリプトになっているため
A列の文字からMidとFindを利用して抽出を行っている。
下記の様な関数を埋め込んでいます。

=if($A2="","",IF(C$1="--","",MID($A2,FIND(C$1,$A2)+LEN(C$1)+1,FIND(D$1,$A2)-FIND(C$1,$A2)-LEN(C$1)-2)))

1行目には各メールについている固定の見出しを記述しているため、MidとFindはそこの見出しを文字列として参照を行っています。
またこちらも後述しますが未読のメールを強制的に既読にしてしまうので不要な場合は下記のコード解説の所をご参照ください。


![afad.PNG](https://qiita-image-store.s3.amazonaws.com/0/237388/a5387633-ba02-6cd6-6311-28ecd4f803f2.png)

こんな感じです。

##コード

```java
function myFunction() {
  var threadcnt = 30;
  var app = SpreadsheetApp.getActiveSheet();
  var sp = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  '検索用タイトル　'
  var mtitle = ※Gmailで検索する文字列　たとえば　subject:(お問い合わせ) など
  '実際にメールを検索するやつ'
  var thread = GmailApp.search(mtitle,0,threadcnt);
  'メールのスレッド取得'
  var messege = GmailApp.getMessagesForThreads(thread);
  var bun = [];
  var link = [];
  var date = [];
  
  for(var i=0;i<messege.length;i++){
    bun[i] = [];
    link[i] = [];
    date[i] = [];
    'メールの本文取得　bunに突っ込んでる。改行コードをreplaceで削除して取り込んでる'
    bun[i].push(messege[i][0].getPlainBody().replace(/(\r\n)+/g,"\r\n"));
    'メールの本文を見れる用のURLを取得してる'
    link[i].push(thread[i].getPermalink());
    'メールの届いた日付、時間を取得してる'
    date[i].push(messege[i][0].getDate());
　　'スプレッドシートに書き出したメールを既読にする。既読にしないと永遠と書き出され続ける。
    thread[i].markRead(); '
  }![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/237388/b8edba8e-f804-33b7-bdf3-bc9d4a6af157.png)

  '今入力されている最終行を取得してる'
  for(var lastrow=2;sp.getRange(lastrow,1).getValue()!=="";lastrow++){ 
  }  
  'メッセージがない時エラーが出るらしいからif文で入らないようにしてる'
  if(bun.length>0){
    app.getRange(lastrow,1,i,1).setValues(bun);  
    app.getRange(lastrow,2,i,1).setValues(date);
    app.getRange(lastrow,15,i,1).setValues(link);
  }
}
```
##コードの解説
ひとまずvarの部分からできるところは解説していきたいと思います。
特にAPI周りの所でしょうか。

###mtitle
titleの部分にはGmailで検索するときの文字を入れてください。
Gmailのここ
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/237388/2d688ba8-041b-0fc8-9e57-f964aa001eff.png)
に検索したときの文字をそのまま入れてください。

###thread
threadにてmtitleで指定したメールを取得します。
ここではGmailApp.searchを利用して特定のメールだけを抽出します。
私の環境では届くメールのタイトルに必ず「職人募集」という文言が入っておりかつ必ず転送されて届くので
'is:unread subject:(職人募集) -{Re: or Fwd:}'
と記述しています。
**※unreadを指定することにより未読のメールを指定しています。これがないとうまく動作しないのでお気を付けください。未読メール以外も取得したいということであれば別の方法をご検討ください・・・。**

https://developers.google.com/apps-script/reference/gmail/gmail-app#search(String)
上記のリファレンスを元に
search(query, start, max)となっているのですが私の見解だと、
（検索バーに入れる検索文字列,メールのどこから取得するのか,最大何件取得するのか）
という意味に捕らえました。※間違っていたらご指摘ください。

###messege
GmailApp.getMessagesForThreadsにてメールの本文を取得する。
※ただLogで見たところ
![wdqw.PNG](https://qiita-image-store.s3.amazonaws.com/0/237388/014ebc5a-62a3-3a1a-b976-3a23aaf8a8d4.png)
とこのようになっておりそのままでは扱えません。
後述するgetPlainBodyにて文字列にしています。

###getPermalink
おまけの機能ですがこちらにてthreadの配列に対して指定してやると
メールだけが開くURLが帰ってきます。スプレッドシートの画面からすぐにメールが見れるようになります。
※全画面表示のメール表示なので印刷とかには便利かも？

###getDate
メールの届いた日付を読んで字のごとく取得しています。こちらはmessegeに対して付けます。

###markRead
threadに対して指定してやると未読のメールを既読に変更することが可能となっています。
**そのためメールの検索条件を未読としたのがここに生きてきます。一度スプレッドシートに取り込んだら既読にすることにより再度同じメールを取得しないように設定します。**

あとはコメント通りの動作なのでよろしくお願いいたします。


##Gmailの制限について
コードの実装が終わったらあとはプロジェクトトリガーをメールの件数と相談しながら設定を行えば完了です。
ただ更新頻度を上げ過ぎるとGmailの規制に引っかかったりするので注意。
threadcnt = 30; となっているが未読の検索条件に伴ったメールを30件しか読み込まないよ！という宣言なので
反響が半端ない方は規制とうまーく相談しながら設定してください。



##参考文献
https://tonari-it.com/gas-add-contact-mail/
https://tonari-it.com/gas-gmail-search-limit/
こちらのサイト様を元に勉強させていただきました。
同一サイトですが上が基本構文、下がGmailの制限についてです。

##追記情報
2018/10/10　コード解説がおおざっぱすぎたのをわかる範囲で追記
一部記述等に誤りがありましたらご指摘いただけますと幸いです。