Alexa SDK for Node.js Ver2を使って、nodemailerによるメール送信とJSONによるサーバとのデータの受渡しを行います。「Alexa SDK for Node.js Ver2をAWS Lambdaにデプロイ」で Alexa SDK for Node.js Ver2をAWS Lambdaにデプロイしました。この「node_modules」にメーラライブラリ「nodemailer」を追加してデプロイします。ここでは、次のスクリプトを作成します。
- メーラライブラリ「nodemailer」によるメール送信
- JSONによるサーバへのデータ送信
- JSONによるサーバからのデータ受信
今回のスクリプトではASK SDK v1アダプター「ask-sdk-v1adapter」を使用します。これはV2でメール送信とJSONによるデータの受け渡しの方法が調べきれなかったためです。V2でスクリプトを作成すると、応答が返ってくる前にスクリプトが終了してしまします。
メーラライブラリ「nodemailer」のデプロイ
Raspberry piに作成したカスタムスキルを開発するローカルな開発環境で、次のコマンドでASK SDK v1アダプター「ask-sdk-v1adapter」とメーラライブラリ「nodemailer」をインストールし、作成したフォルダ/ファイルをzipファイルとして圧縮します。ただし、「aws-sdk」はフォルダが大きいため、Web上の「コードをインラインで編集」が利用できないので、削除してAWS Lambdaにデプロイは行いません。
$ npm install --save ask-sdk-v1adapter ask-sdk $ npm install nodemailer $ npm install nodemailer-smtp-transport
メーラライブラリ「nodemailer」によるメール送信
AWS Lambdaのindex.jsに次のスクリプトを記述し、メーラライブラリ「nodemailer」によりメールの送信が完了すると、Amazon Echoに「メールを送信しました」と発話させます。
- 2行目:ASK SDK v1アダプター「ask-sdk-v1adapter」を指定します。
- 6-10行目:ASK SDK v1アダプター「ask-sdk-v1adapter」で動作させるときはこのように変更します。
- 28-34行目:メールサーバへの接続情報を設定します。
- 29-44行目:送信するメールの内容を設定します。
index.js
'use strict'; const Alexa = require('ask-sdk-v1adapter'); var APP_ID = undefined; exports.handler = function (event, context, callback) { var alexa = Alexa.handler(event, context); alexa.APP_ID = APP_ID; alexa.registerHandlers(handlers); alexa.execute(); }; var handlers = { 'LaunchRequest': function () { this.emit('GetNewFactIntent'); }, 'GetNewFactIntent': function () { var te = this; var targetEmail = 'xxxx'; var fromEmail = 'xxxx'; var sesAccessKey = 'xxxx'; var sesSecretKey = 'xxxx'; var nodemailer = require('nodemailer'); var smtpTransport = require('nodemailer-smtp-transport'); var transporter = nodemailer.createTransport(smtpTransport({ host: 'xxxxx', port: 587, auth: { user: sesAccessKey, pass: sesSecretKey } })); var text = 'Tomoでございます。'; var mailOptions = { from: fromEmail, to: targetEmail, subject: '問い合わせ', text: text }; transporter.sendMail(mailOptions, function (error, info) { if (error) { console.log(error); } te.emit(':tell', 'メールを送信しました'); }); } };
AWS Lambda画面右上の「テスト」ボタンをクリックして作成した「index.js」を実行すると、次のような応答がAWS Lambda画面上に表示されます。また、Amazon開発者コンソールに紐づいたAmazon Echoからどのような音声を入力しても、「メールを送信しました」とAmazon Echoが答え、指定したメールの宛先にメールが届きます。
Response: { "version": "1.0", "response": { "shouldEndSession": true, "outputSpeech": { "type": "SSML", "ssml": "メールを送信しました " } }, }
JSONによるサーバへのデータ送信
AWS Lambdaのindex.jsに次のスクリプトを記述し、httpライブラリ「http」によりJSON形式のデータをWebサーバに送信し、送信が完了すると、Amazon Echoに「データを送信しました」と発話させます。
- 2行目:ASK SDK v1アダプター「ask-sdk-v1adapter」を指定します。
- 6-10行目:ASK SDK v1アダプター「ask-sdk-v1adapter」で動作させるときはこのように変更します。
- 23-26行目:送信するデータをJSON形式で記述します。
- 29-38行目:対象リソースの通信オプション「options」を使ってHTTPのパラメータ設定します。
index.js
'use strict'; const Alexa = require('ask-sdk-v1adapter'); var APP_ID = undefined; exports.handler = function (event, context, callback) { var alexa = Alexa.handler(event, context); alexa.APP_ID = APP_ID; alexa.registerHandlers(handlers); alexa.execute(); }; var handlers = { 'LaunchRequest': function () { this.emit('GetNewFactIntent'); }, 'GetNewFactIntent': function () { let http = require('http'); const HOST = `xxxx`; const PATH = `xxxx/postdata.php`; let postData = { "name": "TomoSoft8", "comment": "good soft" }; let postDataStr = JSON.stringify(postData); let options = { host: HOST, port: 80, path: PATH, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': postDataStr.length } }; let req = http.request(options, (res) => { console.log('STATUS: ' + res.statusCode); console.log('HEADERS: ' + JSON.stringify(res.headers)); res.setEncoding('utf8'); res.on('data', (chunk) => { console.log('BODY: ' + chunk); this.emit(':tell', 'データを送信しました'); }); }); req.on('error', (e) => { console.log('problem with request: ' + e.message); }); req.write(postDataStr); req.end(); } };
webサーバに置かれ、AWS Lambdaのindex.jsのスクリプトから呼ばれる「postdata.php」を次に示します。index.jsのスクリプトから呼ばれと、ファイル「samplepost.txt」に入力情報を保存し、JSON形式で渡された情報を応答として返します。
postdata.php
<?php try { $headers = getallheaders(); $post_body = file_get_contents('php://input'); $fp = fopen("samplepost.txt", "w"); foreach ($headers as $name => $value) { fwrite($fp,"$name: $value\n"); } fwrite($fp,"$post_body\n"); fclose($fp); $obj = json_decode($post_body); // オブジェクト形式 if ($obj === NULL) return; var_dump($obj); echo "<br>"; echo $obj->{'payload'}->{'channels'}[0]->{'value'}; echo "<br>"; echo $obj->{'datetime'}; echo "<br>"; } catch (PDOException $e){ var_dump($e->getMessage()); } ?>
AWS Lambda画面右上の「テスト」ボタンをクリックして作成した「index.js」を実行すると、次のような応答がAWS Lambda画面上に表示されます。console.logコマンドにより、応答のステータス、ヘッダ、戻り値を表示します。また、Amazon開発者コンソールに紐づいたAmazon Echoからどのような音声を入力しても、「データを送信しました」とAmazon Echoが答え、指定したWebサーバにデータが届きます。
Response: { "version": "1.0", "response": { "shouldEndSession": true, "outputSpeech": { "type": "SSML", "ssml": "データを送信しました " } }, } Function Logs: 2018-07-21T04:11:59.611Z STATUS: 200 2018-07-21T04:11:59.611Z HEADERS: {"server":"nginx","date":"Sat, 21 Jul 2018 04:11:59 GMT","content-type":"text/html; charset=UTF-8","transfer-encoding":"chunked","connection":"close","x-powered-by":"PHP/7.1.19"} 2018-07-21T04:11:59.613Z BODY: object(stdClass)#1 (2) { 2018-07-21T04:11:59.613Z BODY: ["name"]=> string(9) "TomoSoft8" ["comment"]=> string(9) "good soft" }
ファイル「samplepost.txt」に保存された入力情報を次に示します。JSON形式でデータが渡されていることがわかります。
samplepost.txt
Host: tomosoft.jp X-Real-Ip: 18.179.31.112 X-Forwarded-Proto: http Listen-Ipaddr: 49.212.207.43 Content-Length: 42 Content-Type: application/json {"name":"TomoSoft8","comment":"good soft"}
JSONによるサーバからのデータ受信
AWS Lambdaのindex.jsに次のスクリプトを記述し、httpライブラリ「http」によりJSON形式のデータをWebサーバに送信し、送信が完了すると、Amazon Echoに「データを送信しました」と発話させます。
- 2行目:ASK SDK v1アダプター「ask-sdk-v1adapter」を指定します。
- 6-10行目:ASK SDK v1アダプター「ask-sdk-v1adapter」で動作させるときはこのように変更します。
- 23-31行目:対象リソースの通信オプション「options」を使ってHTTPのパラメータ設定します。
- 41行目:JSON形式で受信したデータを使って、発話を編集します。
index.js
'use strict'; const Alexa = require('ask-sdk-v1adapter'); var APP_ID = undefined; exports.handler = function (event, context, callback) { var alexa = Alexa.handler(event, context); alexa.APP_ID = APP_ID; alexa.registerHandlers(handlers); alexa.execute(); }; var handlers = { 'LaunchRequest': function () { this.emit('GetNewFactIntent'); }, 'GetNewFactIntent': function () { let http = require('http'); const HOST = `xxxx`; const PATH = `xxxx/getdata.php`; let options = { host: HOST, port: 80, path: PATH, method: 'GET', headers: { 'Content-Type': 'application/json', } }; let req = http.request(options, (res) => { res.setEncoding('utf8'); res.on('data', (chunk) => { var parsedValue = JSON.parse(chunk); var key1 = "price"; console.log(parsedValue); console.log(parsedValue[key1]); this.emit(':tell', String(parsedValue['price']) + 'えんです'); }); }).on('error', (e) => { console.log(e.message); //エラー時 this.emit(':tell', 'エラーです' + e.message); }); req.end(); } };
webサーバに置かれ、AWS Lambdaのindex.jsのスクリプトから呼ばれる「getdata.php」を次に示します。index.jsのスクリプトから呼ばれと、JSON形式で情報「'{“price”:500, “item”:”card” , “date”:”2018/11/05″}’」を返します。
getdata.php
<?php try { // ヘッダーを指定 header( "Content-Type: application/json; charset=utf-8" ) ; $fp = fopen("sampleget.txt", "w"); fwrite($fp,"123\n"); fclose($fp); $post_body = '{"price":500, "item":"card" , "date":"2018/11/05"}'; echo $post_body ; } catch (PDOException $e){ var_dump($e->getMessage()); } ?>
AWS Lambda画面右上の「テスト」ボタンをクリックして作成した「index.js」を実行すると、次のような応答がAWS Lambda画面上に表示されます。Webサーバから受信したデータを、console.logコマンドにより表示します。また、Amazon開発者コンソールに紐づいたAmazon Echoからどのような音声を入力しても、指定したWebサーバからデータを受信し、受信したデータから「500えんです」とAmazon Echoが答えます。
Response: { "version": "1.0", "response": { "shouldEndSession": true, "outputSpeech": { "type": "SSML", "ssml": "500えんです " } }, } 2018-07-21T04:35:46.326Z { price: 500, item: 'card', date: '2018/11/05' } 2018-07-21T04:35:46.327Z 500