20 メール送信、ショートメール送信、プッシュ通知

メールをチェックして返信するのは時間のかかる作業ですが、メッセージごとに対応が異なるので、すべてのメールを処理してくれるプログラムを書くことはできません。それでも、メールの送受信ができるプログラムの書き方を知れば、メールに関連する作業の一部を自動化することはできます。

例えば、スプレッドシートに保存された顧客の年齢と住所に応じて異なる文面のメールを送りたいとしましょう。商用ソフトウェアではそのようなことができないかもしれません。自分でプログラムを書けば、そのようなメールの送信も可能で、コピーアンドペーストで浪費していた時間を大幅に節約できます。

コンピュータから離れている間に通知を行うショートメール(SMS)やプッシュ通知のプログラムを書くこともできます。実行に数時間を要する作業を自動化したとしたら、そのプログラムの実行状況を確認するのにたびたびコンピュータのところに行かなければならないのは煩わしいでしょう。実行が終了したときにショートメールを送れば、コンピュータから離れている間に別の作業に集中できます。

この章では、Gmailアカウントから簡単にメールの送受信ができるEZGmailモジュールと、無料でプッシュ通知を送ることができるntfyサービスを取り上げます。

警告

スクリプトでメールを送受信するアカウントを別に開設することを強くおすすめします。そうすればバグにより個人で使っているアカウントに悪影響(メールの削除や登録されている連絡先へのスパムメールの送信など)を及ぼすことはありません。最初は実際にメールを送ったり削除したりするコードをコメントアウトしてその代わりに一時的に print()を呼び出すdry runを実施することもおすすめします。こうすれば実際に実行する前にプログラムをテストできます。

Gmail API

Gmailはメールクライアント市場シェアの約3分の1を占めており、少なくとも1つはGmailアドレスを持っている人が多いでしょう。Gmailのセキュリティとアンチスパム対策のため、Gmailアカウントを操作するのに、Pythonの標準ライブラリのsmtplibモジュールとimaplibモジュールではなく、EZGmailモジュールを使うことをおすすめします。私は公式Gmail APIを利用してPythonからGmailを使いやすくしたEZGmailモジュールを書きました。EZGmailをインストールする方法は付録Aをご参照ください。

APIの有効化

コードを書く前にhttps://gmail.comでGmailアカウントのサインアップが必要です。そして、https://console.cloud.google.comのGoogle Cloudコンソールから、そのアカウントでGmail APIを設定します。これらの手順は第15章で詳しく説明したEZSheetsの設定と同じですので、この章では繰り返しません。新しいプロジェクトを作成し、今回はGoogle Sheets APIではなくGmail APIを有効化します。OAuth同意画面の設定では、https://mail.google.comをスコープに追加して、Pythonスクリプトからメールの送受信ができるようにします。手順を終えると認証情報ファイルとトークンファイルがあるはずです。

対話型シェルで以下のコードを入力してください。

>>> import ezgmail
>>> ezgmail.init()

エラーが発生しなければ、EZGmailが正常にインストールされています。

メールの送信

EZGmailの設定ができたら、関数を1回呼び出すだけでメールの送信ができるはずです。

>>> import ezgmail
>>> ezgmail.send('recipient@example.com', 'Subject line', 'Body of the email')

添付ファイルはsend()関数にリスト引数で指定します。

>>> ezgmail.send('recipient@example.com', 'Subject line', 'Body of the email',
['attachment1.jpg', 'attachment2.mp3'])

セキュリティのアンチスパム機能により、Gmailは同じ本文のメールを繰り返し送れないかもしれませんし(スパムのように見えるからです)、.exeファイルや .zipファイルを添付したメールを送れないかもしれません(ウィルスの可能性があるからです)。

CCやBCCを送信するためにccとbccのオプションのキーワード引数を設定することもできます。

