f7: メール で LINE メッセージ送受信


.

/ 2019/10/13 訂正

/ [ 2. 仕込 1 (LINE からの受信) ] line-receive.php
/ 　メール本文の出力項目の順序変更( who, msg/txt を上部へ)

/ [ 3. 仕込 2 (LINE への送信) ] line-send.php
/ 　以下 タイプミス修正と、あいまい型判定による
/ 　フレンド指定 ID が取得できなくても POST されるバグの修正
/ 　1. タイプミス修正 - (too1 != 99) -> (too01 != 99)
/ 　2. 型変換ロジックの追加 - is_int(), is_numeric(), strpos('.')
/ 　3. if分岐の型判定追加
/ 　　if (Subject1 == 1) -> if (sbj01 === 1)
/ 　　if (too01 != 99) -> if (too01 !== 99)

/ を行ないました、あいまい を あいまいのまま にすると
/ こうなりますの典型例です、失礼いたしました

/ 型判定は、ひとまず、
/ 　1) 整数か否か is_int
/ 　2) 数値文字列か否か is_numeric
/ 　3) 小数点は除外 strpos
/ 　4) 数値文字列ならキャストで数値型変換
/ 　5) 符号付きは そのまま判定対象
/ としましたが、もう少しスマートな方法もあるかと思います

---

前回記事 [Pythonista で LINE メッセージ送信]
https://qiita.com/cxfgp/items/bb82b4ce7b7af000bd6f
と やることは同じです

違いは以下

・Pythonista 版
　1. iOS 限定、送信 のみ
　2. POST が ダイレクトの為 送達が多少速い
　3. テキスト 1行目 -> フレンド No. 指定

・メール 版
　1. 送信も 受信も 可能
　2. メール環境さえあれば LINE メッセージのやりとりが可能
　3. メールの件名 -> フレンド No. 指定


< 補足 1 >

　・皆様が記事している LINE Messaging API の登録・設定は割愛
　・LINE Messaging API + フリープラン -> 1000通/月 制限有
　・相手先の公式アカウントに出現する( = フレンドには表示されない)
　・フレンドID は事前取得しているものとする
　・テキストメッセージ送信のみ(スタンプその他未対応)

< 補足 2 > (フレンドID の事前取得 に 関して)

　事前に webhook -> line-receive.php を
　仕込んでおいて QR コードか URL で
　フレンドに 登録(追加のアクション) 
　をしてもらい レスポンスより 
　フレンドID を取得し、フレンド分岐処理に埋め込み
　というベタなやり方をしました
　実際 フレンドID の事前取得が必須
　(API 上、フレンド登録済み前提) な為
　いきなり Pythonista 版 ( = LINE POST ) は 出来ないです


---
### **[ 1. キッチン ]**

さくらのレンタルサーバ
スタンダード

php 7.2

LINE Messaging API


---
### **[ 2. 仕込 1 (LINE からの受信) ]**

01) LINE Messaging API コンソール上の webhook URL を設定
https://xxxx.xxxx/xx/line-receive.php
02) スクリプトの設置
03) フレンドの招待 (登録依頼)
　

```php:line-receive.php

#!/usr/local/bin/php

<?php

mb_language("Japanese");
mb_internal_encoding("UTF-8");

date_default_timezone_set('Asia/Tokyo');

// webhook からの受け取り
$json_string = file_get_contents('php://input');

if(isset($json_string)){ 

	$now20 = date('Y-m-d H:i:s');

	$json_object = json_decode($json_string);

	$replyToken20 = $json_object->{"events"}[0]->{"replyToken"};
	$type20a = $json_object->{"events"}[0]->{"type"};

	$type20b = $json_object->{"events"}[0]->{"source"}->{"type"};
	$userId20 = $json_object->{"events"}[0]->{"source"}->{"userId"};

	$msg_id20 = $json_object->{"events"}[0]->{"message"}->{"id"};
	$msg_type20c = $json_object->{"events"}[0]->{"message"}->{"type"};
	$msg_text20 = $json_object->{"events"}[0]->{"message"}->{"text"};


	// ====================================

	// フレンド 1: ゆうちゃん
	$unam01 = 'Uxxxxxxxxxxxxxx1';

	// フレンド 2: むうちゃん
	$unam02 = 'Uxxxxxxxxxxxxxx2';

	$usds01 = '';

	// フレンドの振り分け
	if($userId20 == $unam01){
		$usds01 = 'yuu';
	} elseif ($userId20 == $unam02){
		$usds01 = 'muu';
	} else {
		$usds01 = 'user unknown';
	}

	// ====================================


	// type = text ならメール送信
	if($msg_type20c == "text"){

		$name2 = "FROM-LINE: ".$usds01." ".$now20;

		$text5 = $msg_text20;

		$text6 = "\n".$now20."\n\n"
		."who: ".$usds01."\n\n"
		."msg/txt: ".$text5."\n\n"
		."RToken: ".$replyToken20."\n\n"
		."type1: ".$type20a."\n"
		."src/type2: ".$type20b."\n"
		."src/usrid: ".$userId20."\n\n"
		."msg/id: ".$msg_id20."\n"
		."msg/type3: ".$msg_type20c."\n\n";

		$to = 'info@mailaddress.com';

		$subject = $name2;
		$message = $text6;

		$headers = 'From: sakura@mailaddress.com' . "\r\n";

		if (mb_send_mail($to, $subject, $message, $headers)) {
			// echo "send mail is ok";
		} else {
			// echo "send mail is ng";
		}

	}

}

?>

```

