LoginSignup
10
8

More than 5 years have passed since last update.

AWS Lambda + SES + Node.js で、Connpass の新着情報を定期的にメールで取得する

Last updated at Posted at 2018-02-15

※ AWS Lambda と SES の勉強がてら、作ってみました。前記事の続き となります。

IT系勉強会を探すときに、Connpass をよく使っています。

Connpass では、所属するグループが新しい勉強会を登録すると、メールで通知を行ってくれます。

しかし、特定のキーワードや地域名での通知機能は存在しません。このため、自分が所属するグループ外で、面白そうな勉強会が開かれていても、情報を見過ごすことが何度かありました。

そこで、AWSを利用して

  • 自分が興味あるキーワード、地域の勉強会の登録情報を定期的に確認
  • 新しい勉強会が登録されたら、メールで通知する

ようにしてみました。

やること

Connpass で、自分が興味あるキーワードの勉強会が新規登録・更新されたら、メールで通知する。キーワードは「AWS」「東京都」の2つを含むものとする。

仕様

AWS Lambda で、一日一回「AWS」「東京都」に関する勉強会の更新・登録情報を検索する.
新着情報があったら、その勉強会のURLを AWS SES に渡し、自分宛てにメールで送信する.

以下

  • AWS SESの設定
  • IAMロールの設定
  • Lambda 関数の作成
  • コードの記述
  • テスト
  • CloudWatch によるスケジュール設定

の順番で記述します。

AWS SESの設定

SES (Simple Mail service) を利用するにはドメインもしくはメールアドレスを登録してベリファイを行う必要があります。今回はメールアドレスを登録することにしました。

2018年2月時点ではSESはアジア・パシフィック(東京)リージョンでは使えない。このため以下の3リージョンいずれかで設定する。

EU (アイルランド)
米国東部 (バージニア北部)
米国西部 (オレゴン)

今回はバージニア北部(us-east-1)で設定しました。リージョン情報は後で必要となるので控えておきます。

SESのコンソールから登録したいメールアドレスを入力します。

lambda_01.png

登録したメールアドレス宛に、確認用のメールが届くので、URLをクリックすると、ベリファイが終了。登録したメールアドレスをFromとしてメールの送信が可能となります。

lambda_03.png

IAMロールの設定

IAMロールの設定を行います。Lambda では 関数を登録する際に、任意の権限を持つロールを付与する必要があります。

Lambda関数の実行のため 「AWSLambdaExecute」、SESの操作のため「AmazonSESFullAccess」の
2つのポリシーをアタッチしたIAMロールを作成する。名前は「Lambda_test」としました。

lambda_06.png

Lambda 関数の作成

AWSのコンソールからLambda を選び、新規関数を作成。

lambda_07.png

「一から作成」を選び、名前、ランタイム、ロールを設定する。ランタイムはNode.js 6.10、ロールは先ほど作成したロールを選択します。

コードの記述

Node.js で、Connpass のAPIを検索=>SESでメール送信するまでのコードを登録します。

AWS Lambda でNode.jsのパッケージを利用する場合、予めzipファイルで圧縮して、Lambda 上に転送する必要があるそうです。

Azure Functions で実装したときは、APIとの通信に「request」モジュールを利用しました が、パッケージをまとめてZIPを作成するのが少々手間に思えたため、Node.js の標準機能として利用可能な「https」モジュールを利用する形に書き換えました。