>>> import ezgmail
>>> ezgmail.send('recipient@example.com', 'Subject line', 'Body of the 
email', cc='friend@example.com', bcc='otherfriend@example.com,
someoneelse@example.com')

token.jsonファイルがどのGmailアドレスについて設定したものかを忘れた場合は、ezgmail.EMAIL_ADDRESSで確認できます。

>>> import ezgmail
>>> ezgmail.EMAIL_ADDRESS
'example@gmail.com'

token.jsonファイルはパスワードと同じように取り扱ってください。誰かがこのファイルを入手すると、(Gmailパスワードの変更はできませんが)Gmailアカウントにアクセスできてしまいます。Google Cloudコンソールに戻ってトークンの認証情報を削除すると、token.json ファイルを失効させられます。EZGmailの利用を再開するには、新しい認証情報とトークンファイルの設定をもう一度しなければなりません。

メールの読み取り

Gmailは返信メールのメッセージを会話スレッドにまとめます。ブラウザやアプリでGmailにログインすると、(スレッドに1つのメールしかないとしても)個々のメールではなくメールスレッドが表示されます。

EZGmailには、会話スレッドを表すGmailThreadオブジェクトと、個々のメールを表すGmailMessageオブジェクトがあります。GmailThreadオブジェクトには、GmailMessageオブジェクトのリストを保持しているmessages属性があります。unread()関数は、直近の未読メールのGmailThreadオブジェクトのリストを返します(最大25件)。これをezgmail.summary()に渡せば、そのリストに含まれる会話スレッドの概要を表示します。

>>> import ezgmail
>>> unread_threads = ezgmail.unread()  # GmailThreadオブジェクトのリスト
>>> ezgmail.summary(unread_threads)
Al, Jon - Do you want to watch RoboCop this weekend?- Dec 09
Jon - Thanks for stopping me from buying Bitcoin. - Dec 09

summary()関数はスレッドの要約を手早く表示するのに使えますが、個々のメッセージ(やメッセージの一部)にアクセスするには、GmailThreadオブジェクトのmessages属性を調べます。messages属性には、スレッドを構成するGmailMessageオブジェクトのリストが格納されています。GmailMessageオブジェクトには、そのメールについての詳細を示すsubject、body、timestamp、sender、recipient属性があります。

>>> len(unread_threads)
2
>>> str(unread_threads[0])
"<GmailThread len=2 snippet= Do you want to watch RoboCop this weekend?'>"
>>> len(unread_threads[0].messages)
2
>>> str(unread_threads[0].messages[0])
"<GmailMessage from='Al Sweigart <al@inventwithpython.com>' to='Jon Doe
<example@gmail.com>' timestamp=datetime.datetime(2026, 12, 9, 13, 28, 48)
subject='RoboCop' snippet='Do you want to watch RoboCop this weekend?'>"
>>> unread_threads[0].messages[0].subject
'RoboCop'
>>> unread_threads[0].messages[0].body
'Do you want to watch RoboCop this weekend?\r\n'
>>> unread_threads[0].messages[0].timestamp
datetime.datetime(2026, 12, 9, 13, 28, 48)
>>> unread_threads[0].messages[0].sender
'Al Sweigart <al@inventwithpython.com>'
>>> unread_threads[0].messages[0].recipient
'Jon Doe <example@gmail.com>'

直近25件より多くの未読メールを取得したければ、maxResultsキーワード引数に整数を渡します。例えば、ezgmail.unread(maxResults=50)は直近50件の未読メールを返します。

ezgmail.unread()関数と同様に、ezgmail.recent()関数も直近25件のスレッドを返します。

>>> recent_threads = ezgmail.recent()
>>> len(recent_threads)
25
>>> recent_threads = ezgmail.recent(maxResults=100)
>>> len(recent_threads)
46

オプションのmaxResultsキーワード引数で件数の上限を変更できます。

メールの検索

ezgmail.unread()とezgmail.recent()を使ってメールを取得するだけでなく、ezgmail.search()を使ってメールを検索して取得できます。Gmailの検索ボックスにクエリを入力するのと同じ要領です。

>>> result_threads = ezgmail.search('RoboCop')
>>> len(result_threads)
1
>>> ezgmail.summary(result_threads)
Al, Jon - Do you want to watch RoboCop this weekend? - Dec 09

このsearch()呼び出しは、図20-1に示すように、検索ボックスにRoboCopと入力したのと同じ結果になります。

Screenshot of the search term “RoboCop” in the Gmail search bar.

図 20-1:GmailウェブサイトでRoboCopメールを検索した結果

unread()やrecent()と同様に、search()関数はGmailThreadオブジェクトを返します。search()関数には、以下のような検索ボックスに入力できる特別な検索演算子を渡すことができます。

'label:UNREAD' 未読メール

'from:al@inventwithpython.com' 差出人がal@inventwithpython.comのメール

'subject:hello' 件名に“hello”が含まれるメール

'has:attachment' 添付ファイルのあるメール

https://support.google.com/mail/answer/7190で検索演算子の一覧を確認できます。

添付ファイルのダウンロード

GmailMessageオブジェクトには、そのメッセージに添付されたファイルの名前のリストであるattachments属性があります。GmailMessageオブジェクトのdownloadAttachment()メソッドにその名前を渡せばファイルをダウンロードできます。downloadAllAttachments()ですべてのファイルを一気にダウンロードすることもできます。デフォルトでは、EZGmailは添付ファイルを現在の作業ディレクトリに保存しますが、downloadAttachment()とdownloadAllAttachments()のdownloadFolderキーワード引数に指定すればそのフォルダに保存します。例を示します。

>>> import ezgmail
>>> threads = ezgmail.search('vacation photos')
>>> threads[0].messages[0].attachments
['tulips.jpg', 'canal.jpg', 'bicycles.jpg']
>>> threads[0].messages[0].downloadAttachment('tulips.jpg')
>>> threads[0].messages[0].downloadAllAttachments(downloadFolder='vacation2026')
['tulips.jpg', 'canal.jpg', 'bicycles.jpg']

添付ファイルと同じ名前のファイルがすでに存在すれば、自動的に上書きします。

EZGmailにはここで紹介した以外にもいろいろな機能があります。https://github.com/asweigart/ezgmailでドキュメントを読めます。

ショートメール

(訳注:訳者が調べた限り、最初に紹介されるSMSメールゲートウェイを利用する方法では、日本の事業者と契約している携帯電話へのショートメールの送信をすることはできず、何らかの有料サービスを利用しなければショートメールを送信できないようでした。)

コンピュータよりもスマートフォンのほうが身近にあることが多いですから、ショートメールのほうがメールよりもすぐに気づくメッセージを送れます。また、ショートメールは短い文章なので、読んでもらえる可能性が高いです。信頼性はそこまで高くありませんが、最も簡単にショートメールを送るには、SMSメールゲートウェイを利用します。SMSメールゲートウェイとは、携帯電話プロバイダーが設置したメールサーバーで、メールからテキストを受け取ってショートメールとして送ります。

EZGmailモジュールかsmtplibモジュールを使ってメールを送信するプログラムを書けます。メールの送信先アドレスは、携帯電話の番号と携帯電話会社のメールサーバーから構成されます。例えば、Verizonと契約している212-555-1234の電話番号にショートメールを送るなら、2125551234@vtext.comにメールを送信します。メールの件名と本文がショートメールの本文に表示されます。

“sms email gateway provider name”とウェブで検索すれば、携帯電話プロバイダのSMSメールゲートウェイがわかります。表20-1でいくつかのプロバイダを一覧にまとめました。多くのプロバイダでは、最大160文字にメッセージを制限しているSMSのメールサーバーと、文字数制限のないMMS(Multimedia Messaging Service)メールサーバーを別々に構築しています。写真を送りたければ、MMSメールゲートウェイを利用して、メールにファイルを添付して送信します。

受信者の携帯電話プロバイダーがわからなければ、キャリア調査サイトで調べてみることができます。ウェブで“find cell phone provider for number”と検索すればキャリア調査サイトが見つかります。これらのサイトの多くは無料で調べられます(API経由で多数の電話番号を調べる場合は有料になるでしょう)。

表 20-1:プロバイダ別のSMSメールゲートウェイ

携帯電話プロバイダ

SMSメールゲートウェイ

MMSメールゲートウェイ

AT&T

number@txt.att.net

number@mms.att.net

Boost Mobile

number@sms.myboostmobile.com

Same as SMS

Cricket

number@sms.cricketwireless.net

number@mms.cricketwireless.net

Google Fi

number@msg.fi.google.com

Same as SMS

Metro PCS

number@mymetropcs.com

Same as SMS

Republic Wireless

number@text.republicwireless.com

Same as SMS

Sprint (now T-Mobile)

number@messaging.sprintpcs.com

number@pm.sprint.com

T-Mobile

number@tmomail.net

Same as SMS

U.S. Cellular

number@email.uscc.net

number@mms.uscc.net

Verizon

number@vtext.com

number@vzwpix.com

Virgin Mobile

number@vmobl.com

number@vmpix.com

Xfinity Mobile

number@vtext.com

number@mypixmessages.com

SMSメールゲートウェイは無料でシンプルに使えますが、大きな欠点があります。

  • ショートメールがすぐに確実に届くとは限らない
  • ショートメールが届いたか届かなかったかがわからない
  • 受信者がショートメールに返信できない
  • メールを送りすぎるとSMSメールゲートウェイからブロックされることがあり、何通送ればブロックされるかわからない
  • SMSメールゲートウェイでショートメールをいつ送れなくなるかわからない

SMSメールゲートウェイ経由でショートメールを送る方法は、緊急ではないメッセージを時々送る必要がある場合に適しています。特に大量のショートメールを、より確実に送りたければ、TwilioなどのサービスプロバイダーのAPIを使うほうがよいでしょう。これらのサービスは一般に定期課金や従量課金であり、申し込まなければ利用できません。国ごとに規制が異なり、料金も変わります。

無料で使えるプッシュ通知がショートメールの代替になります。プッシュ通知については次の節で説明します。

プッシュ通知

HTTPのpub-sub通知サービスを使えば、HTTPウェブリクエスト経由でインターネットから短いその場限りのメッセージを送受信できます。第13章でHTTPリクエストを行うライブラリを紹介しました。ここではそれを使ってhttps://ntfy.shのntfy(すべて小文字でnotifyと同じように発音します)という無料のオンラインサービスでやり取りしてみます。ntfyサービスは無料で登録不要です。

まず、通知を受け取るために、お使いの携帯電話にntfyアプリをインストールしてください。このアプリは無料でAndroidとiPhoneのアプリストアからインストールできます。ブラウザでhttps://ntfy.sh/appに移動することでも通知を受け取ることができます。

このアプリはntfyサービスのトピックに送られたメッセージを確認します。トピックはチャットルームやグループチャットのようなものだと考えてください。世界中の誰でも、トピックにメッセージを送ることができ、トピックをサブスクライブしてメッセージを受け取ることができます。自分たちだけにメッセージを送る予定なら、ランダムな文字の秘密のトピックを使ってください。そのトピック名をパスワードのように扱い、メッセージを読む人にだけ共有します。この章ではコード例でAlSweigartZPgxBQ42というトピックを使いますが、ランダムな文字や数字を含む自分用の秘密のトピックを使うことをおすすめします。トピックは大文字と小文字を区別します。トピックを秘密にしておくとしても、ntfyでパスワードやクレジットカード番号のような機密情報を送らないようにしてください。

プッシュ通知の送信

ntfyウェブサーバーに対してHTTPリクエストを行うだけで、トピックをサブスクライブしている人全員にプッシュ通知を送信できます。これはrequestsライブラリだけで可能です。ntfy固有のパッケージをインストールする必要はありません。

対話型シェルで以下の内容を入力してリクエストを送ってみてください。本章を通じて例に示すAlSweigartZPgxBQ42というトピックはご自身のランダムな秘密のトピックに置き換えてください。

>>> import requests
>>> requests.post('https://ntfy.sh/AlSweigartZPgxBQ42', 'Hello, world!')
<Response [200]>

プッシュ通知を送信するために、requests.post()を呼び出してPOSTのHTTPリクエストを行っています。第13章で紹介したウェブページをダウンロードするrequests.get()関数とは異なります。

トピックAlSweigartZPgxBQ42をサブスクライブしている人は、数秒内に(数分かかることもあります)“Hello, world!”というメッセージを受け取ります。https://ntfy.sh/AlSweigartZPgxBQ42で確認することもできます。

ntfyサービスにはいくつか制限があります。無料ユーザーは1日あたり250通のメッセージしか送れず、メッセージサイズは最大4,096バイトです。たくさんのトピックにメッセージを大量に送るとIPアドレスが一時的にブロックされる可能性があります。有料アカウントを取得すれば、ntfyウェブサイトについてのこうした制限を緩和できます。有料アカウントではトピックの予約ができ、投稿できる人を制限できます。予約されたトピックに投稿する権限がなければ、requests.post()関数呼び出しで<Response [403]>レスポンスになります。

4,096バイトの制限内であれば、メッセージをどのようなフォーマットにしても構いません。誰がトピックにメッセージを送ったのかを判定する方法はありませんから、“To”と“From”のラベルをメッセージのテキスト内に含めたい場合があるでしょう。第18章で紹介したJSONその他のデータ直列化フォーマットを利用することもできます。

ntfyアプリをスマホにインストールしてトピックをサブスクライブすれば、たった2行のコードでPythonのプログラムから通知を送れます。(時間のかかる)Pythonプログラムを実行してコーヒーを飲みに行き、プログラムの処理が終わればスマホで通知を受け取れます。

メタデータの伝送

メッセージは自由形式のテキストですが、ntfyではオプションでタイトル、優先度、タグなどのメタデータを付加できます。

タイトルはメールの件名と似ており、多くのアプリでメッセージの上に大きなフォントで表示されます。優先度は1(優先度最低)から5(優先度最高)まであり、デフォルトでは3です。優先度を高くしてもメッセージが速く届くわけではありません。受信者の側で指定した優先度以上のメッセージだけを表示するように設定できます。タグはメッセージをフィルタリングするために使えるキーワードです。メッセージのタイトルの横に表示する絵文字の名前を指定することもできます。https://docs.ntfy.sh/publish/#tags-emojisで利用できる絵文字の一覧を確認できます。

このメタデータはHTTPリクエストのヘッダーに含めますから、headersキーワード引数にメタデータの辞書を渡します。対話型シェルに以下の内容を入力してメタデータ付きのメッセージを投稿してみてください。

>>> import requests
>>> requests.post('https://ntfy.sh/AlSweigartZPgxBQ42', 'The rent is too high!', 
headers={'Title':'Important: Read this!', 'Tags': 'warning,neutral_face', 'Priority':'5'})
<Response [200]>

この機能はスマホで通知を見る人間にとって便利です。次の節で説明するように、プッシュ通知を受け取るPythonスクリプトを書くこともできます。

プッシュ通知の受信

requestsライブラリでHTTPリクエストを送信することによりトピックに投稿したメッセージを、Pythonプログラムで読み取ることができます。前節で紹介したコードでプッシュ通知を送ってから、対話型シェルで以下の内容を入力してください(トピックはメッセージを送信したトピックと同じにしてください)。

>>> import requests
>>> resp = requests.get('https://ntfy.sh/AlSweigartZPgxBQ42/json?poll=1')
>>> resp.text
'{"id":"1jnHKeFNqwnS","time":1797823340,"expires":1797866540,"event":
"message","topic":"AlSweigartZPgxBQ42","message":"Hello, world!"}\n
{"id":"wZ22cjyKXw1F","time":1797823712,"expires":1797866912,"event":
"message","topic":"AlSweigartZPgxBQ42","title":"Important: Read this!",
"message":"The rent is too high!","priority":5,"tags":["warning",
"neutral_face"]}\n'

