RaspberryPiでPBXとFAXの構築 - 迷惑電話レポート

投稿 2025/07/12 (土) 午後 07:10 | パソコン | hotall



迷惑電話対策をしてから、すっかり迷惑電話に煩わされなくなりました。
たまに着信電話番号リストファイルを覗くと、結構な数の迷惑電話が記録されています。

やはり、現状どのくらい迷惑電話を拒否したのか、それが気になるのです。
そこで、迷惑電話の履歴をレポートとして通知することにしました。

この文書は個人的なものであり、内容について一切の責任を負いかねます。






処理内容は次の通り。
  • 着信電話番号リストファイルを調べ、前回の調べた以降に着信したデータの内、迷惑電話(判定がNG)のデータを抽出しレポート対象リストファイルに保存する。
  • レポート対象データファイルから、レポートを作成し、指定したメールアドレスに送信する。
  • メール送信は留守電やFAXと同様にsSMTPを使用する。
  • レポート対象リストファイルは、次回、処理済みデータの判別に使用する。
  • 一連の処理は毎日定時刻で行う。
プログラムはPython3。
#!/usr/bin/env python3
""" 迷惑電話拒否レポートスクリプト

拒否した迷惑電話についての情報を通知する。

着信電話番号リストファイルから前回通知以降に拒否した迷惑電話の情報をメールで通知する。
通知する情報は次の通り
 ・電話番号
・着信日時
 ・着信回数
 ・コメント/名前
通知する迷惑電話の情報を通知リストファイルに保存し、次回の処理に使用する。
ファイルフォーマットは着信電話番号リストファイルと同じとし、
レコードは降順(最新が先頭)とする。
テキストファイル(utf-8)
<着信電話番号>,<判定区分>,<最新着信日時>,<回数>,<コメント/名前>LF
<着信電話番号>,<判定区分>,<最新着信日時>,<回数>,<コメント/名前>LF
...


Arguments
----------
toaddr : str
送信先メールアドレス


Returns
-------
int
0 : 正常終了 その他 : 処理失敗

Example
-------
コマンドの使い方

python meiwaku_report.py <通知先>

Notes
-----
各ファイルのパスは変数:XXXX_XXXX_FILEに格納。

"""
__author__ = "Yasuaki Nojiri"
__version__ = "1.0.0"
__date__ = "2025/07/01"

import sys
import os
import stat
import asyncio

# 定数の設定
CALLER_LIST_DIR = '/usr/local/share/meiwakuchk'
CALLER_LIST_FILE = f'{CALLER_LIST_DIR}/caller-list.txt'
REPORT_LIST_DIR = CALLER_LIST_DIR
REPORT_LIST_FILE = f'{REPORT_LIST_DIR}/report-list.txt'
REPORT_LIST_FILE_NEW = f'{REPORT_LIST_FILE}.new'
REPORT_MAIL_DIR = CALLER_LIST_DIR
REPORT_MAIL_FILE = f'{REPORT_MAIL_DIR}/report-mail.txt'
REPORT_LIST_FILE_PRM = stat.S_IRWXU | \
stat.S_IRGRP | stat.S_IWGRP | \
stat.S_IROTH | stat.S_IWOTH

MAIL_CONTENT = "To: {toaddr}\n" + \
"Subject: [PBX]: =?UTF-8?B?6L+35oOR6Zu76Kmx44G" + \
"u44Os44Od44O844OI?=\n" + \
"From: PBX <{fromaddr}>\n" + \
"Content-type: text/plain; charset=UTF-8\n" + \
"Content-Transfer-Encoding: Quoted-Printable\n" + \
"\n" + \
"自宅の電話からのお知らせです。\n" + \
"\t迷惑電話の着信を拒否しました。\n" + \
"\t\t\n"

MAIL_ITEM = "\t\t着信日時:{call_date}\n" + \
"\t\t発信元番号:{call_id}\n" + \
"\t\t発信元情報:{call_name}\n" + \
"\t\t累計着信数:{call_times:>4}\n" + \
"\t\t-------------------------\n"

MAIL_CMD = "/usr/sbin/sendmail {sendto} < {content}"
MAIL_FROMADDR = r"xxxx@xxxxxxx.xxxx"

import logging
logger = logging.getLogger(__name__)
APPNAME = os.path.basename(__file__)
logging.basicConfig( \
filename=f'{CALLER_LIST_DIR}/{APPNAME}.log', \
encoding='utf-8', \
format=f'%(asctime)s {APPNAME}[%(process)d]: %(levelname)s: %(message)s', \
level=logging.INFO )

def main(args):
"""メイン関数

Parameters
----------
args : array
コマンドライン引数

Returns
-------
int
終了コード

"""

# コマンドライン引数の処理
toaddr = ""
innum = 0
errmsg = ''
while True:
if len(args) < 2 :
errmsg = "Not enough arguments."
break;

toaddr = args[1]

break;

if errmsg != '':
# コマンドライン引数のエラー
print(errmsg)
print_usage()
sys.exit(-1)

logger.info(f'meiwaku_report start.')

