不覚にも、メールサーバのユーザパスワードが突破され、
50件程度の踏み台にされてしまったので、対策を行った。
先ずは、ユーザのパスワードを即座に変更
# passwd <ユーザ名>
Changing password for user <ユーザ名>.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
メーラー等の設定を修正する。
スパム送信元のIPアドレスを探る。
# tail -10000 /var/log/maillog | grep "LOGIN"
May 14 05:29:03 www postfix/smtpd[xxxx]: xxxxxxxxxxxx: client=unknown[141.XXX.XXX.XXX], sasl_method=LOGIN, sasl_username=ごめんなさい・・・確かに、ヨーロッパのサーバ(ここも踏み台?)に突破されています。
postfixに拒絶するIPアドレスを指定する。
# vi /etc/postfix/main.cf
末尾に
smtpd_client_restrictions=
permit_mynetworks,
check_client_access hash:/etc/postfix/reject_ip,
permit
smtpd_client_restrictions で接続の許可、拒否の定義をする。
permit_mynetworks, $mynetworksに書いたアドレスは許可する。
check_client_access hash:/etc/postfix/reject_ip, 指定するipを拒否
permit 上記以外を許可
拒否するIPアドレス一覧を作成
記載方法は、拒否したいIPアドレス、ドメイン + REJECTと記載。
# nano /etc/postfix/reject_ip
send.hogehoge.com REJECT
141.XXX.XXX.XXX REJECT
141.XXX.XXX REJECT
reject_ipをDB形式に変換
# postmap /etc/postfix/reject_ip
Postfixをリロード
# systemctl restart postfix
設定が反映される。
パスワードは、乱数生成が必須とまではいかないまでも、
ある程度読まれないものにしないとだめだなぁ・・・
突破されるとは思わなんだ・・・。
2020/04/05
slackの登録とbot起動 終了
今更ながら、slackbotに手を出してみる
参考にさせて頂いたところ
https://se.miyabikno-jobs.com/entrance-labotlatori/
Hubotを使う方法が簡単なようなので、上記を参考に導入
01.slackのアカウント取得
02.Hubotのアプリを追加
03.HubotのAPIトークンを取得
04.pythonのライブラリ slackbotをインストール
$ sudo apt-get install python-3-pip
$ sudo pip3 install slackbot
$ mkdir slackbot
$ cd slackbot
05. $ touch slackbot_settings.py bot.py botmodule.py
・slackbot_settings.py:Botの設定を書くためのファイル(名称変更不可)
・bot.py:Botを起動するための実行ファイル(名前は任意)
・botmodule.py:Botの応答を記述するためのモジュール(名前は任意)
06.$ nano slackbot_settings.py
# 「API_TOKEN」にはSlackから取得したAPIトークンを記述
API_TOKEN = "XXXXXXXXXXXXXXXXXXX"
# 知らない言葉を聞いた時のデフォルトの応答
DEFAULT_REPLY = "その言葉の意味は学習していません"
# 外部ファイルを読み込む。botmodule.pyを読込
PLUGINS = [
'slackbot.plugins',
'botmodule',
]
07.$ nano bot.py
from slackbot.bot import Bot
# Botを起動する
def main():
bot = Bot()
bot.run()
if __name__ == "__main__":
main()
08.$ nano botmodule.py
from slackbot.bot import respond_to
from slackbot.bot import listen_to
# 「respond_to」はメンションする(@でターゲットを指定すること)と応答する
@respond_to('よろしく')
def greeting_1(message):
# Slackに応答を返す
message.reply('よろしくお願いします!')
# 「listen_to」はメンションがなくても応答する
@listen_to('コニチハ')
def greeting_2(message):
message.reply('コニチハ')
09.$ nohup python3 bot.py &
ssh接続を切っても稼働するようにnohup ~ &で起動
再度sshで接続し、プロセスを停止さえたい場合は、
$ ps x
にて pyhon3 bot.py のプロセスidを調べて、
$ kill -9
として停止させる。
ログインシェルがsshを閉じる際にSIGHUPを投げるため、プロセスが終了してしまうと思っていた。
nohupはSIGHUPのシグナルハンドラをSIG_IGNに設定、つまり「受信しても無視」する設定にして、コマンドラインで指定されたジョブを実行している。
nohupで起動した時点ではRUNNNINGだが、端末が閉じられた後、標準入力に対してread()するようなプログラムでは、(5分ごとに読みなおしなどの動作が入るもの)はcloseしてしまっていて、
EOFを返してきてしまう。
nohupを使わなくても停止しないケースもあるようだが、説明が難しい。
非常に詳しくテストされた解説が掲載されている
https://www.glamenv-septzen.net/view/854
実際は、SIGHUPのデフォルト処理はプロセス終了となっており、SIGHUPの受信にかかわらず、プロセスが終了するとき、そのプロセスがセッションリーダーだった場合、カーネルからそのセッションのフォアグラウンドプロセスグループに対してSIGHUPが送信されるらしい。
また、カーネル側で放置しているバックグラウンドジョブに対しても、シェル(bash)側で終了時にSIGTERM/SIGCONTを送信する事があるためというのが実態のようだ。
参考にさせて頂いたところ
https://se.miyabikno-jobs.com/entrance-labotlatori/
Hubotを使う方法が簡単なようなので、上記を参考に導入
01.slackのアカウント取得
02.Hubotのアプリを追加
03.HubotのAPIトークンを取得
04.pythonのライブラリ slackbotをインストール
$ sudo apt-get install python-3-pip
$ sudo pip3 install slackbot
$ mkdir slackbot
$ cd slackbot
05. $ touch slackbot_settings.py bot.py botmodule.py
・slackbot_settings.py:Botの設定を書くためのファイル(名称変更不可)
・bot.py:Botを起動するための実行ファイル(名前は任意)
・botmodule.py:Botの応答を記述するためのモジュール(名前は任意)
06.$ nano slackbot_settings.py
# 「API_TOKEN」にはSlackから取得したAPIトークンを記述
API_TOKEN = "XXXXXXXXXXXXXXXXXXX"
# 知らない言葉を聞いた時のデフォルトの応答
DEFAULT_REPLY = "その言葉の意味は学習していません"
# 外部ファイルを読み込む。botmodule.pyを読込
PLUGINS = [
'slackbot.plugins',
'botmodule',
]
07.$ nano bot.py
from slackbot.bot import Bot
# Botを起動する
def main():
bot = Bot()
bot.run()
if __name__ == "__main__":
main()
08.$ nano botmodule.py
from slackbot.bot import respond_to
from slackbot.bot import listen_to
# 「respond_to」はメンションする(@でターゲットを指定すること)と応答する
@respond_to('よろしく')
def greeting_1(message):
# Slackに応答を返す
message.reply('よろしくお願いします!')
# 「listen_to」はメンションがなくても応答する
@listen_to('コニチハ')
def greeting_2(message):
message.reply('コニチハ')
09.$ nohup python3 bot.py &
ssh接続を切っても稼働するようにnohup ~ &で起動
再度sshで接続し、プロセスを停止さえたい場合は、
$ ps x
にて pyhon3 bot.py のプロセスid
$ kill -9
として停止させる。
ログインシェルがsshを閉じる際にSIGHUPを投げるため、プロセスが終了してしまうと思っていた。
nohupはSIGHUPのシグナルハンドラをSIG_IGNに設定、つまり「受信しても無視」する設定にして、コマンドラインで指定されたジョブを実行している。
nohupで起動した時点ではRUNNNINGだが、端末が閉じられた後、標準入力に対してread()するようなプログラムでは、(5分ごとに読みなおしなどの動作が入るもの)はcloseしてしまっていて、
EOFを返してきてしまう。
nohupを使わなくても停止しないケースもあるようだが、説明が難しい。
非常に詳しくテストされた解説が掲載されている
https://www.glamenv-septzen.net/view/854
実際は、SIGHUPのデフォルト処理はプロセス終了となっており、SIGHUPの受信にかかわらず、プロセスが終了するとき、そのプロセスがセッションリーダーだった場合、カーネルからそのセッションのフォアグラウンドプロセスグループに対してSIGHUPが送信されるらしい。
また、カーネル側で放置しているバックグラウンドジョブに対しても、シェル(bash)側で終了時にSIGTERM/SIGCONTを送信する事があるためというのが実態のようだ。
2019/12/12
土日・祝祭日をカウントしないクエリ
土日、祝祭日をカウントしないで、経過日数から処理を行いたい。
休日テーブルのようなものを作って、LEFTJOINして加工
のようなことをやっていたが、
DBなくても動くものが欲しかったので、調べてみたオボエガキ。
範囲を絞る方法として、
次のように使う
select 【id】 from 【table名】
where (to_timestamp(to_char(now(),'YYYY-MM-DD'),'YYYY-MM-DD') -
(to_timestamp(to_char(【table名】.【受付日】,'9999-99-99'),'YYYY-MM-DD'))) > interval '5 days'
and
(SELECT count(*) FROM generate_series(to_timestamp(to_char(【table名】.【受付日】,'9999-99-99'),'YYYY-MM-DD'),
to_timestamp(to_char(now(),'YYYY-MM-DD'),'YYYY-MM-DD')-interval '1 day',
interval '1 day') the_day
WHERE (extract('ISODOW' FROM the_day) < 6
and not(EXTRACT(MONTH FROM the_day) * 100
+ EXTRACT(DAY FROM the_day)
IN (101, 113, 211, 223, 224, 320, 429, 503, 504, 505, 506, 723, 724, 810, 921, 922, 1103, 1123) ) ) ) >4
idが 【table名】.【受付日】から5日以上経過(当日含まないので中4日)
なお、条件として、【table名】.【受付日】がint2(8)の為、DATE型に変換している。
解説
副問い合わせをしているのだが、
(SELECT count(*) FROM generate_series(to_timestamp(to_char(【table名】.【受付日】,'9999-99-99'),'YYYY-MM-DD'),
to_timestamp(to_char(now(),'YYYY-MM-DD'),'YYYY-MM-DD')-interval '1 day',
interval '1 day') the_day
WHERE (extract('ISODOW' FROM the_day) < 6
and not(EXTRACT(MONTH FROM the_day) * 100
+ EXTRACT(DAY FROM the_day)
IN (101, 113, 211, 223, 224, 320, 429, 503, 504, 505, 506, 723, 724, 810, 921, 922, 1103, 1123) ) ) ) >4
generate_series という集合を返す関数を使って、カウントが中4日となる様に制御している。
generate_series
(
to_timestamp(to_char(【table名】.【受付日】,'9999-99-99'),'YYYY-MM-DD'),
to_timestamp(to_char(now(),'YYYY-MM-DD'),'YYYY-MM-DD')-interval '1 day',
interval '1 day'
) the_day
始まり,終わり,間隔 と記載している。
終わりの中で -interval '1 day' としているのは、当日を入れたくないため。
WHERE
(
extract('ISODOW' FROM the_day) < 6
and not
(
EXTRACT(MONTH FROM the_day) * 100
+
EXTRACT(DAY FROM the_day)
IN
(101, 113, 211, 223, 224, 320, 429, 503, 504, 505, 506, 723, 724, 810, 921, 922, 1103, 1123)
)
extract('ISODOW' FROM the_day) < 6 ISODOWは6が土曜、7が日曜となる。
(DOWだと0が日曜、6が土曜)
and not 以下の括りで、国民の休日をカウント対象から除外させている。
EXTRACT(MONTH FROM the_day) * 100
+
EXTRACT(DAY FROM the_day)
で月を100倍し、日と足す。
これを 副問い合わせのIN関数
(左側の式の結果が右側の式のどれかと等しい場合、結果は「真」を返す)
を用いて、その日付だった場合は、2重否定となり、カウントされない。
固定日以外の春分の日なんかは、国立天文台の算定式で括ってあげればいいんだが、
このところ、天皇即位やオリンピックで変則が多いので、調べて直接日付を書いたほうが
よさそう。
春分の計算
(EXTRACT(MONTH FROM date) = 3
AND EXTRACT(DAY FROM date) = FLOOR(20.8431
+ 0.242194 * (EXTRACT(YEAR FROM date) - 1980))
- FLOOR((EXTRACT(YEAR FROM date) - 1980) / 4))
and not でそれぞれ括れば、除外できるが
and not が直ぐに思いつかなかった・・・。
休日テーブルのようなものを作って、LEFTJOINして加工
のようなことをやっていたが、
DBなくても動くものが欲しかったので、調べてみたオボエガキ。
範囲を絞る方法として、
次のように使う
select 【id】 from 【table名】
where (to_timestamp(to_char(now(),'YYYY-MM-DD'),'YYYY-MM-DD') -
(to_timestamp(to_char(【table名】.【受付日】,'9999-99-99'),'YYYY-MM-DD'))) > interval '5 days'
and
(SELECT count(*) FROM generate_series(to_timestamp(to_char(【table名】.【受付日】,'9999-99-99'),'YYYY-MM-DD'),
to_timestamp(to_char(now(),'YYYY-MM-DD'),'YYYY-MM-DD')-interval '1 day',
interval '1 day') the_day
WHERE (extract('ISODOW' FROM the_day) < 6
and not(EXTRACT(MONTH FROM the_day) * 100
+ EXTRACT(DAY FROM the_day)
IN (101, 113, 211, 223, 224, 320, 429, 503, 504, 505, 506, 723, 724, 810, 921, 922, 1103, 1123) ) ) ) >4
idが 【table名】.【受付日】から5日以上経過(当日含まないので中4日)
なお、条件として、【table名】.【受付日】がint2(8)の為、DATE型に変換している。
解説
副問い合わせをしているのだが、
(SELECT count(*) FROM generate_series(to_timestamp(to_char(【table名】.【受付日】,'9999-99-99'),'YYYY-MM-DD'),
to_timestamp(to_char(now(),'YYYY-MM-DD'),'YYYY-MM-DD')-interval '1 day',
interval '1 day') the_day
WHERE (extract('ISODOW' FROM the_day) < 6
and not(EXTRACT(MONTH FROM the_day) * 100
+ EXTRACT(DAY FROM the_day)
IN (101, 113, 211, 223, 224, 320, 429, 503, 504, 505, 506, 723, 724, 810, 921, 922, 1103, 1123) ) ) ) >4
generate_series という集合を返す関数を使って、カウントが中4日となる様に制御している。
generate_series
(
to_timestamp(to_char(【table名】.【受付日】,'9999-99-99'),'YYYY-MM-DD'),
to_timestamp(to_char(now(),'YYYY-MM-DD'),'YYYY-MM-DD')-interval '1 day',
interval '1 day'
) the_day
始まり,終わり,間隔 と記載している。
終わりの中で -interval '1 day' としているのは、当日を入れたくないため。
WHERE
(
extract('ISODOW' FROM the_day) < 6
and not
(
EXTRACT(MONTH FROM the_day) * 100
+
EXTRACT(DAY FROM the_day)
IN
(101, 113, 211, 223, 224, 320, 429, 503, 504, 505, 506, 723, 724, 810, 921, 922, 1103, 1123)
)
extract('ISODOW' FROM the_day) < 6 ISODOWは6が土曜、7が日曜となる。
(DOWだと0が日曜、6が土曜)
and not 以下の括りで、国民の休日をカウント対象から除外させている。
EXTRACT(MONTH FROM the_day) * 100
+
EXTRACT(DAY FROM the_day)
で月を100倍し、日と足す。
これを 副問い合わせのIN関数
(左側の式の結果が右側の式のどれかと等しい場合、結果は「真」を返す)
を用いて、その日付だった場合は、2重否定となり、カウントされない。
固定日以外の春分の日なんかは、国立天文台の算定式で括ってあげればいいんだが、
このところ、天皇即位やオリンピックで変則が多いので、調べて直接日付を書いたほうが
よさそう。
春分の計算
(EXTRACT(MONTH FROM date) = 3
AND EXTRACT(DAY FROM date) = FLOOR(20.8431
+ 0.242194 * (EXTRACT(YEAR FROM date) - 1980))
- FLOOR((EXTRACT(YEAR FROM date) - 1980) / 4))
and not でそれぞれ括れば、除外できるが
and not が直ぐに思いつかなかった・・・。
2019/11/22
PHP SMS APIサービスのテスト Twilio送信内容の確認
昨日の投稿の続き
送った内容をコンソールでなく、ブラウザ上で確認したい。
検索等の実装も可能なようだ。
先ずは、一覧を表示できないと話にならないので、サンプルを作成してみる。
PHPサンプル list_messages.php
<?php
require("/autoloadが置いてあるでぃてくとりをフルパスで指定/autoload.php" );
use Twilio\Rest\Client;
//定義
$sid = "アカウントのSID";
$token = "アカウントのAUTHTOKEN";
$twilio = new Client($sid, $token);
$messages = $twilio->messages
->read(array(), 20);//取り合えず20個まで
foreach ($messages as $record) {
print($record->to);//toで送信先の番号
print($record->body);//送信メッセージの内容
}
?>
送信結果を取りたいのであれば、
body
date_sent
status
to
body
で十分な気がする。
取得できる配列は以下のようだ。
JSON APIの記載があった。
"account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"api_version": "2010-04-01",
"body": "testing",
"date_created": "Fri, 24 May 2019 17:18:27 +0000",
"date_sent": "Fri, 24 May 2019 17:18:28 +0000",
"date_updated": "Fri, 24 May 2019 17:18:28 +0000",
"direction": "outbound-api",
"error_code": 30007,
"error_message": "Carrier violation",
"from": "+12019235161",
"messaging_service_sid": "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"num_media": "0",
"num_segments": "1",
"price": "-0.00750",
"price_unit": "USD",
"sid": "MMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"status": "sent",
"subresource_uris": {
"media": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMb7c0a2ce80504485a6f653a7110836f5/Media.json",
"feedback": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMb7c0a2ce80504485a6f653a7110836f5/Feedback.json"
},
"to": "+18182008801",
"uri": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMb7c0a2ce80504485a6f653a7110836f5.json"
送った内容をコンソールでなく、ブラウザ上で確認したい。
検索等の実装も可能なようだ。
先ずは、一覧を表示できないと話にならないので、サンプルを作成してみる。
PHPサンプル list_messages.php
<?php
require("/autoloadが置いてあるでぃてくとりをフルパスで指定/autoload.php" );
use Twilio\Rest\Client;
//定義
$sid = "アカウントのSID";
$token = "アカウントのAUTHTOKEN";
$twilio = new Client($sid, $token);
$messages = $twilio->messages
->read(array(), 20);//取り合えず20個まで
foreach ($messages as $record) {
print($record->to);//toで送信先の番号
print($record->body);//送信メッセージの内容
}
?>
送信結果を取りたいのであれば、
body
date_sent
status
to
body
で十分な気がする。
取得できる配列は以下のようだ。
JSON APIの記載があった。
"account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"api_version": "2010-04-01",
"body": "testing",
"date_created": "Fri, 24 May 2019 17:18:27 +0000",
"date_sent": "Fri, 24 May 2019 17:18:28 +0000",
"date_updated": "Fri, 24 May 2019 17:18:28 +0000",
"direction": "outbound-api",
"error_code": 30007,
"error_message": "Carrier violation",
"from": "+12019235161",
"messaging_service_sid": "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"num_media": "0",
"num_segments": "1",
"price": "-0.00750",
"price_unit": "USD",
"sid": "MMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"status": "sent",
"subresource_uris": {
"media": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMb7c0a2ce80504485a6f653a7110836f5/Media.json",
"feedback": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMb7c0a2ce80504485a6f653a7110836f5/Feedback.json"
},
"to": "+18182008801",
"uri": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/SMb7c0a2ce80504485a6f653a7110836f5.json"
2019/11/21
PHP SMS APIサービスのテスト Twilio 登録から送信テスト完了まで
SMS APIサービスの実装テストにあたりTwilioさんのトライアル版を試してみた。
アカウント取得
ブラウザがchromeでないと上手くいかなかった。
https://jp.twilio.com/try-twilio/kddi-web
2019年に業務提携があったようで、トライアルアカウント取得のページが
複数存在するようだ。ここで、取得できた。
性、名、メールアドレス、パスワード(14文字以上)
を入力してトライアルアカウント作成をすると
ログインする。
その後、2段階式の認証が入り、SMSが有効な電話番号を求めてくるので、
入力して送信すると、認証数列がSMSに届くので、
それを入力して登録完了。
PHPへの実装
composerにてtwilio-phpのライブラリを取得
任意のフォルダにて
$ composer require twilio/sdk
処理されて
Generating autoload files
サンプルプログラム sms_send.php
<?php
require("/autoloadが置いてあるでぃてくとりをフルパスで指定/autoload.php" );
use Twilio\Rest\Client;
$account_sid = 'ダッシュボードのアカウントSIDを記載';
$auth_token = 'ダッシュボードのAUTH TOKENを記載';
$twilio_number = '+120********';//取得したTwilioの電話番号テストは+120のみ許容
$client = new Client($account_sid, $auth_token);
$client->messages->create(
'+8190********',//090の場合日本は+81なので090が+8190となる。トライアル時は登録した電話番号のみ許容される。
[
'from' => $twilio_number,
'body' => 'SMS送信テスト'
]
);
?>
実行してみる
$ php sms_send.php
PHP Fatal error: Uncaught exception 'Twilio\Exceptions\RestException' with message '[HTTP 426] Unable to create record: Upgrade Required' in /var/www/html/vendor/twilio/sdk/Twilio/Version.php:85
Stack trace:
#0 /var/www/html/vendor/twilio/sdk/Twilio/Version.php(219): Twilio\Version->exception(Object(Twilio\Http\Response), 'Unable to creat...')
#1 /var/www/html/vendor/twilio/sdk/Twilio/Rest/Api/V2010/Account/MessageList.php(70): Twilio\Version->create('POST', '/Accounts/AC5c4...', Array, Array)
#2 /var/www/html/maildistributer/test/twilio_test.php(20): Twilio\Rest\Api\V2010\Account\MessageList->create('+8190********', Array)
#3 {main}
thrown in /var/www/html/vendor/twilio/sdk/Twilio/Version.php on line 85
ん?
426エラーが返ってきたので、
twilioの仕様を確認したところ、tls1.2を強要とのこと
phpinfoで知らべたところ稼働中のサーバは
opensslは1.2対応していたが、
cURLのNSSが/3.15でTLS1.2に対応していなかった。(3.283.19.1-6以降以上を要求らしい)
手っとり早い方法を探したところ、NSS/3.28以上のパッケージをインストールしてから
curlをアップデートするのが最速とのことだったので、
# yum install -y https://rpms.southbridge.ru/rhel7/stable/x86_64/southbridge-stable-release-1.0-el7.southbridge.noarch.rpm
# yum update curl
依存処理に結構時間がかかったが、何とか処理完了
# systemctl restart httpd.service
phpを再起動
これも、壊したか?と不安になる位 えらく時間がかかった・・・。
再度テスト
$ php sms_send.php
届いた!
登録から送信完了まで作業時間が約1時間半だった。
2018-9月にTLS1.3がリリースされたので、
近いうちにTLS1.3(openssl 1.1.1)にアップデートが必要になるものと
推測される。
なにやら攻撃を受ける可能性があるなどの情報もありもう少し様子見しようかな
と思っているが、そろそろ、PHPも7.2に引き上げが必要だろう。
動作確認とか大変だなぁ
アカウント取得
ブラウザがchromeでないと上手くいかなかった。
https://jp.twilio.com/try-twilio/kddi-web
2019年に業務提携があったようで、トライアルアカウント取得のページが
複数存在するようだ。ここで、取得できた。
性、名、メールアドレス、パスワード(14文字以上)
を入力してトライアルアカウント作成をすると
ログインする。
その後、2段階式の認証が入り、SMSが有効な電話番号を求めてくるので、
入力して送信すると、認証数列がSMSに届くので、
それを入力して登録完了。
PHPへの実装
composerにてtwilio-phpのライブラリを取得
任意のフォルダにて
$ composer require twilio/sdk
処理されて
Generating autoload files
サンプルプログラム sms_send.php
<?php
require("/autoloadが置いてあるでぃてくとりをフルパスで指定/autoload.php" );
use Twilio\Rest\Client;
$account_sid = 'ダッシュボードのアカウントSIDを記載';
$auth_token = 'ダッシュボードのAUTH TOKENを記載';
$twilio_number = '+120********';//取得したTwilioの電話番号テストは+120のみ許容
$client = new Client($account_sid, $auth_token);
$client->messages->create(
'+8190********',//090の場合日本は+81なので090が+8190となる。トライアル時は登録した電話番号のみ許容される。
[
'from' => $twilio_number,
'body' => 'SMS送信テスト'
]
);
?>
実行してみる
$ php sms_send.php
PHP Fatal error: Uncaught exception 'Twilio\Exceptions\RestException' with message '[HTTP 426] Unable to create record: Upgrade Required' in /var/www/html/vendor/twilio/sdk/Twilio/Version.php:85
Stack trace:
#0 /var/www/html/vendor/twilio/sdk/Twilio/Version.php(219): Twilio\Version->exception(Object(Twilio\Http\Response), 'Unable to creat...')
#1 /var/www/html/vendor/twilio/sdk/Twilio/Rest/Api/V2010/Account/MessageList.php(70): Twilio\Version->create('POST', '/Accounts/AC5c4...', Array, Array)
#2 /var/www/html/maildistributer/test/twilio_test.php(20): Twilio\Rest\Api\V2010\Account\MessageList->create('+8190********', Array)
#3 {main}
thrown in /var/www/html/vendor/twilio/sdk/Twilio/Version.php on line 85
ん?
426エラーが返ってきたので、
twilioの仕様を確認したところ、tls1.2を強要とのこと
phpinfoで知らべたところ稼働中のサーバは
opensslは1.2対応していたが、
cURLのNSSが/3.15でTLS1.2に対応していなかった。(
手っとり早い方法を探したところ、NSS/3.28以上のパッケージをインストールしてから
curlをアップデートするのが最速とのことだったので、
# yum install -y https://rpms.southbridge.ru/rhel7/stable/x86_64/southbridge-stable-release-1.0-el7.southbridge.noarch.rpm
# yum update curl
依存処理に結構時間がかかったが、何とか処理完了
# systemctl restart httpd.service
phpを再起動
これも、壊したか?と不安になる位 えらく時間がかかった・・・。
再度テスト
$ php sms_send.php
届いた!
登録から送信完了まで作業時間が約1時間半だった。
2018-9月にTLS1.3がリリースされたので、
近いうちにTLS1.3(openssl 1.1.1)にアップデートが必要になるものと
推測される。
なにやら攻撃を受ける可能性があるなどの情報もありもう少し様子見しようかな
と思っているが、そろそろ、PHPも7.2に引き上げが必要だろう。
動作確認とか大変だなぁ
2019/11/14
CSPRでの乱数生成 (暗号論的疑似乱数生成関数)
この度、セキュリティポリシーの高い
パスワードの自動生成が必要になり、
疑似乱数生成(PR)によりパスワードの生成をしようとしたころ、
安全な乱数でないと駄目です。とNGをもらった。
安全な乱数なんて量子コンピュータでもないと出来ないよ~~
とか、
エントロピーの無駄使いだ!!
とか言っても解決しないので、簡単な方向を模索してみる。
稼働サーバのPHPが5.4なので、当初randメソッドやmt_randメソッドを
SHA256で包括して、SEEDをハッシュ値で生成するから
疑似じゃないでしょ?で行こう思っていたが、
駄目っぽい雰囲気だったので、もう少し調べてみたところ、
PHP5.4でもライブラリを実装するとPHP7からの
CSPRNGである「random_int」メソッドが使えたので、オボエガキ。
ライブラリは、いつものGitHub様から取得
公式からもリンクされるという素晴らしさ!!
https://github.com/paragonie/random_compat
適宜配置
実際のソース
<?php
//ライブラリ読み込み
require_once "./php_lib/random.php";
// 利用可能な文字列の指定
$chars = 'ABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789';
// 変数初期化
$passwd = '';
// ランダムに文字列を生成(12文字)
for ($i = 0; $i < 12; $i++) {
$passwd .= $chars[random_int(0, 35)];//$charsの文字数を修正時は、必ず揃え、35を修正する。
}
//無限ループ注意!! 数字のみ英大文字のみを許容しない
while ( (preg_match('/^[0-9]+$/', $passwd) || preg_match('/^[A-Z]+$/', $passwd)) ){
$passwd = '';//一旦 $passwd をまっさらにする
for ($i = 0; $i < 12; $i++) {
$passwd .= $chars[random_int(0, 35)];//条件充足までループ
}
}
//文字列表示
echo $passwd;
?>
こんな感じ
やっぱり、困ったら一人で頑張らないで、公式サイトのメソッドを見るべきだ
と感じた。
パスワードの自動生成が必要になり、
疑似乱数生成(PR)によりパスワードの生成をしようとしたころ、
安全な乱数でないと駄目です。とNGをもらった。
安全な乱数なんて量子コンピュータでもないと出来ないよ~~
とか、
エントロピーの無駄使いだ!!
とか言っても解決しないので、簡単な方向を模索してみる。
稼働サーバのPHPが5.4なので、当初randメソッドやmt_randメソッドを
SHA256で包括して、SEEDをハッシュ値で生成するから
疑似じゃないでしょ?で行こう思っていたが、
駄目っぽい雰囲気だったので、もう少し調べてみたところ、
PHP5.4でもライブラリを実装するとPHP7からの
CSPRNGである「random_int」メソッドが使えたので、オボエガキ。
ライブラリは、いつものGitHub様から取得
公式からもリンクされるという素晴らしさ!!
https://github.com/paragonie/random_compat
適宜配置
実際のソース
<?php
//ライブラリ読み込み
require_once "./php_lib/random.php";
// 利用可能な文字列の指定
$chars = 'ABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789';
// 変数初期化
$passwd = '';
// ランダムに文字列を生成(12文字)
for ($i = 0; $i < 12; $i++) {
$passwd .= $chars[random_int(0, 35)];//$charsの文字数を修正時は、必ず揃え、35を修正する。
}
//無限ループ注意!! 数字のみ英大文字のみを許容しない
while ( (preg_match('/^[0-9]+$/', $passwd) || preg_match('/^[A-Z]+$/', $passwd)) ){
$passwd = '';//一旦 $passwd をまっさらにする
for ($i = 0; $i < 12; $i++) {
$passwd .= $chars[random_int(0, 35)];//条件充足までループ
}
}
//文字列表示
echo $passwd;
?>
こんな感じ
やっぱり、困ったら一人で頑張らないで、公式サイトのメソッドを見るべきだ
と感じた。
2019/08/18
apache SELinuxがEnforcingの時、特定のフォルダで読み書きを可能にしたい。
安否確認を自主作成している際、PHPでファイルを読み書きできない状況になったので
調べたところ、コンテキストをいじるには
policycoreutils-python がインストールされていることが条件
yum list policycoreutils-python で調べてなければ、インストールのこと
/var/www/html/test 配下を許容するには
# semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/test/(/.*)?"
# restorecon -R /var/www/html/test/
でSELinuxの例外を追加する必要がある。
ls -alFZ /var/www/html/test
で確認できる。
嵌ったパターン
既にファイルを生成していて、ディレクトリの属性を
httpd_sys_rw_content_tに変えてrestoreconをしても、
既にあるファイルの属性は変わらない 仕様である。
これが分からず、さんざん悩んだ挙句、
ls -alFZ /var/www/html/対象がいるディレクトリ/
で調べたところ、案の定 rwの属性になっていなかった・・・。
個別に属性付与か、いったん削除して再度scp等でアップするなりが必要。
調べたところ、コンテキストをいじるには
policycoreutils-python がインストールされていることが条件
yum list policycoreutils-python で調べてなければ、インストールのこと
/var/www/html/test 配下を許容するには
# semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/test/(/.*)?"
# restorecon -R /var/www/html/test/
でSELinuxの例外を追加する必要がある。
ls -alFZ /var/www/html/test
で確認できる。
嵌ったパターン
既にファイルを生成していて、ディレクトリの属性を
httpd_sys_rw_content_tに変えてrestoreconをしても、
既にあるファイルの属性は変わらない 仕様である。
これが分からず、さんざん悩んだ挙句、
ls -alFZ /var/www/html/対象がいるディレクトリ/
で調べたところ、案の定 rwの属性になっていなかった・・・。
個別に属性付与か、いったん削除して再度scp等でアップするなりが必要。
2019/07/01
シェルスクリプトが動かない場合
プログラムを書いて試験して
予定通りに動いたので、cronで自動化をしようと
シェルスクリプトを記載したが、
うまく動かなかった。
logを取ると、プログラムが無いといわれる。
症状を調べると、改行がLFでなくCRLFになっていた。
最近エディタにatomを使っているのだが、
Windowsでatomを使うとデフォルトではCRLFを改行コードに
しているとのことだった。
atomの設定で、
Core Packages ⇒ line-ending-selector に
LF CRLF OS Default があるので、これを
LFにしてあげれば良い。
30分くらい嵌ってしまった。
予定通りに動いたので、cronで自動化をしようと
シェルスクリプトを記載したが、
うまく動かなかった。
logを取ると、プログラムが無いといわれる。
症状を調べると、改行がLFでなくCRLFになっていた。
最近エディタにatomを使っているのだが、
Windowsでatomを使うとデフォルトではCRLFを改行コードに
しているとのことだった。
atomの設定で、
Core Packages ⇒ line-ending-selector に
LF CRLF OS Default があるので、これを
LFにしてあげれば良い。
30分くらい嵌ってしまった。
2019/06/17
PDF解像度変更と一部のページ除去 gsコマンド(GhostScript)
表題の操作をスキャン後のファイルに自動処理で行いたい。
不要なページの削除方法
◆pdftkコマンドを使う
今回はスキャナの為の台紙である一枚目を取り除きたいので、
$ pdftk origin.pdf cat 2-end output modify.pdf
となる。
2枚目だけを取り除きたい場合は、
$ pdftk origin.pdf cat 1 3-end output modify.pdf
オプションの詳細
解像度の変更
◆gsコマンドを使う
オプションが非常に長いが、中途半端に記載すると
処理に時間がかかったので、ファイルサイズ軽減に係るところは全部表記した。
$ gs -q -sOutputFile="/home/user0463/out.pdf" -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER -dQUIET -dCompatibilityLevel=1.4 -sColorConversionStrategy=GRAY -dProcessColorModel=/DeviceGray -dGrayImageDownsampleType=/Bicubic -dGrayImageResolution=72 -dMonoImageDownsampleType=/Bicubic -dMonoImageResolution=72 -dColorImageDownsampleType=/Bicubic -dColorImageResolution=72 -dEmbedAllFonts=false -dSubsetFonts=false -dPDFSETTINGS=/printer /home/user0463/moto.pdf
解説
-q 実行時にメッセージを出力しない。
-sOutputFile="出力先ファイル記述"
-sDEVICE=pdfwrite pdf以外の設定 gs -hで確認できる。
-dNOPAUSE ページごとに処理に一時停止をさせない。(これを書かないと遅くなる)
-dBATCH 一連処理させる。
-dSAFER deletefileとrenamefileオペレータを無効
-dQUIET 標準出力への情報を表示しない。
-dCompatibilityLevel=1.4 1.3~1.6まで定義可
-sColorConversionStrategy=GRAY GRAY,CMYK,RGBを指定
-dProcessColorModel=/DeviceGray DeviceGray,DeviceCMYK,DeviceRGBを指定
-dGrayImageDownsampleType=/Bicubic /Subsample, /Average, /Bicubicを指定
-dGrayImageResolution=72 解像度を指定 dpiを指定デフォルト72
-dMonoImageDownsampleType=/Bicubic /Subsample, /Average, /Bicubicを指定
-dMonoImageResolution=72 解像度を指定 dpiを指定デフォルト72
-dColorImageDownsampleType=/Bicubic /Subsample, /Average, /Bicubicを指定
-dColorImageResolution=72 解像度を指定 dpiを指定デフォルト72
-dEmbedAllFonts=false フォントを埋め込むか? true,falseを指定
-dSubsetFonts=false 標準フォントを埋め込むか? true,falseを指定
-dPDFSETTINGS=/printer /screen, /ebook, /printer, /prepress, /defaultを指定
PDFSETTINGS は 低解像度← screen,ebook,printer,prepress →高解像度
defaultは元データを参照するようである。
あとは、シェルスクリプトに記載して、cron や inotifywait
で 自動処理させれば良い。
gsコマンドは端折って記載するより全部書いたほうが早いと云うのが面白い。
不要なページの削除方法
◆pdftkコマンドを使う
今回はスキャナの為の台紙である一枚目を取り除きたいので、
$ pdftk origin.pdf cat 2-end output modify.pdf
となる。
2枚目だけを取り除きたい場合は、
$ pdftk origin.pdf cat 1 3-end output modify.pdf
オプションの詳細
解像度の変更
◆gsコマンドを使う
オプションが非常に長いが、中途半端に記載すると
処理に時間がかかったので、ファイルサイズ軽減に係るところは全部表記した。
$ gs -q -sOutputFile="/home/user0463/out.pdf" -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER -dQUIET -dCompatibilityLevel=1.4 -sColorConversionStrategy=GRAY -dProcessColorModel=/DeviceGray -dGrayImageDownsampleType=/Bicubic -dGrayImageResolution=72 -dMonoImageDownsampleType=/Bicubic -dMonoImageResolution=72 -dColorImageDownsampleType=/Bicubic -dColorImageResolution=72 -dEmbedAllFonts=false -dSubsetFonts=false -dPDFSETTINGS=/printer /home/user0463/moto.pdf
解説
-q 実行時にメッセージを出力しない。
-sOutputFile="出力先ファイル記述"
-sDEVICE=pdfwrite pdf以外の設定 gs -hで確認できる。
-dNOPAUSE ページごとに処理に一時停止をさせない。(これを書かないと遅くなる)
-dBATCH 一連処理させる。
-dSAFER deletefileとrenamefileオペレータを無効
-dQUIET 標準出力への情報を表示しない。
-dCompatibilityLevel=1.4 1.3~1.6まで定義可
-sColorConversionStrategy=GRAY GRAY,CMYK,RGBを指定
-dProcessColorModel=/DeviceGray DeviceGray,DeviceCMYK,DeviceRGBを指定
-dGrayImageDownsampleType=/Bicubic /Subsample, /Average, /Bicubicを指定
-dGrayImageResolution=72 解像度を指定 dpiを指定デフォルト72
-dMonoImageDownsampleType=/Bicubic /Subsample, /Average, /Bicubicを指定
-dMonoImageResolution=72 解像度を指定 dpiを指定デフォルト72
-dColorImageDownsampleType=/Bicubic /Subsample, /Average, /Bicubicを指定
-dColorImageResolution=72 解像度を指定 dpiを指定デフォルト72
-dEmbedAllFonts=false フォントを埋め込むか? true,falseを指定
-dSubsetFonts=false 標準フォントを埋め込むか? true,falseを指定
-dPDFSETTINGS=/printer /screen, /ebook, /printer, /prepress, /defaultを指定
PDFSETTINGS は 低解像度← screen,ebook,printer,prepress →高解像度
defaultは元データを参照するようである。
あとは、シェルスクリプトに記載して、cron や inotifywait
で 自動処理させれば良い。
gsコマンドは端折って記載するより全部書いたほうが早いと云うのが面白い。
2019/05/17
raspberrypi3のカメラを使ってメール応答型のスクリプト node.jsを活用
やりたいこと
メールを受信すると、raspberrypi3のカメラで撮影し、
メールに添付して指定のメールアドレスに送信するスクリプト。
子供や愛犬の見守りなど目的は同じになるが、
玄関の施錠をしたか?を最寄りの駅で気になった場合に
万が一の為に戻りたくないので作成。
玄関が開き戸だったら、もっといろいろな仕掛けができたのだが・・・。
補足
メール部分は自分でサーバ建てるのが大変なので、
Gmailを利用し、node.jsを使ってメールの送信を常に監視し、
監視中にメールが来るとそれをトリガーにして
カメラで撮影、メールを送信する。
node.jsは『非同期スクリプト』であるため、
fs等を使う場合は、同期させた処理を行う必要がある。
ここで、嵌ってしまった・・・。
カメラの処理に時間がかかり、ファイルが生成される前に
メール送信のためのファイル加工が動作してしまい、
エラーが返って来てしまうので、
別々に動作確認が終わったら、promise 等で同期処理をさせる。
前提
・raspberry-pi3のカメラモジュールを認識済み
・Gmailのアカウント取得、安全性の低いアプリの許可」を有効にしてある。
・nodeが動かせること
◆◆◆成果物◆◆◆
'use strict';
var inbox = require('inbox');
//var nodemailer = require('nodemailer');
//var iconv = require('iconv');
//var conv = new iconv.Iconv("UTF-8", "UTF-8");
const simpleParser = require('mailparser').simpleParser;
var client = inbox.createConnection(false, 'imap.gmail.com', {
secureConnection: true
,auth: {
user:'Gmailアカウント@gmail.com'
,pass:'Gmailパスワード'
}
});
client.on('connect', function() {
console.log('connected');
client.openMailbox('INBOX', function(error) {
if (error) throw error;
});
});
client.connect();
client.on("new", function(message) {
console.log('日時:' + message.date);
console.log('送信者:' + message.from.name + '-' + message.from.address);
console.log('タイトル:' + message.title);
var stream = client.createMessageStream(message.UID);
simpleParser(stream)
.then(mail=> {
console.log('本文(HTMLテキスト):' + mail.textAsHtml);
})
.catch(err=> {
console.log(err);
});
//node.jsはデフォルトで非同期処理を行うため、
//asyncを用いてカメラがsnap.jpgを生成するのを待ち
//Gmailの送信(snap.jpgの添付)、snap.jpgの削除を行っている
//pi-cameraでは上書き保存ができないため、メール送信後に削除しておく。
const async = require('async'); //同期処理のためasync呼び出す
async.series([
function(callback) {
console.log('カメラの処理開始');
//pi-camera の動作ここから
const PiCamera = require('pi-camera');
const myCamera = new PiCamera({
mode: 'photo',
output: `${ __dirname }/snap.jpg`,
width: 640,
height: 480,
nopreview: true,
});
myCamera.snap()
.then((result) => {
// Your picture was captured
})
.catch((error) => {
// Handle your error
});
//pi-camera の動作ここまで
//安全をみて7秒ディレイ
setTimeout(callback, 7000);
}, function(callback) {
console.log('メールの返信開始');
//Gmailで送信ここから
var nodemailer = require('nodemailer')
var fs = require('fs');
// メッセージ内容
var message = {
from : '送信元@gmail.com',
to : '送信先@gmail.com',
subject : 'Reply to request',
text : 'Reply to request,Picture of the Pi-Camera !',
attachments : [{
filename: 'snap.jpg',
content: fs.readFileSync('snap.jpg') //カメラのデータ生成待ち
}]
};
var smtpConfig = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // SSL
auth: {
user : 'Gmailアカウント@gmail.com',
pass : 'Gmailパスワード'
}
};
var transporter = nodemailer.createTransport(smtpConfig);
transporter.sendMail(message, function(err, response) {
console.log(err || response);
});
//ファイル削除
try {
fs.unlinkSync('snap.jpg');
console.log('snap.jpgを削除しました。');
} catch (error) {
throw error;
}
//Gmailで送信ここまで
setTimeout(callback, 1000);
}, function(callback) {
return console.log('処理終了');
}
], function(err, results) {
if (err) {
return console.log('err[' + err + ']');
}
});
}); // client.connect() を閉じる。
コマンド自体はプロンプト状態なので停止はcrtl+Zにて行う。
sshで操作する場合は、forever等で動かさないと、ターミナル閉じた瞬間に
Killされるので注意が必要。
◆◆動作部分解説◆◆
◆メール受信トリガー部分◆
node.jsのパッケージインストール
$ npm install inbox
$ npm install mailparser
まんま、@hideito2000様の掲載内容を使わせていただいた。
//ソース
client.on("new", function(message) {
console.log('日時:' + message.date);
console.log('送信者:' + message.from.name + '-' + message.from.address);
console.log('タイトル:' + message.title);
var stream = client.createMessageStream(message.UID);
simpleParser(stream)
.then(mail=> {
console.log('本文(HTMLテキスト):' + mail.textAsHtml);
})
.catch(err=> {
console.log(err);
});
//この部分にカメラ処理とメール送信を組み込む
});
//ソースここまで
◆pi-cameraのインストール◆
メールを受信すると、raspberrypi3のカメラで撮影し、
メールに添付して指定のメールアドレスに送信するスクリプト。
子供や愛犬の見守りなど目的は同じになるが、
玄関の施錠をしたか?を最寄りの駅で気になった場合に
万が一の為に戻りたくないので作成。
玄関が開き戸だったら、もっといろいろな仕掛けができたのだが・・・。
補足
メール部分は自分でサーバ建てるのが大変なので、
Gmailを利用し、node.jsを使ってメールの送信を常に監視し、
監視中にメールが来るとそれをトリガーにして
カメラで撮影、メールを送信する。
node.jsは『非同期スクリプト』であるため、
fs等を使う場合は、同期させた処理を行う必要がある。
ここで、嵌ってしまった・・・。
カメラの処理に時間がかかり、ファイルが生成される前に
メール送信のためのファイル加工が動作してしまい、
エラーが返って来てしまうので、
別々に動作確認が終わったら、promise 等で同期処理をさせる。
前提
・raspberry-pi3のカメラモジュールを認識済み
・Gmailのアカウント取得、安全性の低いアプリの許可」を有効にしてある。
・nodeが動かせること
◆◆◆成果物◆◆◆
'use strict';
var inbox = require('inbox');
//var nodemailer = require('nodemailer');
//var iconv = require('iconv');
//var conv = new iconv.Iconv("UTF-8", "UTF-8");
const simpleParser = require('mailparser').simpleParser;
var client = inbox.createConnection(false, 'imap.gmail.com', {
secureConnection: true
,auth: {
user:'Gmailアカウント@gmail.com'
,pass:'Gmailパスワード'
}
});
client.on('connect', function() {
console.log('connected');
client.openMailbox('INBOX', function(error) {
if (error) throw error;
});
});
client.connect();
client.on("new", function(message) {
console.log('日時:' + message.date);
console.log('送信者:' + message.from.name + '-' + message.from.address);
console.log('タイトル:' + message.title);
var stream = client.createMessageStream(message.UID);
simpleParser(stream)
.then(mail=> {
console.log('本文(HTMLテキスト):' + mail.textAsHtml);
})
.catch(err=> {
console.log(err);
});
//node.jsはデフォルトで非同期処理を行うため、
//asyncを用いてカメラがsnap.jpgを生成するのを待ち
//Gmailの送信(snap.jpgの添付)、snap.jpgの削除を行っている
//pi-cameraでは上書き保存ができないため、メール送信後に削除しておく。
const async = require('async'); //同期処理のためasync呼び出す
async.series([
function(callback) {
console.log('カメラの処理開始');
//pi-camera の動作ここから
const PiCamera = require('pi-camera');
const myCamera = new PiCamera({
mode: 'photo',
output: `${ __dirname }/snap.jpg`,
width: 640,
height: 480,
nopreview: true,
});
myCamera.snap()
.then((result) => {
// Your picture was captured
})
.catch((error) => {
// Handle your error
});
//pi-camera の動作ここまで
//安全をみて7秒ディレイ
setTimeout(callback, 7000);
}, function(callback) {
console.log('メールの返信開始');
//Gmailで送信ここから
var nodemailer = require('nodemailer')
var fs = require('fs');
// メッセージ内容
var message = {
from : '送信元@gmail.com',
to : '送信先@gmail.com',
subject : 'Reply to request',
text : 'Reply to request,Picture of the Pi-Camera !',
attachments : [{
filename: 'snap.jpg',
content: fs.readFileSync('snap.jpg') //カメラのデータ生成待ち
}]
};
var smtpConfig = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // SSL
auth: {
user : 'Gmailアカウント@gmail.com',
pass : 'Gmailパスワード'
}
};
var transporter = nodemailer.createTransport(smtpConfig);
transporter.sendMail(message, function(err, response) {
console.log(err || response);
});
//ファイル削除
try {
fs.unlinkSync('snap.jpg');
console.log('snap.jpgを削除しました。');
} catch (error) {
throw error;
}
//Gmailで送信ここまで
setTimeout(callback, 1000);
}, function(callback) {
return console.log('処理終了');
}
], function(err, results) {
if (err) {
return console.log('err[' + err + ']');
}
});
}); // client.connect() を閉じる。
コマンド自体はプロンプト状態なので停止はcrtl+Zにて行う。
sshで操作する場合は、forever等で動かさないと、ターミナル閉じた瞬間に
Killされるので注意が必要。
◆◆動作部分解説◆◆
◆メール受信トリガー部分◆
node.jsのパッケージインストール
$ npm install inbox
$ npm install mailparser
まんま、@hideito2000様の掲載内容を使わせていただいた。
//ソース
client.on("new", function(message) {
console.log('日時:' + message.date);
console.log('送信者:' + message.from.name + '-' + message.from.address);
console.log('タイトル:' + message.title);
var stream = client.createMessageStream(message.UID);
simpleParser(stream)
.then(mail=> {
console.log('本文(HTMLテキスト):' + mail.textAsHtml);
})
.catch(err=> {
console.log(err);
});
//この部分にカメラ処理とメール送信を組み込む
});
//ソースここまで
◆pi-cameraのインストール◆
$ npm install pi-camera
作成者のページのサンプルをそのまま使う
//ソース
const PiCamera = require('pi-camera');
const myCamera = new PiCamera({
mode: 'photo',
output: `${ __dirname }/snap.jpg`,
width: 640,
height: 480,
nopreview: true,
});
myCamera.snap()
.then((result) => {
// Your picture was captured
})
.catch((error) => {
// Handle your error
});
//ソースここまで
◆nodemailer でメールを送信させるので、インストール◆ $ npm i -D nodemailer
ソースは皆さまの内容を参照させていただいた。
ありがとうございます。
//ソース
var mailer = require('nodemailer');
mailer.SMTP = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // SSL
auth: {
user : 'Gmailのid@gmail.com,
pass : 'Gmailのパスワード'
}
};
fs.readFile("./snap.jpg", function (err, data) {
mailer.send_mail({
sender: '送信元@gmail.com',
to: '送信先@gmail.com',
subject: 'snapshot-Ent!',
body: 'Snapshot of the Entrance !',
attachments: [{'filename': 'snap.jpg', 'content': picture}]
}), function(err, success) {
if (err) {
// Handle error
}
}
});
//ソースここまで
◆ファイルの削除◆
try {
fs.unlinkSync('snap.jpg');
console.log('snap.jpgを削除しました。');
} catch (error) {
throw error;
}
fsは非同期だが、同じコマンドであれば記載の順に動くようだ。
駄目な場合は、 async の回数を増やせば良い。
◆同期処理◆
async.series([
function(callback) {
console.log('処理開始');
このcallback間にメソッドを記載
setTimeout(callback, 1000);
}, function(callback) { console.log('処理2開始');
setTimeout(callback, 1000);
});
}, function(callback) {
return console.log('処理終了');
}
],
期待した動きができたので、満足。
2019/05/08
CentOS(RedHat系) rootパスワードが分からない際の対策
CentOS7以降、レスキューモード(旧シングルユーザモード)、エマージェンシーモード
ともにrootパスワードを要求される。
しかし、管理者が不慮のアクシデントで対応できない状況となった際に、
どうしてもrootパスワードが必要なことが生じることがある。
今回、どうにもならない状況になってしまったため、操作した。
Procedure 25.6. Resetting the Root Password Using rd.break
いくつか手順を発見したので、残しておく
1.GRUB(ブートするOSを選択する画面)で「e」を押す。
2.rhgb quiet LANG*** を消して、systemd.debug の後ろにrw init=/bin/bashを加える。
3.Ctrl+x でboot開始
としてパスワードを強制上書きできるが、リラベリングに、えらく時間がかかった。
以下の手順でも再設定はできたので、間違いではないと思われる。
mozcの設定がうまくいっていなかったのかもしれないが、自分で構築していないので
どうにもならなかった・・・。
1.GRUB(ブートするOSを選択する画面)で「e」を押す。
2.rhgb quiet を消して、 rd.break enforcing=0 を書き加える。
(linux16の行と書いてあるが、同じ位置で問題なかった。)
※ enforcing=0はSELinuxの制御をオミットする意味とのこと。
3.Ctrl+x でboot開始
4.switch_root:/# mount -o remount,rw /sysroot を入力しエンター
※ファイルシステムを書き換え可能にする。
5.switch_root:/# chroot /sysroot を入力しエンター
※ファイルシステムをroot管理にする
6.sh-4.2# passwd でrootパスワードを設定する。
7.sh-4.2# exit を入力しエンター
8.switch_root:/# exit を入力しエンター
9.再起動し通常のユーザでログイン後ターミナルで新しいパスワードでroot化する。
10.# restorecon -v /etc/shadow を入力しエンター
※rd.breakで操作したrootパスワード格納のshadow定義をデフォルトにする。
※上記をしないと、再起動時にパスワードを誰も読めずログインできなくなる。
11.# setenforce 1 を入力しエンター
※SELinuxを有効にしておく。
以降は、再起動しても問題ない。
一般ユーザのパスワードはそのままで、rootは新しいパスワードが有効になる。
LUKS(Linux Unified Key Setup)を利用している場合は、
上記の操作を開始する時点でパスワードやファイルによる解除が必要となるそうだが、
LUKS は、膨大な (RHEL 7 では 512 文字) 平文テキストのパスフレーズと、非常に大きな (RHEL 7 では 8 MiB) のキーファイルを許可しているそうなので、
導入には、配慮が必要と改めて感じた。
ともにrootパスワードを要求される。
しかし、管理者が不慮のアクシデントで対応できない状況となった際に、
どうしてもrootパスワードが必要なことが生じることがある。
今回、どうにもならない状況になってしまったため、操作した。
Procedure 25.6. Resetting the Root Password Using rd.break
いくつか手順を発見したので、残しておく
1.GRUB(ブートするOSを選択する画面)で「e」を押す。
2.rhgb quiet LANG*** を消して、systemd.debug の後ろにrw init=/bin/bashを加える。
3.Ctrl+x でboot開始
4.bash-4.2# touch /.autorelabel でSELinuxを有効にする
5.bash-4.2# passwd でrootパスワードを設定する。
6.bash-4.2# exec /sbin/init 通常モードへ移行する。
6.bash-4.2# exec /sbin/init 通常モードへ移行する。
考察
switch_root:/# exit の再起動がうまくないようだ。
switch_root:/# exit の再起動がうまくないようだ。
rd.break enforcing=0 と宣言しなくとも、SELinuxは無効化される様子。
passwd <管理ユーザ>としてパスワードを強制上書きできるが、リラベリングに、えらく時間がかかった。
以下の手順でも再設定はできたので、間違いではないと思われる。
mozcの設定がうまくいっていなかったのかもしれないが、自分で構築していないので
どうにもならなかった・・・。
1.GRUB(ブートするOSを選択する画面)で「e」を押す。
2.rhgb quiet を消して、 rd.break enforcing=0 を書き加える。
(linux16の行と書いてあるが、同じ位置で問題なかった。)
※ enforcing=0はSELinuxの制御をオミットする意味とのこと。
3.Ctrl+x でboot開始
4.switch_root:/# mount -o remount,rw /sysroot を入力しエンター
※ファイルシステムを書き換え可能にする。
5.switch_root:/# chroot /sysroot を入力しエンター
※ファイルシステムをroot管理にする
6.sh-4.2# passwd でrootパスワードを設定する。
7.sh-4.2# exit を入力しエンター
8.switch_root:/# exit を入力しエンター
9.再起動し通常のユーザでログイン後ターミナルで新しいパスワードでroot化する。
10.# restorecon -v /etc/shadow を入力しエンター
※rd.breakで操作したrootパスワード格納のshadow定義をデフォルトにする。
※上記をしないと、再起動時にパスワードを誰も読めずログインできなくなる。
11.# setenforce 1 を入力しエンター
※SELinuxを有効にしておく。
以降は、再起動しても問題ない。
一般ユーザのパスワードはそのままで、rootは新しいパスワードが有効になる。
LUKS(Linux Unified Key Setup)を利用している場合は、
上記の操作を開始する時点でパスワードやファイルによる解除が必要となるそうだが、
LUKS は、膨大な (RHEL 7 では 512 文字) 平文テキストのパスフレーズと、非常に大きな (RHEL 7 では 8 MiB) のキーファイルを許可しているそうなので、
導入には、配慮が必要と改めて感じた。
2019/01/17
NTT αNXⅡ v4.00 webシステム設定 のjava
NTT αNXⅡ v4.00 webシステム設定
会社がNTTのネットコミュニティシステムαNXⅡを利用しているのだが、
ブラウザ上で電話帳や電話機の名称等の設定ができる。
javaのバージョンによっては動作しないので、
少し調べてみたので、オボエガキ
少し古い、αNX typeLのマニュアルの200ページくらいに
「次世代のJava Plug-inを有効にする 」設定を無効にする必要があると書いてある。
ところが、Oracleで確認すると、
末尾に
とあり、 Java Pluginが利用できなくなっている。
あわせて、次世代のJava Plug-inを有効無効の制御ができなくなったようだ。
一度、古めの6をインストールして、Webシステム設定を動作できる状況にしてから、
JDK8等をインストールすると両立できた。
会社がNTTのネットコミュニティシステムαNXⅡを利用しているのだが、
ブラウザ上で電話帳や電話機の名称等の設定ができる。
javaのバージョンによっては動作しないので、
少し調べてみたので、オボエガキ
少し古い、αNX typeLのマニュアルの200ページくらいに
「次世代のJava Plug-inを有効にする 」設定を無効にする必要があると書いてある。
ところが、Oracleで確認すると、
Changes in Java SE 6u171 b31
Please note that fixes from prior BPR (6u161 b32) are included in this version.末尾に
Known Issues
deploy
Windows - There is a non-functional Java icon in control panel after installing 6u171 or 7u161
Deployment features in 6u171 and 7u161 have been removed. Installing a
version of the JRE that has deployment technologies support AFTER
having installed the current JRE will cause the Windows Control Panel to
display a non-functional Java Control panel icon.
JDK-8185373 (not public)
とあり、 Java Pluginが利用できなくなっている。
あわせて、次世代のJava Plug-inを有効無効の制御ができなくなったようだ。
一度、古めの6をインストールして、Webシステム設定を動作できる状況にしてから、
JDK8等をインストールすると両立できた。
2018/11/16
postfix メールキューのエラー 大量のメールを誤送信してしまい、遅延がひどい場合の措置
サーバ内のメール転送プログラム実行中にエラーが生じた際に、
エラー警告メールを送信し、エスケープする処理を盛り込んだのだが、
エスケープの記述をしくじり、エンドレス送信が生じてしまった。
2時間程経過した際に以上に気づき、即座にプログラムは停止させ、/var/spool/mail/配下の指定アドレスの中身は処理したのだが、
postfixのキューに大量の残骸が残ってしまった。
遅延の遅延の遅延を繰り返し、頑張って送ってきてはいるが、
1万数千単位のメールが何時までも送られてくるため、当該ユーザの
通常のメールにも遅延が生じてしまっている状態。
そこで、postfixのキューを何とかして、通常の状態に戻してみた。
幸い、該当のメールのサイズが2kBと非常に小さいもので、他の遅延が殆どなかったので、
さらっと内容を確認して、該当のメールだけを削除する。
qmgr キューマネージャーにてメッセージはキューを通過する。
格納されている先
既に、 /var/spool/mail/配下の指定アドレスの中身は処理済みの場合、
問題は、
これで、正常な状態に戻っている(はず)
小生の環境では、これで正常に配信されるようになった。
この方の解説が非常にわかりやすかった。ありがとうございます。
kazupon.com様
エラー警告メールを送信し、エスケープする処理を盛り込んだのだが、
エスケープの記述をしくじり、エンドレス送信が生じてしまった。
2時間程経過した際に以上に気づき、即座にプログラムは停止させ、/var/spool/mail/配下の指定アドレスの中身は処理したのだが、
postfixのキューに大量の残骸が残ってしまった。
遅延の遅延の遅延を繰り返し、頑張って送ってきてはいるが、
1万数千単位のメールが何時までも送られてくるため、当該ユーザの
通常のメールにも遅延が生じてしまっている状態。
そこで、postfixのキューを何とかして、通常の状態に戻してみた。
幸い、該当のメールのサイズが2kBと非常に小さいもので、他の遅延が殆どなかったので、
さらっと内容を確認して、該当のメールだけを削除する。
qmgr キューマネージャーにてメッセージはキューを通過する。
格納されている先
/var/spool/postfix/incoming リモート受信した最新のメッセージ格納 /var/spool/postfix/active 処理中メッセージ /var/spool/postfix/bounce 配信できなかったメールID毎のログ /var/spool/postfix/corrupt postfixの形式に則ってないメッセージ格納
/var/spool/postfix/deferred 配信不能だがリトライする。 /var/spool/postfix/hold 無期限保存する際利用 /var/spool/postfix/defer 一時的に配送不能なメッセージリトライする。
既に、 /var/spool/mail/配下の指定アドレスの中身は処理済みの場合、
問題は、
deferredとdeferに残骸が有ると、何度もリトライを繰り返してしまう点にある。
そこで、 defer配下をfindしてファイルサイズ2kのものをxargsで渡して削除
# find /var/spool/postfix/defer/ -size 2k | xargs rm -rf
マジで全部消えるので、ほんとにそのサイズで大丈夫か?を確認すること
※ -execだとファイルの数だけコマンドを投げる仕様のようで、時間がかかってしまう。
今回1万数千回の実行は xargs の方が向いている。
同様に、deferredでも行う。
# find /var/spool/postfix/deferred/ -size 2k | xargs rm -rf
その後、 残った問題の無いものを強制送信。
# postfix flush
最後にキューをきれいにする
# postsuper -d ALL
キューがきれいになったか確認
# postqueue -p Mail queue is empty
これで、正常な状態に戻っている(はず)
小生の環境では、これで正常に配信されるようになった。
この方の解説が非常にわかりやすかった。ありがとうございます。
kazupon.com様
2018/11/06
SUBARU XV DBA-GT7 CADデータ
現行のSUBARU(スバル)XVのCADデータが見つからず・・・。
平面図が欲しかったが、SUBARUさんも3面図のみの掲載・・・。
平面図を作成するために、結局全部書いてしまった・・・。
誰トク?なCADデータだが、約2,500台/月の販売実績だし、
ちょっとリコール出てるけど、車に問題はないし、
オーナー様にご利用頂ければと思い、公開。
FC2に「SUBARU_XV_DBA_GT7.zip」でアップロードしてます。(JW_CAD)
SUBARU(スバル)XV 2017年5月~ DBA-GT7型 2.0i-Sアイサイト
平面図が欲しかったが、SUBARUさんも3面図のみの掲載・・・。
平面図を作成するために、結局全部書いてしまった・・・。
誰トク?なCADデータだが、約2,500台/月の販売実績だし、
ちょっとリコール出てるけど、車に問題はないし、
オーナー様にご利用頂ければと思い、公開。
FC2に「SUBARU_XV_DBA_GT7.zip」でアップロードしてます。(JW_CAD)
SUBARU(スバル)XV 2017年5月~ DBA-GT7型 2.0i-Sアイサイト
PHP 日本語メールの環境依存文字 文字化け対策
先般、SPF問題の解決の為、PHPMAILERにてメール送信を行うように仕様変更したが、
まだ、JIS-2022-JPの7bit問題が解決していない。
問題点としては、さまざまな環境のメールサーバやOSがアンドロイドでないフィーチャーフォン
(所謂ガラケー)では、8bitを許容していないようだが、ほとんどの動作環境下でUTF-8が
利用できるようになってきている。
と思われる。
そこで、今までは、JIS-2022-JP(7bit)の制約を受け、環境依存文字や半角カナ
が文字化けを起こす環境で運用を行っていたが、さすがに、ガラケーのみで
運用をするユーザが現役社会人である可能性は、万が一くらいでいいだろうと判断した。
前段が長くなってしまったが、
UTF-8でPHPMAILERのインスタンスを生成する際の記載をオボエガキ
前回との変更箇所をオレンジ表記
$mail->AddAttachment('./hogefile.pdf');日本語は極力使わない!!
大分後になって
$mail->CharSet = "UTF-8";
$mail->Encoding = "base64";
と宣言をするよりも、
$mail->CharSet = "iso-2022-jp";
$mail->Encoding = "7bit";
として、愚直に
mb_encode_mimeheader(mb_convert_encoding($fromname,"JIS","UTF-8"))
としたほうが、エンコード率が高いことが分かった。
まだ、JIS-2022-JPの7bit問題が解決していない。
問題点としては、さまざまな環境のメールサーバやOSがアンドロイドでないフィーチャーフォン
(所謂ガラケー)では、8bitを許容していないようだが、ほとんどの動作環境下でUTF-8が
利用できるようになってきている。
と思われる。
そこで、今までは、JIS-2022-JP(7bit)の制約を受け、環境依存文字や半角カナ
が文字化けを起こす環境で運用を行っていたが、さすがに、ガラケーのみで
運用をするユーザが現役社会人である可能性は、万が一くらいでいいだろうと判断した。
前段が長くなってしまったが、
UTF-8でPHPMAILERのインスタンスを生成する際の記載をオボエガキ
前回との変更箇所をオレンジ表記
smtp送信テストPHP(UTF-8送信)<?
require_once("/置いた所/vendor/autoload.php" ); //これを忘れると動かない!! require_once("/置いた所/vendor/phpmailer/phpmailer/class.phpmailer.php"); //これを忘れると動かない!!
mb_language("japanese");
mb_internal_encoding("UTF-8");
$to = "XXXX@gmail.com"; $subject = "SMTP587テスト"; $body = "smtpサーバ経由のメールテスト";
$from = "hoge@hogehoge.com"; $fromname = "送信テスト君"; $mail = new PHPMailer();//インスタンス生成 $mail->CharSet = "UTF-8";//UTF-8の宣言をすること $mail->Encoding = "base64";//記述しないと正しく認識しないサーバが存在するらしい。 $mail->IsSMTP(); //smtp利用宣言 $mail->SMTPAuth = TRUE;//smtp認証宣言 $mail->Host = 'mail.xxxx.jp:587'; // ホストアドレス:ポート25or587 $mail->Username = 'hoge'; //smtp認証ユーザ $mail->Password = 'hogehoge'; //smtp認証パス $mail->AddAddress($to);
$mail->From = $from;
$mail->FromName = $fromname;
$mail->Subject = $subject; $mail->Body = $body;
//メールを送信 if (!$mail->Send()){ echo("Failed to send mail. Error:".$mail->ErrorInfo); }else{ echo("Send mail OK."); }
?>
大分後になって
$mail->CharSet = "UTF-8";
$mail->Encoding = "base64";
と宣言をするよりも、
$mail->CharSet = "iso-2022-jp";
$mail->Encoding = "7bit";
として、愚直に
mb_encode_mimeheader(mb_convert_encoding($fromname,"JIS","UTF-8"))
としたほうが、エンコード率が高いことが分かった。
2018/10/24
composerで配置したPHPMailerの アクセス権限について
昨日、home直下のユーザディレクトリで作業を行ない、
/home/user/vendorという状況でテストを行ったが
例えば、/ver/www/htmlの配下から
/home/user/vendorにリクエストをする際に、パーミッションエラーが起こり
phpのプログラムが止まってしまった。
autoload.phpが正しくrequireされているかを確認するのが、厄介だった。
また、home以下のディレクトリのパーミッションを流石にすべて777にしたくないので、
/ver/www/html側に
composerから再度PHPMailerを配置し、お茶を濁した。
/home/user/vendorという状況でテストを行ったが
例えば、/ver/www/htmlの配下から
/home/user/vendorにリクエストをする際に、パーミッションエラーが起こり
phpのプログラムが止まってしまった。
autoload.phpが正しくrequireされているかを確認するのが、厄介だった。
また、home以下のディレクトリのパーミッションを流石にすべて777にしたくないので、
/ver/www/html側に
composerから再度PHPMailerを配置し、お茶を濁した。
2018/10/23
メールの到達率を高める。 SPF逆引き対策
受付完了のメールなどを、社内のサーバから送信しているのだが、
セキュアな対策を行っているメールサーバを利用している方に、メールが届かない
というケースが生じてきた。
SPF(Sender Policy Framework) という技術だそうで、
FORMのIPアドレスがDNSの逆引きで実在するかをチェックするという動きのようだ。
わざわざレンタルサーバ上でメールを作成して送信も手間なので、
今までは、特段気にしていなかったが、基幹システム化しつつあるため、そうも言ってられなくなった。
要は、実在するSMTPサーバを経由してメールを送ればいいので、少し調べた所
いくつか方法があった。
1.
1.は設定変更等が生じた際に面倒な気がしてならないので、保留。
2.は魅力的だが、php7.0以降でサポートしていないようなので、後ろ髪惹かれつ第2候補に
というわけで、PHPMailerをインストールしてみる。
依存関係を考慮しつつライブラリを使えるようにしてくれる
composerという PHPのパッケージ管理システムを使って
PHPMailerを導入してみる。
セキュアな対策を行っているメールサーバを利用している方に、メールが届かない
というケースが生じてきた。
SPF(Sender Policy Framework) という技術だそうで、
FORMのIPアドレスがDNSの逆引きで実在するかをチェックするという動きのようだ。
わざわざレンタルサーバ上でメールを作成して送信も手間なので、
今までは、特段気にしていなかったが、基幹システム化しつつあるため、そうも言ってられなくなった。
要は、実在するSMTPサーバを経由してメールを送ればいいので、少し調べた所
いくつか方法があった。
1.
postfixのmain.cf にリレーさせる
2.Qdsmtpというhal456さんが作成したライブラリを利用させて頂き、smtpサーバ経由にする。
3.PHPMailerという老舗のライブラリを利用させて頂きsmtpサーバを経由にする。
1.は設定変更等が生じた際に面倒な気がしてならないので、保留。
2.は魅力的だが、php7.0以降でサポートしていないようなので、後ろ髪惹かれつ第2候補に
というわけで、PHPMailerをインストールしてみる。
依存関係を考慮しつつライブラリを使えるようにしてくれる
composerという PHPのパッケージ管理システムを使って
PHPMailerを導入してみる。
# mkdir comp 適当な作業ディレクトリを作成。
# cd comp
# php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
# php composer-setup.php
All settings correct for using Composer
Downloading...
Composer (version 1.7.2) successfully installed to: /root/composer.phar
Use it: php composer.phar
# rm -f composer-setup.php もう要らないので、消す
# mv composer.phar /usr/local/bin/composer システム全般で使えるように移動
セキュリティホールになるからルートで使うなと言われるらしいので、 一般ユーザで確認
$ composer
でロゴとか出れば、OK
続けて、ライブラリ
phpmailer
を入れる。
任意のユーザの任意のディレクトリで行うこと
$ composer require phpmailer/phpmailer
Using version ^5.2 for phpmailer/phpmailer
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing phpmailer/phpmailer (v5.2.26): Downloading (100%)
phpmailer/phpmailer suggests installing league/oauth2-google (Needed for Google XOAUTH2 authentication)
Writing lock file
Generating autoload files
何処に置いたか忘れたら、これで探すようかな?
$ find -name vendor -type d
smtp送信テストPHP<?
require_once("/置いた所/vendor/autoload.php" ); //これを忘れると動かない!! require_once("/置いた所/vendor/phpmailer/phpmailer/class.phpmailer.php"); //これを忘れると動かない!!
mb_language("japanese");
mb_internal_encoding("UTF-8");
$to = "XXXX@gmail.com"; $subject = "SMTP587テスト"; $body = "smtpサーバ経由のメールテスト";
$from = "hoge@hogehoge.com"; $fromname = "送信テスト君"; $mail = new PHPMailer();//インスタンス生成 $mail->CharSet = "iso-2022-jp"; $mail->Encoding = "7bit"; $mail->IsSMTP(); //smtp利用宣言 $mail->SMTPAuth = TRUE;//smtp認証宣言 $mail->Host = 'mail.xxxx.jp:587'; // ホストアドレス:ポート25or587 $mail->Username = 'hoge'; //smtp認証ユーザ $mail->Password = 'hogehoge'; //smtp認証パス $mail->AddAddress($to);
$mail->From = $from; $mail->FromName = mb_encode_mimeheader(mb_convert_encoding($fromname,"JIS","UTF-8"));
$mail->Subject = mb_encode_mimeheader(mb_convert_encoding($subject,"JIS","UTF-8")); $mail->Body = mb_convert_encoding($body,"JIS","UTF-8"); //メールを送信 if (!$mail->Send()){ echo("Failed to send mail. Error:".$mail->ErrorInfo); }else{ echo("Send mail OK."); }
?>
テスト送信が届いたら、
念のため、SMTPサーバの/var/log/maillog も確認し、上手くいってるようだ。
稼働中のプログラムの置き換えをして完了。
明日できれば置き換えよう
うん、がんばろう・・・。
2018/10/10
tesseractの数字と一部の記号のみ識字させる方法
https://code-examples.net/ja/q/4b73be
此処に記載があった。
outputbase digits のオプションでは、何故か上手く行かなかったので、
此処に記載があった。
outputbase digits のオプションでは、何故か上手く行かなかったので、
少し調べてみたところ
標準出力にオプションでキャラクタの設定が出来るとあった。
標準出力にオプションでキャラクタの設定が出来るとあった。
stdout -c tessedit_char_whitelist=指定したい内容
これは上手くいったので、一旦標準出力させたものを無理やりファイル出力させた。
正規の方法は、学習させることだと思うが、
数字とハイフンのみ識別させればよかったので、この方法を採った。
数字の認識のみさせるであれば余程特殊なフォントでなければ、かなりの精度で認識した。
ファイル出力する場合
$ tesseract test.png stdout -c tessedit_char_whitelist=0123456789- >test.txt
ファイル出力する場合
$ tesseract test.png stdout -c tessedit_char_whitelist=0123456789- >test.txt
このようにすると良い。
デフォルトのライブラリを通すと、~や#に誤認識することが有り、
上手くなかったので、探してみたところ有益な情報が見つかったので、オボエガキ
2018/09/12
MSSQLへPHPで接続(PDO接続)
表題の、PHPでMSSQLへの接続時のオボエガキ
もともとは、mssql_connectにてMS SQLServerに接続していたが、
サーバの仕様変更と、php7から利用できなくなることもありPDO(PHP Data Objects の略)
接続へ切り替えた。
設定は、/etc/odbc.iniにてODBCのIDとfreetdsドライバーを関連付
/etc/odbcinst.iniに freetdsドライバーを追加
[freetds]
Description = MS SQL database access with Free TDS
Driver = /usr/local/lib/libtdsodbc.so
UsageCount = 1
Trace = Yes
freetdsをリポジトリからインストールするとSSLサポートされないので、
手動でインストールが必要だった。
https://stackoverflow.com/questions/39395548/how-to-configure-pymssql-with-ssl-support-on-ubuntu-16-04-lts/39395549
先駆者様ありがとうございます。
python-pip と libssl-dev をインストール後、
freeTDSは0.95のtar.gzを展開し、ディレクトリ内でmakeインストールする。
# ./configure --with-openssl=/usr/include/openssl --with-tdsver=7.3
# make
# make install
freetdsで接続する際に参照される接続先の定義は、/home/ユーザ名/.freetds.confに記載する。
##.freetds.confの中身##
# $Id: freetds.conf,v 1.12 2007-12-25 06:02:36 jklowden Exp $
#
# This file is installed by FreeTDS if no file by the same
# name is found in the installation directory.
#
# For information about the layout of this file and its settings,
# see the freetds.conf manpage "man freetds.conf".
# Global settings are overridden by those in a database
# server specific section
[global]
# TDS protocol version
; tds version = 4.2
# Whether to write a TDSDUMP file for diagnostic purposes
# (setting this to /tmp is insecure on a multi-user system)
; dump file = /tmp/freetds.log
; debug flags = 0xffff
# Command and connection timeouts
; timeout = 10
; connect timeout = 10
# If you get out-of-memory errors, it may mean that your client
# is trying to allocate a huge buffer for a TEXT field.
# Try setting 'text size' to a more reasonable limit
text size = 64512
# A typical Sybase server
[hoge] ←この変数を 'odbc:hoge' で読み込む。
host = hoge-sql.database.windows.net
port = 1433
tds version = 7.3
database = DEMODB
encryption = require
【PHPの中身】
//MSSQLにPDO接続
//基本:$pdo = new PDO($dsn, $username, $password, $driver_options);
try {
$pdo = new PDO('odbc:hoge','ログインユーザ名@hoge-sql.database.winwdows.net','パスワード');
$pdo->exec('SET CHARACTER SET utf8');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch(PDOException $Exception){
die('接続エラー:' .$Exception->getMessage());
}
//クエリ取得
try{
$sql= "select * from [テーブル名] where 条件";
$stmh = $pdo->prepare($sql);
$stmh->execute();
}catch(PDOException $Exception){
die('接続エラー:' .$Exception->getMessage());
}
while($col = $stmh->fetch(PDO::FETCH_ASSOC)){
print($col['カラム名']);
//変数等を定義する場合も普通に行える。
}
}//クエリの取得終了
//sqlServerの接続を解除
$pdo = null;
もともとは、mssql_connectにてMS SQLServerに接続していたが、
サーバの仕様変更と、php7から利用できなくなることもありPDO(PHP Data Objects の略)
接続へ切り替えた。
設定は、/etc/odbc.iniにてODBCのIDとfreetdsドライバーを関連付
/etc/odbcinst.iniに freetdsドライバーを追加
[freetds]
Description = MS SQL database access with Free TDS
Driver = /usr/local/lib/libtdsodbc.so
UsageCount = 1
Trace = Yes
freetdsをリポジトリからインストールするとSSLサポートされないので、
手動でインストールが必要だった。
https://stackoverflow.com/questions/39395548/how-to-configure-pymssql-with-ssl-support-on-ubuntu-16-04-lts/39395549
先駆者様ありがとうございます。
python-pip と libssl-dev をインストール後、
freeTDSは0.95のtar.gzを展開し、ディレクトリ内でmakeインストールする。
# ./configure --with-openssl=/usr/include/openssl --with-tdsver=7.3
# make
# make install
$ tsql -C
Compile-time settings (established with the "configure" script)
Version: freetds v0.95
freetds.conf directory: /usr/local/etc
MS db-lib source compatibility: no
Sybase binary compatibility: no
Thread safety: yes
iconv library: yes
TDS version: 7.3
iODBC: no
unixodbc: yes
SSPI "trusted" logins: no
Kerberos: no
OpenSSL: yes ←ここが重要
GnuTLS: no
freetdsで接続する際に参照される接続先の定義は、/home/ユーザ名/.freetds.confに記載する。
##.freetds.confの中身##
# $Id: freetds.conf,v 1.12 2007-12-25 06:02:36 jklowden Exp $
#
# This file is installed by FreeTDS if no file by the same
# name is found in the installation directory.
#
# For information about the layout of this file and its settings,
# see the freetds.conf manpage "man freetds.conf".
# Global settings are overridden by those in a database
# server specific section
[global]
# TDS protocol version
; tds version = 4.2
# Whether to write a TDSDUMP file for diagnostic purposes
# (setting this to /tmp is insecure on a multi-user system)
; dump file = /tmp/freetds.log
; debug flags = 0xffff
# Command and connection timeouts
; timeout = 10
; connect timeout = 10
# If you get out-of-memory errors, it may mean that your client
# is trying to allocate a huge buffer for a TEXT field.
# Try setting 'text size' to a more reasonable limit
text size = 64512
# A typical Sybase server
[hoge] ←この変数を 'odbc:hoge' で読み込む。
host = hoge-sql.database.windows.net
port = 1433
tds version = 7.3
database = DEMODB
encryption = require
【PHPの中身】
//MSSQLにPDO接続
//基本:$pdo = new PDO($dsn, $username, $password, $driver_options);
try {
$pdo = new PDO('odbc:hoge','ログインユーザ名@hoge-sql.database.winwdows.net','パスワード');
$pdo->exec('SET CHARACTER SET utf8');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch(PDOException $Exception){
die('接続エラー:' .$Exception->getMessage());
}
//クエリ取得
try{
$sql= "select * from [テーブル名] where 条件";
$stmh = $pdo->prepare($sql);
$stmh->execute();
}catch(PDOException $Exception){
die('接続エラー:' .$Exception->getMessage());
}
while($col = $stmh->fetch(PDO::FETCH_ASSOC)){
print($col['カラム名']);
//変数等を定義する場合も普通に行える。
}
}//クエリの取得終了
//sqlServerの接続を解除
$pdo = null;
2018/08/09
postfixのTLS設定
gmailで暗号化されていないと赤い鍵が表示されて何か気になるので対策してみる。
ファイアーウォールは適宜解放のこと
25、587、465
ローカルのSSL/TLSの設定は行っているが、
postfixのサーバ間の接続については、細かく設定していなかった。(MTA間通信)
これをTLSやS/MIMEに対応させていないと、gmailで赤い鍵が表示されてしまう仕様のようだ。
postfixの設定見直しはSMTP関連は次のようにしておく
赤い鍵が消えた。よかった。
ファイアーウォールは適宜解放のこと
25、587、465
ローカルのSSL/TLSの設定は行っているが、
postfixのサーバ間の接続については、細かく設定していなかった。(MTA間通信)
これをTLSやS/MIMEに対応させていないと、gmailで赤い鍵が表示されてしまう仕様のようだ。
postfixの設定見直しはSMTP関連は次のようにしておく
# nano /etc/postfix/master.cf 頭の方に記載がある
【中身】
smtp inet n - n - - smtpd
↑必須 submission inet n - n - - smtpd ↑587ポートを使う場合
-o smtpd_tls_security_level=may
↑587の時これをencriptにすると、STARTTLSをしてから送れ、と言われてしまうので、どっちも許容のmayがよい
-o smtpd_sasl_auth_enable=yes
↑SMTP認証を使う場合はyesにする
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
↑SMTP-AUTHを通ったものを許可する。rejectは細かく指定するとそこは蹴れる。
# nano /etc/postfix/main.cf TLSは末尾に記載されているので、そこを編集
【中身】
## TLS
# Transport Layer Security
#
smtpd_use_tls = yes
smtp_use_tls = yes
#smtpd_tls_auth_only = yes
↑これを有効にするとTLSでないと蹴るので、コメントアウトのままにしておく smtpd_tls_key_file = /usr/local/ssl/private/キーファイル.key smtpd_tls_CAfile = /usr/local/ssl/crt/SSL証明書ファイル.crt smtpd_tls_loglevel = 3
↑これを1にすると、ログにTLSの事が記載されるらしい。
smtpd_tls_received_header = yes
tls_random_source = dev:/dev/urandom
smtpd_tls_security_level=may
↑25ポートからのSTARTTLSを使う場合は、master.cfでなく、main.cfに記載するとの事。postfixを再起動して内容反映
# systemctl restart postfix
オレンジ色の部分を記載すると、
相手がTLSを受け付けてくれる場合は、MTA間通信をSSL/TLSにて行える
登録:
投稿 (Atom)