通知を送るときにはrequests.post()関数を使いましたが、通知を受け取るときにはrequests.get()関数を呼び出していることに注意してください。また、URLの末尾が/json?poll=1となっていることにも注意してください。

これはポーリングによるメッセージの取得で、サーバーに存在する、トピックのメッセージがすべて返ってきます。ntfyメッセージをストリーミングで取得する方法もありますが、ポーリングのほうがシンプルです。poll=1の後にsinceURLパラメータを追加して、以下のような基準でメッセージを取得することもできます。

since=10m トピックの過去10分のメッセージをすべて取得します。sで秒を、hで時間を指定することもできます。例えばsince=2h30mと指定すると、過去2時間半のすべてのメッセージを取得します。

since=1737866912 エポック秒1737866912以降のメッセージをすべて取得します。エポック秒はtime.time()で返される値で、1970年1月1日からの経過秒数を表します。第19章で時間関数を紹介しました。

since=wZ22cjyKXw1F 'wZ22cjyKXw1F'というIDのメッセージ以降のメッセージをすべて取得します。

URLパラメータを追加するときは、アンド記号(&)で区切ってください。例えば、https://ntfy.sh/AlSweigartZPgxBQ42/json?poll=1&since=10mというURLでは、AlSweigartZPgxBQ42トピックの過去10分のメッセージをすべて取得します。ntfyサーバーに負荷をかけすぎないように、ポーリングを無限ループでできるだけ速く行わず1分に1回程度にしてください。通知をすぐに受け取りたければ、オンラインドキュメントを参照して、通知ストリームについて調べてください。