exports.handler = (event, context) => {

  "use strict";

// APIとの通信のためhttpsモジュールを利用

  const https = require('https');

// API検索に利用する変数を定義 

  const DOMAIN = 'connpass.com';
  const PATH = '/api/v1/event/?keyword=aws&keyword=%E6%9D%B1%E4%BA%AC%E9%83%BD';

// AWS SESでメール送信するための各種変数を定義

  const mailTo = ['メールの送信先アドレス'];
  const mailFrom = 'SESで認証したメールアドレス';
  const AWS = require('aws-sdk');
  AWS.config = new AWS.Config();
  AWS.config.region = "us-east-1";
  const ses = new AWS.SES({
    apiVersion: '2010-12-01'
  });

// 通信結果を受け取る変数「response」と、メール文面を作るための変数「list」を定義

  let response = '';
  let list = '';

// 関数「ConnpassSearch」を利用して新着勉強会の情報を取得
// 過去24時間内にアップデートがあった勉強会のURLを変数に格納

  connpassSearch(DOMAIN, PATH).then(function(json) {
    const events = json.events;
    const dt = new Date();
    const yesterday = dt - 86400000;
    list += '「AWS」「東京都」に合致する勉強会の更新がありました。\n';
    for (let i in events) {
      let updated_at = new Date(events[i].updated_at);
      if (updated_at > yesterday) {
        list += events[i].event_url + "\n";
      }
    }

    // AWS SES へ更新・新着勉強会のURLを渡す

      postData(list);

  });


// 関数「ConnpassSearch」を定義
// Connpass のAPIを叩き、取得したデータをPromise で返す

  function connpassSearch(DOMAIN, PATH) {
    const options = {
      host: DOMAIN,
      path: PATH,
      method: 'get',
      headers: {
        'Content-Type': 'application/json',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
      }
    };
    return new Promise((resolve, reject) => {
      const req = https.request(options, (res) => {
        res.on('data', (chunk) => {
          response += chunk;
        });
        res.on('end', (res) => {
          res = JSON.parse(response);
          resolve(res);
        });
      })
      req.on('error', (e) => {
        console.error(`problem with request: ${e.message}`);
      });
      req.end();
    });
  }


// AWS SESでメール送信を行う関数「postData」を定義

  function postData(list) {
    ses.sendEmail({
      Source: mailFrom,
      Destination: {
        ToAddresses: mailTo
      },
      Message: {
        Subject: {
          Data: 'Connpassで勉強会の更新がありました。'
        },
        Body: {
          Text: {
            Data: list,
          }
        }
      }
    }, function(err, data) {
      if (err) throw err
      console.log('Email sent:');
      console.log(data);
    });
  }
};



記述したコードを、Lambda のエディタ画面に貼り付けます。

実行時間を設定します。今回のコードは、REST APIの通信結果を待ってから処理を行うため、30秒に設定してみました。

lambda_12.png

テスト

コードの貼り付けと設定が終わったら、テストを行います。
今回のコードは何かデータを受け取ってから処理を行うわけではなく、コード単体で完結してるため、初期状態で用意されている「Hello World」のテストデータをそのまま使います。

lambda_13.png

設定が終わったら、テストを実行。正常終了のログが出力され、データがメールで飛んできたらテスト完了です。

CloudWatch によるスケジュール設定

最後に、CloudWatch を設定して、毎日朝8時にコードを起動するようにします。

lambda_15.png

今回はcron式で記述しました。Lambda のCron式設定は、このドキュメントに書いている ので、書式を確認しながら設定します。日本時間のAM8時は、UTCの23時となります。

lambda_16.png

定時実行の設定が終わったら終了です。

以後、毎日朝8時に、Connpassに新規登録・もしくは更新があった勉強会のURLがメールで送信されます。

lambda_17.png

参考情報

以下のドキュメントを参考にしました。

https://dev.classmethod.jp/cloud/aws/lambda-to-ses/
https://qiita.com/ysti/items/9eeca4179aab5ea847b5
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/ses-examples.html
https://nodejs.org/api/http.html#http_http_request_options_callback
https://qiita.com/n0bisuke/items/33a6a6da1d6f455105f9
https://qiita.com/yoshidasts/items/2d7117ef0f31754a06ab

Lambda 全般については この書籍がとても詳しく、参考になりました。

ちなみに

Movable Type に関する Connpass のエンドポイントは

https://connpass.com/api/v1/event/?keyword=Movable%20Type

となります。(ダイマ)

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8