mgetty+sendfax /tesseract

# ファクシミリ　〜電気通信の歴史〜
実は有線電話よりファクシミリのほうが歴史が長いのです。1843年にはA.ベインによってファクシミリが実現しています。ボーソー、メウッチ、G.ベル、グレイらが発明し特許出願で争いまでした「電話」より11年も早かったのです。

昭和な
零細企業ではまだFAXが使われています。
そこそこな値段のFAXサーバというものが売られていて、それを使えばいいのですが
現状は生産国問題があります。（CN)

# なぜ未だにFAXに取り組んでいるのか
なぜまだ使おうとしているのでしょう。逆にすでに設定されていても良かったのではと思うのですが・・・
（無論、専用機を買えばいい事ですが、高いですし、中で何をやっているかわかりません。）
実は、モデムをUNIXサーバとつなげるというシステムは30年以上前に「古臭い」「面倒くさい」「不安定」でバッサリ切り捨てていたのがあります。 
PPPでつなげることを考えれば、切れる・遅い・通話料金が高い　と嫌なことしか思い出せず、忌避していたのです。
とはいえ、業務において、光ファイバが普及しても　いわゆるインターネット・メールがFAXを完全に滅ぼしてしまうことは出来ませんでした。業態としてFAXが必要という客は年にして数％の比率で消滅しているのでしょうが、保管状況の確認が容易な手書き文書＋ボタン操作だけでコピーを送りつけられるデバイス、PTSNの手堅さに支えられて今もしぶとく生き延びています。この事実を足掻くのをやめて受け入れます。


## 2024年に FreeBSD で Faxを使うには？
FreeBSDに限って言うと、ほとんどの 有線FAX を扱えるパッケージされたものは排除されています。(ラジオFAXはいくつかあるようです）　そもそもシステム健全性を考えるとメンテナンスされてないものは淘汰されてしまいます。

## mgetty+sendfax 他の歴史　

* HylaFaxはUnix系PC-FAXの老舗的なパッケージです。CSRG, UC Berkeleyに在籍して　BSD-UNIXの歴史に名を刻むエンジニアの一人 Samuel J. Lefflerさんによって作られています。当時は FlexFaxという名前だったようです。商用パッケージ化もあって、おそらく今でもユーザが一番多いでしょう。FreeBSDでは色々あったのか、portsからは消えてます。

* 1994年8月 に Gert Doeringさん(gert@greenie.muc.de) が残している バージョン 0.20というのがあり、これより少し前から作られていたのでしょう。 

* efaxは、後発ですが原作者のサイトがあります。 https://www.cce.com/efax/
これも slackware を使っていた頃に入れた記憶がありますが、当時のPCサーバの性能、市販で手に入るでFAXモデムの安定性はお世辞にも良いとはいえず、顧客の業務に使うに至りませんでした。20年前でもすでに業務用モデムの入手性は高くなかったというか、これらは複合機メーカの独占物でした。

## asterisk でやればいいのでは？
いまなら、asterisk で ボイスメール系と一緒に管理できるのでしょうねえ。ただ純粋なデジタルファクス＝T.38のファクスがあまり普及してないのもありますし、VoIPアダプタだけででアナログFAX受信が出来るのかは不明。おそらくFXOゲートウェイで仮想モデムとか経由したらできるんじゃねーの？という話になるのかと思いますが、詳しくないのでまた今度。

# mgetty+sendfax 設定したことがなかった・・
30年も前から存在を知っていたのに、つい最近まで使うことを思いつかなかったのが大いなる "謎" です。
そして2024年でも使えそうなのが mgetty+sendfax であることに縋っています。

## 設定準備
* 必要なもの   :  usb modem　FreeBSDの入ったサーバ
* 必要なports :  comms/mgetty+sendfax,mail/heirloom-mailx,graphics/netpbm,graphics/ImageMagick7,graphics/tesseract

とりあえず、揃えてインストールしておきます。 以下説明。
### usb modem　
20世紀末からの鉄板、 US-Robotics あたりの V.56/Fax対応 外付けモデムがあれば、間違いはないですが、21世紀の2024年ともなれば、RS-232C/RS-422Aポートがないサーバ、すでにシリアルコンソールで埋まってるサーバでも大丈夫なように安いUSB接続モデムでも買っておきましょう。　USBモデムの需要なんて、今後いつまであるのか？という気もします。

### mgetty+sendfax

 すまんなのび太、これはx86/amd64専用なんだ。
 
と、RaspberryPi on FreeBSD　では無理そうです。　そういうことで、RasPi使いは こっちを参考にするといいでしょう。　⇒ Raspberry Pi で FAX 受信専用サーバ https://qiita.com/nanbuwks/items/68a6c9fc9a41dc41dcc7

## heirloom/mailx
 mailx (mua) は 歴史あるソフトウェアであるため、様々な亜種があります。添付ファイルをわざわざmime処理などを書かずに送付できる heirloom/mailx を使うのは時代遅れで、最近の流れなら 各種のスクリプトにあるsmtpライブラリで書けばいいじゃないかというという感もありますが、そこは「立っていれば親でも使う」のが信条で、わざわざコードを書く必要のないものをさっさと入れてしまいます。

 ## netpbm
これも歴史があるのですが、詳しいことはよくわかりません。
 画像フォーマットを表すのに、 pgm/pbm/ppm などの拡張子がありますが、これらは pnm （"p"ortable-a"n"y-"m"ap) という画像ファイル形式群です。
 mgetty+sendfax では、ファクスで標準化されたG3圧縮された画像ファイルからpbmを取り出せる、 g3topbm　が用意されています。単純なpbmファイルは切り出しツールが使いやすいので後で使います。 あとFAXでは引き合いに出される、Tagged Image File Format = tiff形式の話もしましょう。 tiffファイルとg3ファイルは基本と拡張の関係にあり、昔は詳しく知らずに、ファクス画像=tiffだと思っていたことがあります。そもそもの tiffファイルは、デジタル通信媒体で使うことが前提なため、誤り訂正情報がないもので、1986年にMicrosoftとAldus社の２社が定めたフォーマットでした。あまりに幅広く利用されることを想定し１ファイルの中に複数の画像が入るなど、初期からやや込み入ったものでしたが、拡張性が優れていたことで多くの亜種が出来ました。 
 
 ## ImageMagick
 WordPressを使う人は、必ずお世話になっているだろう画像ファイル形式関連をイッテに引き受けてくれるツールです。 ファクスでは G3圧縮された画像ファイル形式をやりとりするので、g3からpdfに変換させる用途で使います。

