お天気情報を毎日メールで送りたい

宮崎県も梅雨入りして6月らしい感じになってきました。毎日お天気情報をみては傘を持って行こうかどうしようかと考えるので、スマフォにお天気アプリを入れようかと思ったのですが、そのためだけにインストールするの面倒。お気軽に宮崎県の天気情報を見たいなと思い、メールで受け取ろうという結論になりました。GASを駆使してお天気情報のデータを加工してメールで受け取るプログラムを書いてみました。

JSON情報の取得とパース

まずお天気情報ですが、livedoor天気情報のWeather Hacksを使用することにしました。お天気マークの画像も使用できるし、JSON形式で取得できるのでこのデータを元に制作していきます。

JSON情報の取得は、以前に書いた記事「スプレッドシートでXML情報を取得して表形式に出力する方法(前編)」と同様に、UrlFetchAppクラスを使用します。JSON情報の取得してパースした値を返すように関数化してみます。

/**
 * Weather Hacks JSON Parse
 * http://weather.livedoor.com/weather_hacks/webservice
 *
 * return Object
 */
function parseJson() {
  var feedURL  = "http://weather.livedoor.com/forecast/webservice/json/v1?city=450010";
  var response = UrlFetchApp.fetch(feedURL);
  return JSON.parse(response.getContentText());
}
  1. 08行目 – feedURL変数にJSON APIのパスをセット(city=450010は宮崎県宮崎市の値を取得)
  2. 09行目 – Class UrlFetchAppparseメソッドでフィードを取得
  3. 10行目 – JSONparseメソッドでJSONデータをパースして返す

この関数で取得したデータを元にHTMLメールを制作します。

HTMLメールのテンプレート設定

これから新規で制作するHTMLメールのテンプレート設定を行います。テンプレートの設定を行うには、HtmlServiceクラスを使用します。この処理も一つの関数にまとめてしまいます。

/**
 * HTML Template create.
 * 
 * @param  Object data
 * @return String
 */
function createTemplate(data) {
  var html  = HtmlService.createTemplateFromFile('mail_template');
  html.data = data;
  html.len  = data.forecasts.length;
  html.pref = data.location.prefecture;

  return html.evaluate().getContent();
}
  1. 07行目 – 引数にparseJson関数で取得した値を受け取る
  2. 08行目 – HtmlServiceクラスのcreateTemplateFromFileメソッドでHTMLテンプレートファイル名を指定(これから新規作成する)してオブジェクトを変数にセット
  3. 09行目 – テンプレート側にdataをセット
  4. 10行目 – テンプレート側にdata.forecasts(天気情報)の要素数をセット
  5. 11行目 – テンプレート側にdata.location.prefecture(都道府県名)をセット
  6. 13行目 – evaluateメソッドでテンプレートをレンダリングしてコンテンツを取得したものを返す

HTMLメールのテンプレート制作

次にHTMLメールのテンプレートを制作します。「ファイル」→「新規作成」からHTMLファイルを選択します。ファイル名は、先程のcreateTemplate関数内で、createTemplateFromFileメソッドの引数に指定した「mail_template」にします。(html拡張子つけます)

HTMLファイル作成

HTMLを普通にコーディングしますが、GASから渡した値を使用するためにHTMLテンプレート側にスクリプトを記述する必要があります。

記述方法は、<? …… ?>で、GASのシンタックスを記述。<?= …… ?>でアウトプットします。XSS対策のためエスケープされて出力されます。とりあえず、mail_template.htmlの全文。

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h2><?= pref ?>のお天気</h2>
    <ul style="list-style: none; padding: 0;">
      <? for (var i = 0; i < len; i++) { ?>
      <li style="float: left; margin: 0 15px 0 0;">
      <span style="display: block;"><?= data.forecasts[i].dateLabel ?>[<?= data.forecasts[i].date ?>]</span>
      <span style="display: block;"><?= data.forecasts[i].telop ?></span>
      <img style="margin: 10px 0" src="<?= data.forecasts[i].image.url ?>" alt="<?= data.forecasts[i].image.title ?>">
      </li>
      <? } ?>
    </ul>
    <hr style="clear: both;">
  </body>
</html>

例えば7行目の <h2><?= pref ?>のお天気</h2>は、pref変数にGAS側から、html.pref = data.location.prefecture;と渡している値が表示されますので、「宮崎県宮崎市のお天気」という文字列がh2要素に囲まれて表示されます。

そういう具合に通常のGASと同じようにループして表示したりしてあげれば完成します。

メールの送信

最後にメールの送信処理を書きます。これも関数化してあげます。

/**
 * HTML mail send.
 * 
 * @param String content
 */
function sendMail(content) {
  MailApp.sendEmail({
    to: 'info@example.jp',
    subject: '今日のお天気',
    htmlBody: content
  });
}

メールの送信には、MailAppクラスを使用します。sendEmailメソッドにメールのヘッダー情報を渡します。contentは、createTemplate関数の戻り値をsendMail関数の引数に渡して、htmlBodyにセットします。これで完了。

関数を動作させる関数

各処理の関数、テンプレートの準備ができたのでそれらを動作させる関数を、main関数としてその中で全部の処理をつなげます。以下、main.js全文。

/**
 * Main Function
 */
function main() {
  var data    = parseJson();
  var content = createTemplate(data);
  sendMail(content);
}

/**
 * Weather Hacks JSON Parse
 * http://weather.livedoor.com/weather_hacks/webservice
 *
 * return Object
 */
function parseJson() {
  var feedURL  = "http://weather.livedoor.com/forecast/webservice/json/v1?city=450010";
  var response = UrlFetchApp.fetch(feedURL);
  return JSON.parse(response.getContentText());
}

/**
 * HTML Template create.
 * 
 * @param  Object data
 * @return String
 */
function createTemplate(data) {
  var html  = HtmlService.createTemplateFromFile('mail_template');
  html.data = data;
  html.len  = data.forecasts.length;
  html.pref = data.location.prefecture;

  return html.evaluate().getContent();
}

/**
 * HTML mail send.
 * 
 * @param String content
 */
function sendMail(content) {
  MailApp.sendEmail({
    to: 'info@example.com',
    subject: '今日のお天気',
    htmlBody: content
  });
}

これで準備OK。それでは、main関数を実行してみます。※送信先メールアドレスは変更してください。

今日のお天気メール

できた!\(^o^)/
HTMLメールが届きました。あとは、トリガーの設定したりして好きな時間帯に送るだけです。

余談

HTMLメールを久しぶりに作ったのですが、スタイル設定などメーラーによって異なる部分があったり、外部CSSやhead要素内でのstyle要素定義をいい感じにインラインにコンバートしてくれるサイトを教えてもらったのでご紹介。Gmailがあまり色々できないみたいなので、Gmail基準で作っていけば大丈夫かな?

HTML Mail Style Guide
https://www.campaignmonitor.com/css/
Bring your email styles inline
http://foundation.zurb.com/emails/inliner.html