このHTTPレスポンスのテキストは、各行にJSONオブジェクトが含まれており、一つの正しいJSONオブジェクトではありません。splitlines()文字列メソッドを使って分割してからjsonモジュール(第18章で紹介しました)で解析します。対話型シェルで続けて以下のように入力してください。

>>> import json
>>> notifications = []
>>> for json_text in resp.text.splitlines():
...     notifications.append(json.loads(json_text))
...
>>> notifications[0]['message']
'Hello, world!'
>>> notifications[1]['message']
'The rent is too high!'

json.loads()関数がntfyから取得したJSONテキストをPythonの辞書に変換します。キーと値のペアを一つずつ見ていきましょう。

"id":"wZ22cjyKXw1F" 'id'キーの値は固有の識別文字列です。同じメッセージであっても通知を識別できます。

"time":1797823712 'time'キーの値は通知が作成された時点のエポック秒です。str(datetime.datetime .fromtimestamp(1797823712))を呼び出すと、'2026-12-20 21:28:32'のような人間に読みやすい文字列が返されます。

"expires":1797866912 'expires'キーの値は通知がntfyサーバーから削除される時点のエポック秒です。

"event":"message" 'event'キーの値は'message'、'open'、'keepalive'、'poll_request'のいずれかです。これらのイベントタイプについてはオンラインドキュメントで説明されています。当面の関心は'message'イベントです。