## Tesseract 
FAXを＊＊＊するといえば、まあOCRです。といっても、全文を扱うOCR性能は期待しません。そもそも画像を送ってくるのが仕事のファクスでOCRして文字にしてやるのはOCRの本地本命とはいえなかなか厳しいでしょう。
有線電話で、アナログのファクスを受信しても、回線契約によっては送信者IDがわからないことがあります。私の環境では建前でアナログ収容されている（銅線をやめて光収容されている？）線では、送信者の電番を表示しない契約でしたので、誰から来たかは実際のヘッダを見るしかありません。無論、ナンバーディスプレイ契約でもしていればPTSNだろうが出るんでしょうが、このあたりは詳しくないので ''' 知らないことにしておきます '''（知っても契約しなければ使えん）。INSならDチャネルで送られてくるので、TAに表示が出たり通知できるのはわかるのですが・・・
というようなわけで、FAXの上辺部分に小さな文字で打たれている数字だけをOCRしてやろうということになります。そうでないと「FAXが来ました」くらいしかユーザに通知できず、読まずに捨てるかの判断が難しいです。

## インストールしていく
* usbモデム
適当に挿せばいいのですが、その後 
<pre>
/dev/cuaU0
</pre>
が生えてくるかを確認しましょう。まれに出来ないことがあります。


* mgetty+sendfax
pkg install で okです。　重要なのは３つの設定ファイル。
<pre>
/usr/local/etc/mgetty+sendfax/mgetty.config
/usr/local/etc/mgetty+sendfax/sendfax.config 👈　存在しないかも
/usr/local/lib/mgetty+sendfax/new_fax　👈　存在しないかも
</pre>

#### mgetty.config 

<pre>
verbose y
debug 8 
fax-id 0xx-yyy-aaaa
speed 19200
port cuaU0
speed 19200
switchbd 19200
modem-type c2.0
</pre>

にしてます。G3 FAX = 14400 bps  なので 19,200 bps以上でないと多分取りこぼします。USB2.0であれば普通 115,200以上でも設定されるでしょう。


### sendfax.config 

<pre>
verbose y
debug 5
fax-devices cuaU0
fax-id 0xxx-pppp-qqqq
max-tries 3
max-tries-continue y
port cuaU0

</pre>
このファイルはインストールされてなかったりします。バイナリファイルから文字列を引いて所在判明しましたが、これがないと送信時のFAX-IDには 49 115 XXXXXXXX の文字列が入ります。無論無くても動くには動きます。

### /usr/local/lib/mgetty+sendfax/new_fax

これも初期設定されなかったりします。　ファクスを受け取った際にhookするスクリプトで印刷したり、PDF化したり、メールにしたりする処理を書きます。
私は、動けばいいやの拙いスクリプト書きなので本当にひどいものでごまかしていますがこんな適当なのでも動きます。

/usr/local/lib/mgetty+sendfax