QRコードや URL で招待したフレンドが 追加 後に
メッセージ送信のアクションを起こすと
webhook した php 経由で 指定メールアドレスに
LINE メッセージが 届きます
(フレンドID が取得出来ます、
最初は user unknown になります)


---
### **[ 3. 仕込 2 (LINE への送信) ]**

01) LINE 送信用に ドメインメールアカウントを作成
02) .mailfilter に以下追記で、 php へパイプ設定
cc "| /usr/local/bin/php -q /home/xxxx/www/xxxx/line-send.php"
03) スクリプトの設置
　

```php:line-send.php

#!/usr/local/bin/php

<?php

require_once('/home/xxxx/www/xxxx/mimeDecode.php');

mb_language("Japanese");
mb_internal_encoding("UTF-8");


// メールパース (mimeDecode.php 使用)
$params['include_bodies'] = true; 
$params['decode_bodies']  = true; 
$params['decode_headers'] = true; 
$params['input'] = file_get_contents("php://stdin");
$params['crlf'] = "\r\n"; 

$mail_data = Mail_mimeDecode::decode($params); 

$FromAddress = trim($mail_data->headers['from']); 
$ToAddress = trim($mail_data->headers['to']); 
$Subject1 = trim($mail_data->headers['subject']);


// メールアドレス文字列のみ切り出し
//  例: abc <def@mailaddress.com> -> def@mailaddress.com
if(strpos($FromAddress,'<') !== false){
	$ff02 = strpos($FromAddress,'<');
	$ff02 += 1;
	$FromAddress = substr($FromAddress, $ff02, -1);
}


// 指定メールアドレスからの受信のみ LINE POST 許可
$eunf0 = 0;
$eunf1 = 'myaddress1@mailaddress.com';
$eunf2 = 'myaddress2@mailaddress.com';

if ($FromAddress === $eunf1) { $eunf0 = 1; }
elseif ($FromAddress === $eunf2) { $eunf0 = 1; }


if ($eunf0 == 1) {

	$Subject1 = mb_convert_encoding($Subject1,"UTF-8");

	$MailBody1 = $mail_data->body;
	$MailBody1 = mb_convert_encoding($MailBody1,"UTF-8");

	$frmpl6 = rtrim($MailBody1);

	$too01 = 0;
	$too02 = '';
	$too03 = '';
	$errno = 0;

	$ckr01 = 0;
	$ckr02 = 0;
	$ckr03 = 0;
	$sbj01 = 0;


	// $Subject1 が 整数 なら そのまま 代入
	if (is_int($Subject1)) {
		$ckr01 = 1;
		$sbj01 = $Subject1;

	} else {

		// $Subject1 が 数値文字列 か
		if (is_numeric($Subject1)) {

			// $Subject1 が 数値 (小数点) 文字列 なら 66 代入
			if(strpos($Subject1, '.') !== false){
				$ckr01 = 2;
				$sbj01 = 66;

			// $Subject1 が 数値 文字列 なら 整数型(キャスト) にして 代入
			} else {
				$ckr01 = 4;
				$sbj01 = (int)$Subject1;
			}

		// $Subject1 が 文字列 なら 88 代入
		} else {
			$ckr01 = 5;
			$sbj01 = 88;
		}

	}


	// =============================

	// if 分岐、$Subject1 -> $sbj01 に修正、型チェックも追加

	if ($sbj01 === 1) {

		// フレンド 1: ゆうちゃん
		$too01 = 1;
		$too02 = 'Uxxxxxxxxxxxxxx1';
		$too03 = 'yuu';

	} elseif ($sbj01 === 2) {

		// フレンド 2: むうちゃん
		$too01 = 2;
		$too02 = 'Uxxxxxxxxxxxxxx2';
		$too03 = 'muu';

	} else {

		// フレンド 指定先不明 -> 99
		$too01 = 99;
		$too02 = 'xxxx';
		$too03 = 'user unknown';

	}

	// =============================


	// 比較変数も 念のため 型チェック
	if (is_int($too01)) {
		$ckr02 = 1;
	} else {
		$ckr02 = 2;
	}


	// 件名 -> 指定先フレンドNo. 取得出来たら処理続行

	// タイプミス修正 ($too1 -> $too01, 型チェックも追加)
	// if ($too1 != 99) {
	if ($too01 !== 99) {

		// アクセストークン
		$channelToken = 'MxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxU=';

		$headers = [
		'Authorization: Bearer ' . $channelToken,
		'Content-Type: application/json; charset=utf-8',
		];

		// POST データを設定して JSON にエンコード
		$post = [
			// 'replyToken' => $replyToken,
			'to' => $too02,

			'messages' => [
				[
					'type' => 'text',
					'text' => $frmpl6,
				],
			],
		];

		$post = json_encode($post);

		// HTTPリクエストを設定
		$ch = curl_init('https://api.line.me/v2/bot/message/push');
		$options = [
			CURLOPT_CUSTOMREQUEST => 'POST',
			CURLOPT_HTTPHEADER => $headers,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_BINARYTRANSFER => true,
			CURLOPT_HEADER => true,
			CURLOPT_POSTFIELDS => $post,
		];

		curl_setopt_array($ch, $options);

		// 実行
		$result = curl_exec($ch);

		// エラーチェック
		$errno = curl_errno($ch);
		if ($errno) {
			// return;
		}

		$ckr03 = 1;
		$frmpl5 = "LINE-SEND: ".$Subject1.": ".$too03." - POST";

	} else {

		$ckr03 = 2;
		$frmpl5 = "LINE-SEND: ".$Subject1.": ".$too03." - UN-POST";

	}


	// バックアップメール送信

	$to33 = 'backup@mailaddress.com';
	$subject = $frmpl5;

	$message = "\n"."ckr01(Subject1): ".$ckr01."\n"
	."sbj01: ".$sbj01."\n"."ckr02(too01): ".$ckr02."\n"
	."ckr03(route): ".$ckr03."\n\n".$frmpl6."\n\n"
	."too01: ".$too01."\n"."too02: ".$too02."\n"
	."too03: ".$too03."\n"."err no: ".$errno."\n\n";

	$headers = 'From: sakura@mailaddress.com' . "\r\n";

	if (mb_send_mail($to33, $subject, $message, $headers)) {
		// echo "send mail is ok";
	} else {
		// echo "send mail is ng";
	}


} else {

	// アラート送信

	$frmpl21 = 'LINE-POST: ALERT';
	$frmpl22 = "\n"."[ 不許可アドレスからの投稿 ] "."\n"."FromAddress: ".$FromAddress."\n\n"."[ 許可アドレスは以下 ]"."\n"."eunf1: ".$eunf1."\n"."eunf2: ".$eunf2."\n\n";

	$to44 = 'alert@mailaddress.com';
	$subject = $frmpl21;
	$message = $frmpl22;
	$headers = 'From: sakura@mailaddress.com' . "\r\n";

	if (mb_send_mail($to44, $subject, $message, $headers)) {
		// echo "send mail is ok";
	} else {
		// echo "send mail is ng";
	}

}

?>

```

作成したドメインメール宛に
件名(subject) = フレンド指定先 No. 
(例：1 -> ゆうちゃん、2 -> むうちゃん) として
メールを送信すると、指定先フレンドの LINE に
LINE メッセージが届きます
( + バックアップメールが
指定先メールアドレスに送信されます)


---
### **[ 4. デザート ]**

LINE アプリを使用しない人向け
( SNS 系を メールに統一したい人向け )

API 公開 SNS で json / curl なら
「基本的に」同じ仕組みで可能
( API の仕様変更で使えなくなるまでは OK )
( Slack も Nexmo SMS も同様の仕組みで 使ってますが、
すべての SNS が OK ではないと思います )


以下、前回記事同様

※ 簡易的ざっくり作成なので
　プロセスエラーや細かなエラーは拾ってません
　(メールパースやエンコードも厳密処理ではないので
　送受信環境により文字化けやエラーが出るかもしれません)

.