Edited at

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

More than 1 year has passed since last update.

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

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

https://connpass.com/

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 全般については この書籍がとても詳しく、参考になりました。

https://www.amazon.co.jp/AWS-Lambda%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E5%A4%A7%E6%BE%A4-%E6%96%87%E5%AD%9D-ebook/dp/B0764C5MT5


ちなみに

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

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

となります。(ダイマ)