```
#!/bin/sh
#
MAILTO="strnh@hoge.dom" #
SENDER="$2"
SPOOL=/var/spool/fax/incoming

case $4 in
  /var/spool/fax/incoming/fn*) STRETCH=-s ;; # find out resolution
  *) STRETCH=
esac

FAX=$(echo "$4"|sed 's/...$//')
FAX_BASENAME=$(basename "$FAX")


cd $SPOOL && ls -1 "$FAX_BASENAME".* | /usr/bin/awk '{print "mv " $1 " " $1".g3" }' | /bin/sh -x


/usr/local/bin/convert $SPOOL/"$FAX_BASENAME".*.g3 /tmp/"$FAX_BASENAME".pdf
/usr/local/bin/convert $SPOOL/"$FAX_BASENAME".*.g3 /tmp/"$FAX_BASENAME".pbm
/usr/local/bin/pamcut  -left=0 -top=0 --bottom=48 /tmp/"$FAX_BASENAME".pbm > /tmp/"$FAX_BASENAME".0.pbm
cd /tmp && /usr/local/bin/tesseract /tmp/"$FAX_BASENAME".0.pbm "$FAX_BASENAME" --psm 7 /usr/local/etc/tess.conf

FAXHEAD=$(cat /tmp/"$FAX_BASENAME".txt)

echo fax: from  "$FAXHEAD"  | /usr/local/bin/mailx -s Fax:\ "$FAXHEAD" -a /tmp/"$FAX_BASENAME".pdf $MAILTO

rm /tmp/"$FAX_BASENAME".*

exit 0
```

上記の 書き換えた new_fax のスクリプトは、受信したファイルを加工するだけの簡単なものです。 pbmに落として、pam_cut でヘッダ部の矩形を切り出して、OCRした文字をメールに入れて、FAXをメールで受信したときに分類がしやすくなります。　ここで OCR を担当する tesseract については、今回深く追いませんでした。

/usr/local/lib/mgetty+sendfax/sample 

にインストールされてくるいくつかのサンプルは、動作を確認することには使えますが、やや古き良き時代の書法です。そのまま使うと外部からの文字列、特にFAXヘッダ部にサーバ攻撃を意図した文字列を盛られる可能性はあります。 shellcheck を使って書き直したほうがいいでしょう。



## テスト
FAXを自動でお繰り返してくれるサービスがあればそれを使うのもあります。
今回は私の自宅と実家に同じシステムを導入したので、送受信テストが出来ました。
テスト用スクリプトを書いて送信を繰り返しテストしました。

<pre>
#!/bin/sh
sendfax -v -l cuaU0 -x 9 -n 0xxxxxxxx /var/spool/fax/test/ff71b7767U0.01.g3

</pre>

ログは以下のファイル

/var/log/mgetty.cuaU0 
/var/spool/fax/Faxlog 

に取られます。設定された debug レベルにより　以下のようなログが出ます。

<pre>
10/25 19:54:09 aU0  page complete, 69213 bytes sent
10/25 19:54:09 aU0  sending DLE ETX...
10/25 19:54:09 aU0  fax_wait_for(OK)
10/25 19:54:09 aU0    got:[0d][0a]OK[0d]
10/25 19:54:12 aU0   fax_wait_for: string 'OK'** found **
10/25 19:54:12 aU0  fax_send: 'AT+FET=2'
10/25 19:54:12 aU0  fax_wait_for(OK)
10/25 19:54:12 aU0    got:[0a]AT+FET=2[0d]
10/25 19:54:12 aU0   fax_wait_for: string 'AT+FET=2'
10/25 19:54:12 aU0    got:[0d][0a]+FPTS: 001[0d]
10/25 19:54:17 aU0   fax_wait_for: string '+FPTS: 001'
10/25 19:54:17 aU0  page status: +FPTS: 001
10/25 19:54:17 aU0    got:[0a][0d][0a]+FHNG: 000[0d]
10/25 19:54:17 aU0   fax_wait_for: string '+FHNG: 000'
10/25 19:54:17 aU0  connection hangup: '+FHNG: 000'
10/25 19:54:17 aU0   (Normal and proper end of connection)
10/25 19:54:17 aU0    got:[0a][0d][0a]OK[0d]
10/25 19:54:17 aU0   fax_wait_for: string 'OK'** found **
10/25 19:54:17 aU0  fax_send: 'AT+FCLASS=0'
10/25 19:54:17 aU0   removing lock file
</pre>

## トラブルシューティング
* モデムが応答していない
USBモデムが応答を返さないことがあります。ログに出ないので待たされます。　シリアルデバイスと自動対話型処理をするのに重宝する　/usr/bin/chat などを使った対話プログラムではよくみられます。
mgetty プロセスが kill されたタイミングによっては対話デッドロックしますので、 しばらく待ってから mgetty のプロセスを止めて respawn　を待つか、FAX送信テストしてしまうのが良いです。
* メールが出ない
new_fax スクリプト次第かと思います。

## おわりに
昔から長らく取り扱ってきた問題です。ファクスは滅びてしまうのだと思っていましたが、なかなかどうしてしぶとくいきのびています。とはいっても 20 年ばかり専用機器に任せきりにしていたり、モデムの存在すら忘れていました。サーバ性能が上がってきた昨今、tesseract/OCRエンジン まで使えるのが新しい切り口になると思うのですが、ヘッダの文字が数字／英語／日本語混じりとなるため、 ただの電話番号ですら ➀②③... などとなってしまうのが解決できていません。罫線をキャラクタ化出来るレベルでないと実用にはならないというのが現実かと思います。