MenuBarGmail.app
コードはGitHubにあります。
インストールはHomebrewを使っているならCaskを使って
$ brew cask install rcmdnk/rcmdnkcask/menubargmail
でインストールできます1。
もしくは Releases ページから最新のバージョンをzipかtar.gzで取ってきて、 展開して中に入ってるMenuBarGmail.appを/Applicationsなり 好きな所に入れてください。
立ち上げると、最初にブラウザでGoogleの認証があるので、 許可してください。
そうすると、デフォルトではInboxに入ってる未読メールを取得しに行って、 未読数をメニューバーに表示します。
さらに、メニューバーのアイコンをクリックすると Unread messagesというメニューがあるので、 そこへマウスを持って行くと、 未読メッセージの到着時間、タイトル、メッセージの概略のリストが表示されます。
各メニューについて。
以下の様なメニューがあります。
- About: MenuBarGmailの情報を表示。
- Account: 現在使っているアカウント名が表示されます。
- ここをクリックするとGmailのトップページをブラウザで開きます。
- Reconnect: 認証を再度行います。
- アカウントを変更したい場合は、既定のブラウザで別のアカウントでログインしておいてReconnectしてください。
- Unread messages: 上にも書いた通り未読メッセージ一覧。
- ラベルを複数指定した時はラベル毎の未読数も表示されます。
- Set checking interval: チェックする間隔の設定。初期値は60(秒)。
- Set labels: チェックするラベルの設定。初期値は”“。
- Set filter: チェックするメッセージを検索するフィルタの設定。初期値は”“。
- labelsとfilterが共に空の場合はInboxの未読メールを検索します。
- Mail notification: 新しいメールが来た時に通知センターに知らせるかどうかのトグル。
- Start at login: ログイン時に自動でスタートするかどうかのトグル。
- Uninstall: MenuBarGmailのアンインストール。
- Quit: 終了。
こんな感じです。 ラベルを複数設定すると、
こんな感じでUnread messagesのメニューの中に もう一段階ラベル毎のメニューが出来ます。
また、各メッセージの部分をクリックすると、Gmailのそのメッセージのラベルの ページがブラウザに表示されます。
メッセージ毎のURL、と言うのを取得するのが無理だったので、 ラベル単位でブラウザを開く様にしています。
取り敢えずこれでやりたいことはなんとなく出来たかな、と言った感じ。
ビルド方法
コードを取ってきてビルドして使うことも出来ます。
今行っているのはOS X 10.11.1 El Capitan, Python 2.7.10な環境です。
ビルドするには
以下のパッケージをpip install
等を使ってインストールする必要があります。
また、下にも書いたように、 El Capitanにおいてpyobjc関連のエラーが出たり上手く行かない場合は pyobjc関連のパッケージをpip等で再インストールを試みてください。
後は、上のレポジトリを取ってきてsetup.pyのあるディレクトリで
$ python setup.py py2app
とすれば、distというディレクトリの中にMenuBarGmail.appが出来ます。
細かい所
作るにあたってちょっと問題があったところや細かい所について。
BaseHTTPServer
Googleの oauth2client を使っていますが、 この中で、
from six.moves import BaseHTTPServer
と言ったimportがあります。
pythonスクリプトをそのまま動かすと何も問題が無いのですが、 py2appを使ってアプリケーションにして動かそうとすると、 エラーのポップアップが出て、そこにあるコンソール表示を押して開いてみると
ImportError: No module named BaseHTTPServer
と言ったエラーが出ています。
このsixというライブラリーですが、 HomebrewでPythonをインストールしていると /usr/local/lib/python2.7/site-packages/six.py にあると思いますが、 この中では各モジュールの再定義を行っていて、 これはPython2と3の互換性を作るライブラリだそうです。
BaseHTTPServerは実際には
/usr/lib/python2.7/BaseHTTPServer.py
にあります。
これがpy2appでは上手く機能しないようで、 BaseHTTPServerを取り込めてない様です。
これを解決するに、sixを使わずにBaseHTTPServerを直接使う様に oauth2clientのモジュールを書き換えて使う方法もあるかと思いますが、 今回はMenuBarGmail.pyの中に
import BaseHTTPServer
という行を加える事で解決できました。 これでBaseHTTPServerは取り入れられるので、後は呼ぶ方はsixを使っても大丈夫なようです。
ただし、直接BaseHTTPServerを取り入れてるのでPython 3とは互換性がありません。 (Python 3ではこれはhttp.serverになっています。)
ssl.pyの問題
ssl(/usr/lib/python2.7/ssl.py)というライブラリの中にある
SSLSocket
というクラスの__init__
の中に、
1 2 |
|
と言ったコードがあるんですが、 ここで
IOError: [Errno 20] Not a directory
と言ったエラーが起きていました。
ここでsslはoauth2clientからhttplib2を通して呼ばれていて、 通常は
/usr/local/lib/python2.7/site-packages/httplib2/cacerts.txt
というファイルを読みに行っています。
これが、py2appでアプリを作ると、site-packagesが
MenuBarGmail.app/Contents/Resources/lib/python2.7/site-packages.zip
とzipされた状態で入っていて、さらに上のエラーが出ている部分では
...MenuBarGmail.app/Contents/Resources/lib/python2.7/site-packages.zip/httplib2/cacerts.txt
の様に、zipの下にある様な形で呼んでいました。 zipの中にはファイルは入っているのですが、これだと読めません。
これに関してはちょっと無理やりやっていますが、
まず、setup.pyの中で、OPTIONS
のresources
の値に
1 2 3 4 5 6 7 8 9 10 |
|
と、cacerts.txtをインクルードするようにしています。 これで、
...MenuBarGmail.app/Contents/Resources/cacerts.txt
に取り入れられるので、後は ssl.py内のca_certsを読んでる部分を
1 2 3 4 |
|
こんな感じでzipを使っていたら無理やりパスを変更する、 みたいなことをします。
MenuBarGmail.pyと同じディレクトリにssl.pyをコピーしてきて、 この変更を与えて置いておけば、 後はpy2app時にもこのssl.pyを使ってコンパイルしてくれます。
取り敢えずこれで動きますが、 これもPython 3に互換性が無いし、ちょっと考えもの。
ログイン項目に追加
通常、ログイン時に起動させるアプリを自分で登録するには、 システム環境設定 ユーザとグループログイン項目 へ行ってアプリを追加したりします。
最初はここにアプリを追加したり出来る様にしたのですが、 この辺りAPIがOS X 10.11から結構変更したらしく、 Webにあるような方法を使っても上手く行きません。
LaunchServicesのLSSharedFileList等をimportしたいのですが、 LaunchServicesがSharedFileList*に変更、となっています。 ただ、これをPythonから素直に
from SharedFileList import LSSharedFileList
としてもSharedFileListというそのようなモジュールはない、と言われてしまいます。
もう少し調べてみると、
ここに、
Apparently kLSSharedFileListSessionLoginItems was deprecated (OS X 10.11) already, and Apple is suggesting that using launch agents is a better practice – gbdavid Oct 23 at 7:59
ともあります。 そもそもログインアイテムに追加するようなやりかたはdeprecatedである、と。
代わりにLaunch Agentsを使いなさい、と。
Launch Agentsを使うには ~/Library/LaunchAgents/ に起動用plistファイルを入れてあげれば良いわけですが、 ファイルを作らないといけないのでちょっと面倒。
ですが、今回はこの方法を使っています。
メニューのStart at loginをクリックすると、 ~/Library/LaunchAgents/menubargmail.plistというファイルが 以下の様な内容で作成されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
簡単な雛形で、Label
には適当な名前を、
ProgramArguments
にはアプリの実行ファイルの位置を指定し、
RunAtLoad
をtrueにしておけば
ログイン時にこのファイルがロードされ(~/Library/LaunchAgentsにあるplistが自動でロードされる)
アプリが起動されます。
ここでちょっと詰まったのが実行ファイルの位置の指定です。
まず、実行ファイルはアプリそのものではなく、 アプリ内のContents/MacOS/に入ってる実行ファイルMenuBarGmailを 指定する必要があります(アプリをダブルクリック時にも実際にはこれが起動します)。
最初、MenuBarGmail.pyの中で、
os.path.abspath(__file__)
みたいにして自分へのパスを取ってきて使おうと思ったのですが、 アプリにコンパイルして実行してみても、このパスは
MenuBarGmail.app/Contents/Resources/MenuBarGmail.py
になります。 実際にはコンパイルした実行ファイルの
MenuBarGmail.app/Contents/MacOS/MenuBarGmail
になってないといけません。
ここでもちょっと無理やりですが、
1 2 3 4 5 6 7 |
|
こんな風に、アプリ内で呼ばれている場合、MacOS内の実行ファイルへ パスを変更するようにしました。 (これだと…/Resources/MenuBarGmail.pyを実行しても MacOSの方パスになりますが、まあ、実害はないでしょう、と。)
ログイン時の起動を止めるには
RunAtLoad
の値をfalse
にすれば実行は止められますが、
このファイルはログイン時起動に使うためだけのものであり、
下手にアプリを削除した時に残るの可能性も下げたいので、
Start at loginをオフにするとファイルごと消すようにしています。
oauth2client.tools.run()がdeprecatedになっていた
GoogleのApiを使って認証を取る時に、 最初
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
こんな感じで認証をしてましたが、 これだと
WARNING:root:This function, oauth2client.tools.run(), and the use of the gflags library are deprecated and will be removed in a future version of the library.
みたいな注意が出るようになっていました。
現在はrun_flow
という関数を使うのが正しいようです。
以下のように変更しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
run_flow
には最後に位置指定引数(positional arguments)が必要で
ここにtools.argparse.parse_args([])
を使って空の物を与えています。
上のAPIの説明では
1 2 3 4 5 6 7 |
|
と言った使い方になっていますが、今はコマンドラインから フラグを与える事はしないので(下手に渡されても困るので) ここでは空の物を渡すようにしています。
まとめ
ということで、MacでGmailの通知を行うアプリを作ってみました。
最近は Notify Pro というアプリを使っていましたが、 これと比べると複数のラベルや フィルターを付けて自由にメールを選べる所が優れています。
他のアプリでもその辺選べるのは余り無いと思います(使い方によっては意味ないんでしょうが)。
ちょっと見た目がチープで、特にメールの情報の部分が ただ一行に並べてるだけでちょっと見にくいのがあれですが、 取り敢えず欲しいものは出来たな、という感じ。
これ以上やろうと思うと、rumpsの中を直接変更するか、 同じような物を自分で作った方が早いかな、と言った感じもしますが、 せっかくなのでそのうちやるかも。
UI部分などはいっそのことSwiftとかで書いたほうが早いのかもしれませんが、 GoogleのApiとかがPythonだと慣れてて使いやすいのであれな感じ。
GmailのApiは今回はメールを読みだすだけに使ってますが、 メールを既読にしたりメールを送ったりするのも結構簡単に出来るので、 UIが一新出来たらその辺色々と入れる事はできるな、とは思います。
まあ、基本ブラウザで見るので、簡単な通知さえあれば良いわけですが。。。
-
既にrcmdnk/homebrew-rcmdnkcask をタップしてる場合は
$ brew update && brew cask install menubargmail