"topic":"AlSweigartZPgxBQ42" 'topic'キーの値は、URLのトピックを表す部分の繰り返しです。

"title":"Important: Read this!" 通知にタイトルがあれば、'title'キーがあり、値は文字列です。

"message":"The rent is too high!" 'message'キーの値は通知のテキストの文字列です。

"priority":5 通知に優先度があれば、'priority'キーがあり、値は1から5の整数値です。

"tags":["warning","neutral_face"] 通知にタグがあれば、'tags'キーがあり、値は文字列のリストです。これらの文字列値は表示される絵文字の名前の場合もあります。

この辞書の値を読み取ることにより、Pythonプログラムでrequestsライブラリを使って通知を受け取れます。ntfyサービスを利用すれば、インターネットを通じて相互にやり取りするプログラムを簡単に作れます(ただし、無料ユーザーは1日250通のメッセージに制限されることを忘れないでください)。

まとめ

私たちはインターネットや携帯電話のネットワークを利用して、さまざまな方法でお互いにやり取りしています。メールとショートメールがよく使われます。これらを通じてプログラムからやり取りでき、通知機能を実装できます。

セキュリティとスパム対策として、Gmailのような人気のあるメールサービスでは、標準のSMTPやIMAPプロトコルでサービスにアクセスできないことがあります。EZGmailパッケージはGmail APIのラッパーとして機能しますから、これを使えばPythonスクリプトからGmailアカウントにアクセスできます。プログラムにバグがあっても個人で使っているアカウントに問題を生じさせないように、スクリプトから利用するGmailアカウントを別に開設することを強くおすすめします。

