IMAPプロトコルでメール通知
思うところがあり、メールが来た時に本文を見て一部をslackに通知したくなった
そこで、少し調べているとIMAP4というプロトコルがあるということを知りメール通知 + 本文取得を実装したのでメモ
IMAP4プロトコルとは
IMAP4は、オンラインでサーバ上に設けたメールボックスにアクセスし、操作や管理を行うことができる。そのため、オンラインでサーバにアクセスできる環境であれば、外出先や異なるマシンからでも同じメッセージを確認できるという利点をもっている。IMAP4は、フリーメールとして提供されることの多いWebメールや、モバイルメールなどでよく利用されている。
これに加えてIdleという機能があり、IMAPサーバーからメールの通知が受け取れる機能があるらしい
さらに各社フリーメールで提供されているらしいので、Gmail API等に依存しない形で実現できそうだ
今回使用したコマンド
通知と本文の取得だけであればすべてのコマンドを使う必要がなく、今回は↓のコマンドのみを使用した
LOGIN
LOGIN ユーザー名 パスワード
ユーザー名とパスワードでログインを行う
SELECT
SELECT ラベル名
メール操作の対象をラベル名で指定する
IDLE
IDLE
コマンドを実行するとサーバーがアイドル状態になり、メールを受信するとサーバーから通知が送られる
通知される際にFETCHで利用できるメッセージ番号も同時に送られる
FETCH
FETCH メッセージ番号 データ名
メッセージ番号のメールを取得する、データ名を指定することで目的のデータが手に入る。
今回は、メールの平文が欲しかったので BODY[1]
のみ使用することにした
LOGOUT
LOGOUT
ログアウトする
コマンドを試してみる
上記のコマンドをopensslで試してみる
kaneta@tk2-239-29469:~/kakin-notify$ openssl s_client -quiet -crlf -connect imap.gmail.com:993 depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority verify return:1 depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA verify return:1 depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2 verify return:1 depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = imap.gmail.com verify return:1 * OK Gimap ready for requests from 2001 ? LOGIN {ユーザー名} {パスワード} * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE ENABLE MOVE CONDSTORE ESEARCH UTF8=ACCEPT LIST-EXTENDED LIST-STATUS LITERAL- SPECIAL-USE APPENDLIMIT=35651584 ? OK {ユーザー名} authenticated (Success) ? SELECT INBOX * FLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing) * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing \*)] Flags permitted. * OK [UIDVALIDITY 1] UIDs valid. * 7556 EXISTS * 0 RECENT * OK [UIDNEXT 7667] Predicted next UID. * OK [HIGHESTMODSEQ 441443] ? OK [READ-WRITE] INBOX selected. (Success) ? IDLE + idling * 7557 EXISTS ? NOOP ? BAD Could not parse command ? FETCH 7557 BODY[1] * 7557 FETCH (FLAGS (\Seen) BODY[1] {14} Hello IMAP!= ) ? OK Success ? LOGOUT * BYE LOGOUT Requested ? OK 73 good day (Success) read:errno=0 kaneta@tk2-239-29469:~/kakin-notify$
メール通知 + 本文取得は↓を繰り返せば良いことになる
? IDLE + idling * 7557 EXISTS ? NOOP ? BAD Could not parse command ? FETCH 7557 BODY[1] * 7557 FETCH (FLAGS (\Seen) BODY[1] {14} Hello IMAP!= ) ? OK Success
成果物
プロトコルを完全に網羅するのは辛すぎるので、今回の目的(通知 + 本文の取得)として利用できるようにラップしたパッケージを練習中のgolangで書いた
作成したパッケージでGmailに来るGoogle Playの課金メールを監視して、合計金額をslackに通知するbotも作った github.com
ハマりポイント
- 送信時はcrlfが末尾にないとレスポンスが一切帰ってこない(消費4時間)
- yamlの読み込みに使用する構造体のメンバは公開メンバ(頭文字大文字)にしないとだめ(消費1時間)
phantomJS + agouti(golang)でブラウザ操作自動化 事始め
思うところがあり今日はブラウザ操作の自動化を行っていた
丁度golangを勉強中ということもあり、phantomJS + agoutiの組み合わせでやってみた(別にgoでやる必要はありませんが..)
環境
centos6
go version go1.8.3 linux/amd64
phantomjs 2.1.1
インストール等
Agoutiの手順通りにインストールすればOK Agouti
phantomjsはcentosであれば↓のページのように簡単にインストールできる qiita.com
サンプル
すごく眠たいので、googleを1280*720解像度でキャプチャするだけ
package main import ( "github.com/sclevine/agouti" "log" ) func main() { driver := agouti.PhantomJS() if err := driver.Start(); err != nil { log.Fatalf("error:%v", err) } defer driver.Stop() page, err := driver.NewPage(agouti.Browser("phantomjs")) if err != nil { log.Fatalf("error:%v", err) } page.Size(1280, 720) if err := page.Navigate("https://google.com"); err != nil { log.Fatalf("error:%v", err) } page.Screenshot("./google.jpg") }
google.goとかそんな名前で保存して go run google.go
とすると、フォルダにgoogle.jpgができあがる
何かに使っていこう
2017/07/05
本日も実装多目の日
Jenkinsのジョブなるものを久しぶりに作った
ジョブをcron実行できるのはログも残るし便利だな
2017/07/04
今日はひたすら実装していた。
2017/07/03
自分の配属してるチームに研修を終えた新卒が一人はいってきた
預かり所属の用なので一年いるかわからないらしいが期待の新人だ
Google PageSpeed Insightsが0点だったので対策
前提として個人で制作後、その後の運営は他人がやっているサイトがあります
そのサイトを先日知った、Google PageSpeed Insightsで採点すると100点中0点だった…
そこで指摘されたうちいくつか対策をしたのでメモ
画像を最適化する
jpg画像を投稿することが多いサイト(投稿する人は画像サイズとか気にしない人)なので、最大の要因になっているとあたりをつけて真っ先に対応した
対策は↓のqiitaを参考にjpegoptimインストールしで画像を最適化した
wordpressなのでuploadsフォルダ以下に年月単位でフォルダ分けされているので、↓を実行して一気に変換
find ./uploads -type f -name "*.jpg" | xargs jpegoptim --strip-all --max=40
ただ、ファイル数が多かったり一つ1mbしてたりと、実行した後1分ほど処理が返ってこず、その間サイトが閲覧できなかった
実行する際は注意したほうがよいかも…
これらを施した段階で点数は0→65になった
圧縮を有効にする
gzip圧縮を活用してなかったので有効にした
webサーバーはapacheを利用しているので↓の拾ってきた設定をhttpd.confに書き込んだ
すみません、どこで拾ってきたか忘れてしまった…
<IfModule mod_deflate.c> SetOutputFilter DEFLATE # Mozilla4系などの古いブラウザで無効、しかしMSIEは除外 BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html # gifやjpgなど圧縮済みのコンテンツは再圧縮しない SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary SetEnvIfNoCase Request_URI _\.utxt$ no-gzip # htmlやcssなどは圧縮 AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/atom_xml AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE application/x-httpd-php </IfModule>
これで65→68
ブラウザのキャッシュを活用する
キャッシュの設定をしていなかったので↓の設定を.htaccessに書き込んだ
<IfModule mod_expires.c> ExpiresActive On ExpiresByType text/css "access plus 1 weeks" ExpiresByType application/javascript "access plus 1 weeks" ExpiresByType application/x-javascript "access plus 1 weeks" ExpiresByType text/javascript "access plus 1 weeks" ExpiresByType image/gif "access plus 1 weeks" ExpiresByType image/jpeg "access plus 1 weeks" ExpiresByType image/png "access plus 1 weeks" ExpiresByType application/x-javascript "access plus 1 weeks" </IfModule>
警告の指摘は消えたが点数は68からかわらなかった
がっつり対策する必要がないので、とりあえずここまでで一旦完了
この後は時間があるときにでも..