TwilioでFAX送信

※追記：2021年12月でFAX機能は終了するようです。
https://support.twilio.com/hc/en-us/articles/1260800821230-Programmable-Fax-Migration-Guide-for-Documo-mFax

日本ではまだまだFAXの利用率が高いと聞きますが，私が社内SEとして勤める業界でもFAXはメール以上に利用されている状態です。それで弊社では業務システムから直接FAXを送信できるような仕組みを構築しています。現状としては社内でFAXサーバーを運用しているものの，APIが充実している気が利いた外部のサービスはないものかと時々情報収集していました。そして最近見つけたのが以下の記事です。

*ついに発表！ FAX 機能リリース（twilioブログ）*
https://twilio.kddi-web.com/blog/developer/entry000307.html

## 料金（暫定）
料金については暫定ということで以下のように記載されています。以前にAPIが使える国内のFAXサービスをいくつか調べてみたことがありますが，だいたい1通あたり20円くらいはしました。この暫定料金であれば（送信するファイルにもよりますが）1通あたり6.9円ということになるので，業務で使えるレベルのコストではないかと思いました。

- 完全従量課金
- ￥1.5／ページ + 通信料（エラスティックSIP トランキングの料金に準ずる。日本では固定電話宛5.4円／分）
- 月あたり100ページまで無料（通信料はかかります）

## 番号取得
FAX用に番号を購入します。日本の番号でもFAXは使えるようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/102503/03f7f9e7-2d29-3054-28cd-21deae1af5f4.png)

## APIを使ってみる
最近愛用している[Insomnia](https://insomnia.rest/)を使ってREST APIを試してみます。仕様は[こちら](https://jp.twilio.com/docs/api/fax/rest/faxes#list-post)。
URLはベーシック認証をURLに組み込んだものを使います。

```
URL
https://{ACCOUNT SID}:{AUTH TOKEN}@fax.twilio.com/v1/Faxes

Header
Conetent-Type: multipart/form-data
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/102503/07f73cbc-4960-3e12-ba19-47907714e1a7.png)

twilioからアクセス可能な場所にPDFファイルを置いておき，そのURLを MediaUrl として設定します。PDFファイルのアップロードはできないようなので，実際に業務で利用する場合にはベーシック認証を設定した場所に置くことになりそうです。

```
Body
To: {送信先FAX番号}
From: {さっき取得した番号}
MediaUrl: {インターネット上に置いておいたPDFファイルのURL}
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/102503/d4749349-d79e-cc11-5f2c-c1a28be013e6.png)

これで送信すると，あっさりFAXが送信でき，レスポンスが返ってきました。

```json
{
	"media_sid": null,
	"status": "queued",
	"direction": "outbound",
	"from": "+8150********",
	"date_updated": "2017-12-24T09:54:37Z",
	"price": null,
	"account_sid": "***",
	"to": "+81***",
	"date_created": "2017-12-24T09:54:37Z",
	"url": "https://fax.twilio.com/v1/Faxes/FXae********************",
	"sid": "FXae********************",
	"duration": null,
	"num_pages": null,
	"quality": "fine",
	"price_unit": null,
	"api_version": "v1",
	"media_url": null,
	"links": {
		"media": "https://fax.twilio.com/v1/Faxes/FXae********************/Media"
	}
}
```

送信したFAXの情報は以下のURLを使ってGETで取得できます。FaxSidは送信時に返ってきたレスポンスに含まれています。

```
URL
https://{ACCOUNT SID}:{AUTH TOKEN}@fax.twilio.com/v1/Faxes/{FaxSid}
```

先程送信したFAXの情報を試しに取得してみます。無事送信できているようです。コストも取得できますし，送信したPDFを取得できるURLも記載されています。ちなみに，まだ100ページ以内なので通信費のみになっていますね。

```json
{
	"media_sid": "ME**************************",
	"status": "delivered",
	"direction": "outbound",
	"from": "+8150*******",
	"date_updated": "2017-12-07T09:55:17Z",
	"price": "-5.4",
	"account_sid": "AC*************************",
	"to": "+81********",
	"date_created": "2017-12-07T09:54:37Z",
	"url": "https://fax.twilio.com/v1/Faxes/FXae********************",
	"sid": "FXae********************",
	"duration": 24,
	"num_pages": 1,
	"quality": "fine",
	"price_unit": "JPY",
	"api_version": "v1",
	"media_url": "https://media.twiliocdn.com/fax/...........",
	"links": {
		"media": "https://fax.twilio.com/v1/Faxes/FXae********************/Media"
	}
}
```

## C#で送信する
まずnugetでTwilioライブラリをインストールします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/102503/eedd6da4-b834-5724-bebf-ce5863a460c4.png)

公式ドキュメントにサンプルコードが記載されているのでアカウント情報，FAX番号，PDFのURLを設定すれば動きます。

```csharp
// 公式ドキュメントから引用
// https://jp.twilio.com/docs/api/fax/rest/faxes#list-post
// Download the twilio-csharp library from twilio.com/docs/libraries/csharp
using System;
using Twilio;
using Twilio.Rest.Fax.V1;
using Twilio.Types;
using System.Collections.Generic;

class Example
{
    static void Main(string[] args)
    {
        // Find your Account Sid and Auth Token at twilio.com/console
        const string accountSid = "AC*************************";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        var to = "+81***";
        var mediaUrl = new Uri(
            "https://www.twilio.com/docs/documents/25/justthefaxmaam.pdf");

        var fax = FaxResource.Create(to, mediaUrl, from: "+8150********");

        Console.WriteLine(fax.Sid);
    }
}
```

デバッグで返り値の中を確認してみます。Sidを取得できました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/102503/e87df5d7-c0a1-1d7e-eaaf-d0281140c776.png)

## 感想
APIやライブラリが活用できるのでFAX機能を実装するのがとても楽です。処理も速く，料金も安いので魅力的なサービスだと思います。PDFファイルをローカルから直接アップロードできないので，そこは一仕事しないといけないかなと思います。もう少し試してみて，FAXサーバーに代わる選択肢として考えてみたいところです。