ショートメールは、インターネット接続だけでは送信できない点で、メールとは少し異なります。SMSメールゲートウェイにメールを送ってショートメールを送ることができますが、送信先のキャリアを知らなければならず、またメッセージを確実に送れるとも限りません。自分宛にちょっとしたメッセージを送りたいのであれば、https://ntfy.shのシステムでプッシュ通知が利用できます。ntfyアプリをスマホにインストールして、Pythonスクリプトからトピックにメッセージを送ります。

これらのモジュールを使いこなせるようになれば、特定の条件を満たしたときにプログラムから通知やリマインダーを送ることができます。プログラムを実行しているコンピュータから離れたところにメッセージを送れるようになります。

練習問題

  1. Gmail APIを利用する際の、認証情報ファイルとトークンファイルとは何ですか?

  2. Gmail APIにおいて、GmailThreadオブジェクトとGmailMessageオブジェクトはどう違いますか?

  3. ezgmail.search()でどのようにすれば添付ファイルを見つけられますか?

  4. ショートメールを送るのにSMSメールゲートウェイを利用する欠点は何ですか?

  5. ntfyでプッシュ通知を送受信するのに使うPythonのライブラリは何ですか?

練習プログラム

以下の練習プログラムを書いてください。

傘のリマインダー

第13章では、requestsモジュールでhttps://weather.govからデータをスクレイピングする方法を説明しました。自分が朝起きる前に天気を確認してその日の予報が雨かどうかを調べるプログラムを作成します。雨予報なら家を出る前に傘を忘れないように自分に通知するプログラムを書いてください。