# レポート対象リストファイルの準備
os.makedirs(REPORT_LIST_DIR, exist_ok=True)
if not os.path.isfile(REPORT_LIST_FILE):
# 存在しない場合は、空ファイルを作成
with open(REPORT_LIST_FILE,'w'):pass

# レポート対象リストファイルの先頭行から前回レポート着信日時を取得
lastreport = ""
with open(REPORT_LIST_FILE, mode='r') as file_in:
# 1行毎に読込む
for i, rec_i in enumerate(file_in):
record = rec_i.split(',')
if len(record) > 2:
# 前回レポート着信日時を取得
lastreport = record[2];
break

# 着信電話番号リストファイルからレポート対象のデータを取得
# レポート対象データファイルを作成
report_count = 0;
with open(CALLER_LIST_FILE, mode='r') as file_in, \
open(REPORT_LIST_FILE_NEW, mode='w') as file_out:

# 元のファイルの内容を出力
for i, rec_i in enumerate(file_in):
record = rec_i.split(',')
if len(record) > 2 and record[2] <= lastreport:
# 前回レポート着信日時に達した場合、抜ける
break;

if record[1] == 'NG':
# 迷惑電話判定の場合、レコードを出力
print(rec_i, end='', file=file_out)
report_count = report_count + 1


if report_count > 0:
# レポート対象リストデータがある場合
# レポート対象リストファイルからレポートファイルを作成
with open(REPORT_LIST_FILE_NEW, mode='r') as file_in, \
open(REPORT_MAIL_FILE, mode='w') as file_out:
# ヘッダー、先頭コンテンツの出力
print(MAIL_CONTENT.format( \
toaddr=toaddr, \
fromaddr=MAIL_FROMADDR), end='', file=file_out);

# レポート対象データを出力
for i, rec_i in enumerate(file_in):
record = rec_i.split(',')

# レポート用に編集して出力
print(MAIL_ITEM.format( \
call_date=record[2], \
call_times=record[3], \
call_id=record[0], \
call_name=record[4].removesuffix('\n')), end='', file=file_out)

# メールの送信
if asyncio.run(run_sendmail_command(toaddr, REPORT_MAIL_FILE)) == 0:
# 送信が成功した場合、
# 今回レポート対象リストファイルの権限を設定
os.chmod(REPORT_LIST_FILE_NEW, REPORT_LIST_FILE_PRM)

# 今回レポート対象リストファイルに置換
os.remove(REPORT_LIST_FILE)
os.rename(REPORT_LIST_FILE_NEW, REPORT_LIST_FILE)

logger.info(f'Sent report mail of {report_count} MEIWAKU calls.')

else:
# レポート対象リストデータがない場合
os.remove(REPORT_LIST_FILE_NEW)

logger.info(f'meiwaku_report end. {report_count} records processed.')

return 0

async def run_sendmail_command( toaddr, contnt_file ):
""" メール送信コマンドの実行

メールを送信するコマンドを実行

Parameters
----------
toaddr: str
送信先アドレス
contnt_file : str
送信するメッセージを格納したファイルのパス

Returns
-------
int
終了ステータス
"""
cmd = MAIL_CMD.format(sendto=toaddr, content=contnt_file)

proc = await asyncio.create_subprocess_shell( \
cmd, \
stdout=asyncio.subprocess.PIPE, \
stderr=asyncio.subprocess.PIPE)

stdout, stderr = await proc.communicate()

logger.info(f'[{cmd!r}] exited with {proc.returncode}.')

if stderr:
logger.err(f'{stderr.decode()}')

return proc.returncode

def print_usage():
"""このコマンド使用法の出力
"""
print('meiwaku_report.py <to mail address>')

#
if __name__ == "__main__":
# トップレベル環境で実行された場合、メイン関数を呼ぶ
sys.exit(main(sys.argv))

作成したユーザープログラムを配置します。
場所:/usr/share/asterisk/agi-bin
ファイル名:meiwaku_report.py

ユーザープログラムの権限を設定します。
パーミッションの設定:
chmod 755 meiwaku_report.py

cronのコンフィギュレーション

crontabを使ってスケジュールを設定します。

sudo crontab -e

設定内容:
  • 毎日、12:30と17:30にスクリプトを起動します。
# meiwaku report
30 17 * * * python3 /usr/share/asterisk/agi-bin/meiwaku_report.py xxxxx@xxxxxx.xxx
30 12 * * * python3 /usr/share/asterisk/agi-bin/meiwaku_report.py xxxxx@xxxxxx.xxx
xxxxx@xxxxxx.xxxはメール送信先アドレスです。実際の運用に合わせてください。



■ RaspberryPiでPBXとFAXの構築 - 目次 -
  1. 構成
  2. ひかり電話RV-230SEの設定
  3. OSのセットアップ
  4. LANアダプタの接続
  5. ユーティリティのセットアップ
  6. PBXのセットアップ
  7. ソフトウェアモデムのセットアップ
  8. FAXのセットアップ
  9. 自動再起動
  10. ステータスLEDの接続
  11. ケースに収納・設置
  12. トラブルと対応
  13. 迷惑電話対策
  14. 迷惑電話対策2
  15. ▶迷惑電話レポート
« Prev • Next »

コメント

コメントはありません。

コメントする