twilioとSendGridとherokuでキャリアメール代替プッシュ通知

# Motivation
au携帯をpovoにしてキャリアメールが使えなくなり、長女の公文終了時に来るメールをキャリアメールに転送してプッシュ通知してたのが、通常メールだと気付かず迎えを待たせてしまう。

gmailのフィルタで重要にタグ付けすれば、iPhoneでプッシュ通知できるはずなのだが、どう頑張っても私のiPhoneは通知してくれないので、gmailからメール転送してtwilioからsmsを送るようにした忘備録
こんなことせずとも海外キャリアだとemailからsmsに転送してくれるんだけど。。。
yahooメールとかに転送すればいいのですが。留守電は自宅の固定電話に転送するようにした。

# やったこと
基本は下記twilioサイトのとおりなのだが、github上にあるソースコードがpython2用のものなので、直し直し動かした。
[Send And Receive SMS Messages via Email with Twilio and SendGrid](https://www.twilio.com/blog/2014/05/send-and-receive-sms-messages-via-email-with-twilio-and-sendgrid.html)

## ドメイン取得
gmailからのメール転送をトリガにSendGridのInbound Parse Webhookでheroku上のweb apiを叩くためにメールを受けるドメインとる必要があり、下記サイトを参考にfreenomというところでタダでドメイン取ろうとしたが、全然登録できないので、あきらめてAWSのRoute 53で年間9ドルでドメイン取得、DNSもRoute 53を使った。時間を無駄にしたので、やっぱりタダより高いものは無い。
[SendGrid 新人成長記　第六回　Domain Authentication: メールの到達率を高めるために](https://sendgrid.kke.co.jp/blog/?p=12074)
![写真0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/6e3b3e02-b1df-eb7b-c26e-a90648b6ebfe.png)

## DNS登録
Route 53でドメイン取得したら、上記[サイト](https://sendgrid.kke.co.jp/blog/?p=12074)を参考にsendgridのSettings/Sender Authenticationにドメインを登録
![写真1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/f5591ab4-38cd-784a-3521-3598f544b1d9.png)

SendGridのホストを新しいドメインのホストで引けるようにDNS(Route 53)に指示されるがままCNAMEを設定、新ドメイン宛のメールもmx.sendgrid.netが受けるようMXレコードも設定
![写真2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/f7f21816-2881-64be-81f5-41e980bb03cd.png)
DNSの反映は10分以上かかった。

## twilioで電話番号購入
(2022/10/5追記)
twilioが8末で個人利用できなくなったので、[twilioからvonageに移行してみた](https://qiita.com/kamotsuru/items/3021d968c604ae635a16)で、vonageに移行してます。


twilioでSMS送信元となる電話番号を購入する。日本の番号ではSMS送れないようなのでUSの番号を買う。番号維持料は157円/月くらい。
![写真4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/3cd28540-9455-3488-10dd-3d956c05008d.png)
買った電話番号をProgrammable Messaging/Messageing serviceに紐づける。
![写真5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/9a58f997-9380-039b-99aa-91842b1134ca.png)

## heroku上にWebアプリ構築

(2022/9/11追記)
herokuのfree serviceは11末で廃止になるので[heroku上のweb serviceをrenderに移行してみた。](https://qiita.com/kamotsuru/items/e90a9e887c4aa2ec8bba)で、render.comに移行してます。


前記twilioの[サイト](https://www.twilio.com/blog/2014/05/send-and-receive-sms-messages-via-email-with-twilio-and-sendgrid.html)を参考に

```
$git clone https://github.com/jpf/sms-via-email.git
$cd sms-via-email
```

virtual env環境作る

```
$python3 -m venv venv
$source venv/bin/activate
```

git初期化

```
(venv)$git init
```

herokuにログインして、Webサイトを作成。web browserにパスワード入力求められる。

```
(venv)$heroku login
(venv)$heroku create

Creating app... done, ⬢ xxxxxxx-xxxxx-xxxxx
https://xxxxxx-xxxxx-xxxxx.herokuapp.com/ | https://git.heroku.com/xxxxxxx-xxxxx-xxxxx.git
```

上記URL+/handle-emailを後述sendgridのSettings/Inbound Parseに登録する。

```
(venv)$heroku git:remote -a xxxxxxx-xxxxx-xxxxx
```

twilioのDashboardに出てくるACCOUNT SID/AUTH TOKENを環境変数として設定
![写真6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/13291dcd-f391-8571-3c13-5a781b1f8fcc.png)

```
(venv)$heroku config:set TWILIO_ACCOUNT_SID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(venv)$heroku config:set TWILIO_AUTH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

前述の通りgit上のapp.pyはpython2で書かれている、twilioのlibraryが更新されているので、python3で動くように修正(下記diff参照)
app.pyの中で勝手にtwilioのweb api叩いてくれるので、メールをSMSに転送するだけなら前述以上のtwilioサイト上の設定はいらない。

```
3,4c3
< import configparser
< from urllib.parse import urlparse, parse_qs
---
> import ConfigParser
9c8
< from twilio.rest import Client
---
> from twilio.rest import TwilioRestClient
24c23
<     user_list = configparser.ConfigParser()
---
>     user_list = ConfigParser.ConfigParser()
34c33
< twilio_api = Client(konf.twilio_account_sid, konf.twilio_auth_token)
---
> twilio_api = TwilioRestClient()
93c92
<         except Exception as e:
---
>         except Exception, e:
108c107
<     except Exception as e:
---
>     except Exception, e:
155c154
<         print(str(address_book))
---
>         print str(address_book)
186c185
<     except InvalidInput as e:
---
>     except InvalidInput, e:
206,213d204
<         warn("envelope: "+str(envelope))
<         warn("request.form[to]: "+str(request.form['to']))
<         warn("request.form[from]: "+str(request.form['from']))
<         warn("request.form[text]: "+str(lines[0]))
<         if envelope['to'][0] != request.form['to']:
<             email_from = 'zzzzzzz@gmail.com'
<         else:
<             email_from = envelope['from']
215,216c206,207
<             'to': email_to_phone(envelope['to'][0]),
<             'from_': lookup.phone_for_email(email_from),
---
>             'to': email_to_phone(request.form['to']),
>             'from_': lookup.phone_for_email(envelope['from']),
219c210
<     except InvalidInput as e:
---
>     except InvalidInput, e:
223d213
<         warn("sms: "+str(sms))
227,228c217,218
<         print("oh no")
<         print(str(e))
---
>         print "oh no"
>         print str(e)
237c227
<         print("in debug mode")
---
>         print "in debug mode"
```
206~216行目あたりは、転送かけると、ヘッダとエンベロープのfrom/toが異なるので、違った場合は転送元(zzzzzzz@gmail)に紐付けた番号からsms送るように修正

requirement.txtも同様に修正

```
10c10
< phonenumbers
---
> phonenumbers==6.0.0
15,16c15,17
< twilio
< unittest2
---
> twilio==3.6.6
> unittest2==0.5.1
> wsgiref==0.1.2
```
address-book.cfgを作成

```
[users]
+8180xxxxxxxx: 8180xxxxxxxx@mail.yyyyyyy.de
+1571wwwwwww: zzzzzz@gmail.com
```

herokuのgitにpush

```
(venv)$git status
(venv)$git add -A
(venv)$git commit -m "hoge"
(venv)$git remote show heroku
(venv)$git push heroku master
```

## SendGridのInbound Parse Webhook設定
[SendGrid 新人成長記　第七回　Inbound Parse Webhookを用いてメールを受信する](https://sendgrid.kke.co.jp/blog/?p=12114)
上記サイトを参考にSendGridのSettings/Inbound Parseで新ドメイン宛のメールを受信したら前述heroku上のweb api https://xxxxxx-xxxxx-xxxxx.herokuapp.com/handle-email を叩くように設定する。host名にmailがついてますが、再登録時につけるとエラーになったのでmailなしドメイン名だけで登録し直してます。
![写真3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/8c0b7249-d993-f8e4-5c08-d2ced60af94d.png)

# メール転送
gmail(zzzzzzz@gmail.com)から8180xxxxxxxx@mail.yyyyyyy.deにメールを送ったときの`heroku logs`抜粋、ちゃんとtwilio上で購入した+1571wwwwwwwからSMSきた。

```
2021-04-10T06:55:57.204402+00:00 app[web.1]: WARNING:root:['テスト\r\n']
2021-04-10T06:55:57.216212+00:00 app[web.1]: WARNING:root:{'to': '+8180xxxxxxxx', 'from_': '+1571wwwwwww', 'body': 'テスト\r\n'}
2021-04-10T06:55:57.920606+00:00 heroku[router]: at=info method=POST path="/handle-email" host=xxxxxxx-xxxxx-xxxxx.herokuapp.com request_id=ee5d9529-4778-40aa-9e35-71ea0269b839 fwd="167.89.119.77" dyno=web.1 connect=1ms service=1186ms status=200 bytes=192 protocol=https
```

その後、Google Voiceの番号を持ってたので、そちら宛に送るように設定した。Google VoiceはiPhoneでちゃんとプッシュ通知してくれる。。。

固定費 約~~250~~300円/月(番号維持費、ドメイン月割り、DNSホスト)、DNS queryとSMSの従量課金がどのくらいになるか~~、また後日~~

USの番号宛だとSMS1円/通、日本宛だと8円/通
https://www.twilio.com/sms/pricing/us
https://www.twilio.com/sms/pricing/jp
![Screen Shot 2021-04-20 at 13.32.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/b869ef91-4e8e-e522-e511-9c77fda02310.png)

DNSクエリはメール100万通？くらい送らないと課金発生しなさそう?
![Screen Shot 2021-04-16 at 21.05.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/12d6f988-36fd-727a-05a8-a45ac1e640b3.png)