自動登録解除

メールアカウントを走査して、本文中に登録解除のリンクがあるメールをすべて探し、自動的にそのリンクをブラウザで開くプログラムを作成します。このプログラムはお使いのGmailアカウントにログインする必要があります。第13章で紹介したBeautiful Soupを使って、unsubscribe(登録解除)という言葉がHTMLのリンクタグ内にあるかどうかを確認します。そのURLのリストを作成したら、webbrowser.open()を使って自動的にそのリンクをブラウザで開きます。

このリストから登録解除するには手動での操作が求められることがあるでしょう。多くの場合で確認リンクのクリックが必要です。それでもこのスクリプトは登録解除リンクが含まれるすべてのメールを探すという手間を省いてくれます。

メールやプッシュ通知によるコンピュータ制御

メールまたはntfyを15分ごとにチェックして、自分が送った指示があればその指示を自動的に実行するプログラムを作成します。例えば、BitTorrentはピアツーピアのダウンロードシステムです。qBittorrentのような無料のBitTorrentソフトウェアを使えば、サイズの大きなメディアファイルをコンピュータにダウンロードできます。BitTorrentのリンク(合法なもの)を送ると、プログラムがそのメールまたはntfyの通知をチェックし、そのメッセージに基づいてリンクを抽出して、qBittorrentを起動しファイルのダウンロードを開始します。この仕組みにより、外出中に自宅のコンピュータにダウンロードを開始させることができ、家に帰る頃にはダウンロードが終わっているという寸法です。

第19章でsubprocess.Popen()関数によりコンピュータ上のプログラムを起動する方法を説明しました。例えば、以下のコードは、torrentファイルを指定してqBittorrentを起動します。

qbProcess = subprocess.Popen(['C:\\Program Files (x86)\\qBittorrent\\
qbittorrent.exe', 'shakespeare_complete_works.torrent'])

もちろん、確かに自分が送ったメッセージによりプログラムを実行したいはずです。そのためにメッセージにパスワードを含めるのがよいでしょう。というのも、メールの差出人(from)を偽装するのは簡単だからです。プログラムはメッセージをチェックして指示を見つけたらそのメッセージを削除します。そうしないと何度も指示を実行してしまいます。コマンドを実行するごとに確認メッセージを送る機能を追加するのもよいでしょう。プログラムを実行するコンピュータの前に座っていないので、ログを残すと望ましいです(第5章を参照)。

qBittorrentプログラムには、ダウンロードが完了したら自動的に終了する機能があります(他のBitTorrentプログラムにもあります)。第19章でPopenオブジェクトのwait()メソッドにより起動したアプリケーションが終了したときを判定できると説明しました。wait()メソッドを呼び出すと、qBittorrentの実行中はプログラム実行をブロックしますから、qBittorrentが終了してからダウンロードが完了した旨のメッセージを自分に送れます。

このプロジェクトの追加機能はいろいろ考えられます。行き詰まったら、https://nostarch.com/automate-boring-stuff-python-3rd-editionからこのプログラムの実装例をダウンロードしてください。