Java 向けの疑似 SMTP サーバの Web アプリを作った

疑似 SMTP サーバ

Ruby だと MailCatcher のような疑似(mock / fake / dummy) SMTP サーバがある。 開発中のアプリケーションでうっかり本番用のメールアドレスにメールを送信しないために便利である。 Java の現場では、疑似 SMTP サーバを入れるために Ruby をインストールするのはちょっと面倒である。 ランタイムが不要な言語で作られた疑似 SMTP サーバもいくつかあるが、文字コードの扱いがイマイチで日本語のメールを正しく扱えるものが少ないという問題もある。 そこで Java の現場で簡単に使える 疑似 SMTP サーバが必要だと考えた。

mail-baku

Java で使える疑似 SMTP サーバの Web アプリである mail-baku を開発した。

https://github.com/mallowlabs/mail-baku

ビルドした war は mail-baku/releases からダウンロードできる。

Tomcatwebapps に war ファイルを放り込んで、(Apache httpd を使っている場合には AJP の設定すれば) http://localhost:8080/mail-baku/ で mail-baku にアクセスできる。 この Web アプリケーションは Web アプリであると同時に SMTP サーバとしても動作している。 ポート番号は 1025 番で SMTP を待ち受けている。

f:id:mallowlabs:20190304205405p:plain

この Web アプリケーションが立ち上がった状態で、0.0.0.0 の 1025 番に向けてメールを送信するように開発中のアプリケーションを設定すれば、本番でうっかりメールを外部に送信することを防ぐことができる。

Tomcat を使ってない場合でもソースをクローンして、mvn ninja:run とすれば Web アプリケーションと SMTP サーバが立ち上がる。

制約事項

BCC のメールアドレスは見ることができない。 これは SMTP サーバに利用している subethasmtp の制限なので許して欲しい。

まとめ

Java の現場で使える MailCatcher 風の疑似 SMTP サーバを作った。 Tomcat が立ち上がっていて、Ruby は入っていないという環境でメール機能をテストしたいという場合には使ってみて欲しい。

Node-RED の OAuth2 で refresh token が再起動で消えてしまう件

環境

Node-RED v0.19.5

TL;DL

Node-RED は credential の値の永続化をデプロイのタイミングでしか行わない。 そのため、いくつかの OAuth2 のプラグインは Node-RED を再起動したタイミングで refresh token を忘れてしまうため、再度 OAuth2 の設定をしなおす必要がある。 該当の Issue は https://github.com/node-red/node-red/issues/1055

node-red-contrib-fitbit-token

私は Fitbit の OAuth2 の access token を expire なしで取れるノードを自作している。

https://github.com/mallowlabs/node-red-contrib-fitbit-token

f:id:mallowlabs:20190114122407p:plain

このノードで access token を取得して、FItbit API を叩くことで、Mackerel に心拍数を送ったり、Slack に送って体重を通知したりしている。

この Node が Node-RED を再起動すると、refresh token が invalid になってしまい、再度ログインが必要なるという問題に悩まされていた。

Node-RED のソースを読む

Node-RED のソースを読むと、credential の 永続化はワークフローのデプロイのタイミングでしか行われていないことがわかった。 つまり refresh token を更新した結果は、メモリ上でしか保存されないので、当然 Node-RED を再起動すると refresh token が失われて、access token を refresh できなくなる。

その知識をもとに、GitHub を見るとたしかに Provide a way to programmatically save Credentials nodes (OAUTH) #1055 という issue があった。 どうやら既知の問題なので今後に期待ということがわかった。

解決策

Node-RED の credential API を使っている限り、永続化はできないので、refresh token のみ別のストレージに保存する必要がある。 私は Node-RED を IBM Blumix 上で動かしているので、 Cloudant DB に保存することにした。

対応した diff がこちら

https://github.com/mallowlabs/node-red-contrib-fitbit-token/commit/8cc70027cc2ec6e5e356b0d2f1e65149fcba4cbd?w=1

これで IBM Blumix 上で動作させることが必須になる代わりに、 Node-RED を再起動しても Fitbit の再ログインが求められることはなくなった。

まとめ

Node-RED の OAuth2 を扱うノードが再起動によって refresh token を忘れてしまうという事実はあまり知られていないと感じたので、記事にしてみた。 これを知らずに自分の書いたコードがどこか間違っていると思い続けて調査に無限の時間を費やしたのでこの記事で誰かが救われると嬉しい。

Quick JUnit の Ruby 版っぽい VSCode 拡張作ってみた

この記事は Misoca+弥生 Advent Calendar 2018 2日目の記事です。 Misoca では Ruby を書くお仕事をしています。 Misoca にジョインする前はずっと Java を書くお仕事をしていたので、Ruby 開発について日々勉強中といった感じです。

Qucik JUnit Plugin for Eclipse

Java を書いていた時には Quick JUnit Plugin for Eclipse というプラグインを活用していました。 このプラグイン

  • Cmd+9 (Ctrl+9) で テストコードと実装コードをトグルできる
  • Cmd+0 (Ctrl+0) で テストコードを JUnit ですぐに実行できる
  • テストコードを実行する際に、カーソル位置のテストのみを実行できる

という特徴を持った Eclipse プラグインです。 Javaテスト駆動開発(TDD)をする時にとても重宝していました。

Visual Studio Code 拡張

現在 Ruby を書くときには VSCode を使っています。

  • VSCode でも Quick JUnit と似た操作感で RSpec を実行したい
  • VSCode の拡張を書いてみたい

という理由から VSCode 拡張を作ってみることにしました。

vscode-quick-rspec

できたのがこちらの拡張です → vscode-quick-rspec

動作イメージは以下のような感じです。

f:id:mallowlabs:20181202111700g:plain

Cmd+9 (Ctrl+9) で実装とテストを切り替えて、Cmd+0 で RSpec を実行しています。 もちろん RSpec の実行は現在のカーソル行を実行します。

これで Quick JUnit のような感覚で、Ruby で開発できるようになりました。

自分で使う用なので Marketplace には上げてませんが、使ってみたい場合には

$ git clone https://github.com/mallowlabs/vscode-quick-rspec.git
$ mv vscode-quick-rspec $HOME/.vscode/extensions/

して VSCode を再起動してください。 自分用なのでエラー処理とかは適当です(言い訳)

VSCode 拡張開発の所感

雛形のジェネレーターがしっかりしているので、すぐに開発をスタートできるのが好印象でした。 デバッガもあるし、言語も ES6 で async/await なんかも使えるのでとても快適です。 API も今回作った拡張に必要な分は揃っているという感じで、いろいろできそうだなと感じました。

作っている途中でもうあることに気づく法則

何かを作っていると途中ですでにそれがあることに気づくことはよくありますが、今回も作っている途中で似たような拡張がたくさんあることに気づいてしまいました…。

今回は VSCode 拡張の作り方の勉強になったのでよかった、ということにしたいと思います。

まとめ

VSCode 拡張は思いの外簡単に作れたので、生産性を向上させるような拡張を思いついたらまた作ってみたいです。

明日は @corocn が 「ALB + Lambda + Ruby をセキュアに」する話を書いてくれるみたいです。楽しみですね。

はてなダイアリーからはてなブログに引っ越した

2019年春「はてなダイアリー」終了のお知らせと「はてなブログ」への移行のお願い - はてなダイアリー日記 ということだったので、はてなダイアリーからはてなブログに引っ越してきた。

旧 URL: http://d.hatena.ne.jp/mallowlabs
新 URL: https://mallowlabs.hatenablog.com/

またボチボチ記事を書いていきたい。

Windows 10 Creators Update にアップデートしたら WMDC と ckw-mod が壊れた

以下の2点が壊れて仕事で困ったので、対応策を共有。

  1. Windows Mobile Device Center が起動しなくなった
  2. ckw-mod の表示が壊れた
環境
  • Windows 10 Home / バージョン 1703 / OS ビルド 15063.138
  • Windows Mobile Device Center v6.1
  • ckw-mod 0.9.1.0

Windows Mobile Device Center v6.1 が起動しなくなった

Windows Mobile Device Center v6.1 が起動しなくなって困った。
再インストールしようとしたらインストーラすら起動しなくて更に困った。

対処法
  1. 「サービス(services.msc)」を起動する
  2. Windows Mobile 2003 ベース デバイスの接続」を右クリックして「プロパティ」を開く
  3. 「ログオン」タブを開き、「ローカル システム アカウント」にチェックし、「デスクトップとの対話をサービスに許可」にチェックを入れて OK をクリックする


ckw-mod の表示が壊れた

git diff して日本語を含む内容を表示すると表示が崩れるようになって困った。
Console2 に乗り換えようとしたら Console2 も壊れてて更に困った。
コマンドプロンプトの API が壊れているらしいコマンドプロンプトの設定でなんとかなるらしい ので設定を変更する。

2017.05.28 追記

KB4020102 で修正されたらしい ので、Windows Update を 当てよう。

対処法
  1. コマンドプロンプト(cmd.exe)を開き、タイトルバーを右クリックして「プロパティ」をクリックする
  2. 「従来のコンソールを使う(再起動が必要)」にチェックを入れて OK をクリックする


まとめ

Windows 10 Creators Update 何が変わったのかわからない割にはいろいろ壊れていてとにかく最高!

Wercker からマイグレーションせよというメールが来たので対応してみた

CI サービスの Wercker からマイグレーションせよという以下のメールが来た。

Attention: Manual Migration required on your Wercker Account

Hi Mallowlabs,

We informed you a couple of months ago that we're going to start deprecating our non-Docker (or classic) stack in the future.

Since you have projects on our classic stack, we are pleased to announce that the time has come.

Non Docker-based applications will require a manual effort to migrate please follow this link to our stack migration wizard to start the process.
...

今回、このマイグレーションに対応した記録を共有する。

まずは https://app.wercker.com/applications/migrate にアクセスする。


Heroku deploy targets を使っているのがまずいらしい。

該当アプリの Deploys から edit をクリックする。

更に Edit をクリックする。

Delete Target をクリックして、Deploy Target を削除する。

もう一度 https://app.wercker.com/applications/migrate にアクセスすると、以下のような表示になるのでチェックを入れて、Migrate をクリックする。

リロードすると Up-to-date になる。

アプリの Workflows タブから Add new pipeline をクリックする。

Name に heroku-deploy、YML Pipeline name に deploy を入力して Create をクリックする。

環境変数を設定する画面に遷移するので、以下の3つを入力する。

  • HEROKU_APP_NAME
  • HEROKU_USER
  • HEROKU_KEY

Workflows タブに戻って build の後ろに heroku-deploy Pipeline を追加する。

ここでやっとソースを変更する。

diff --git a/config/mongoid.yml b/config/mongoid.yml
index ccd80db..b658599 100644
--- a/config/mongoid.yml
+++ b/config/mongoid.yml
@@ -3,7 +3,7 @@ development:
   database: asakusa_satellite_development

 test:
-  host: <%= ENV['WERCKER_MONGODB_HOST'] || 'localhost' %>
+  host: <%= ENV['MONGO_PORT_27017_TCP_ADDR'] || 'localhost' %>
   database: asakusa_satellite_test

 production:
diff --git a/wercker.yml b/wercker.yml
index 0ce7ab5..80c1a0b 100644
--- a/wercker.yml
+++ b/wercker.yml
@@ -1,6 +1,6 @@
-box: wercker/rvm
+box: ruby:2.3
 services:
-  - wercker/mongodb
+  - id: mongo
 build:
     steps:
         - bundle-install
@@ -19,3 +19,10 @@ build:
     after-steps:
         - mzp/http-notify:
             url: $DASHBOZU_URL
+deploy:
+  steps:
+    - heroku-deploy:
+        key: $HEROKU_KEY
+        user: $HEROKU_USER
+        app-name: $HEROKU_APP_NAME

ポイントとしては以下の通り。

  • box を指定したところは Docker コンテナを指定するようにする
  • MongoDB などの services も Docker になるのでホスト名等を工夫する
  • Heroku deploy は heroku-deploy を使うようにする

このあと、 変更を master に push すれば Wercker でビルド後、Heroku に deploy される。

所感

Wercker のドキュメントが Wercker Workflows に対応していないものが多くて苦労した。
この記事が誰かの役にたてば嬉しい。

ホビー用途の mLab でリモートバックアップする

環境

  • MongoDB 3.2.11
  • dbxcli 1.4.0
  • heroku-toolbelt 3.43.15
  • heroku-buildpack-mongodb Rev. 59b9e8d
  • heroku-buildpack-dbxcli Rev. d67845a

モチベーション

ホビー用途の Heroku アプリで mLab アドオンを Sandbox プランで利用している。
mLab の DB のバックアップは Sandbox プランでは提供されないので、リモートバックアップを設定したい。
ホビー用途なので、できればお金をかけない範囲で行いたい。

heroku-buildpack-mongodb

Heroku の buildpack に MongoDB のバイナリを使えるようにする heroku-buildpack-mongodb があるので、これを使って Heroku Scheduler で mongodump を呼び出せば、バックアップは取れそうである。

ストレージ

問題はストレージをどうするかである。
普通に考えたら S3 だが、ホビー用途で AWS はあまり使いたくない。IAM や MFA など、考えることが多いためだ。
そこで Dropbox を利用することを考えた。
dbxcli というワンバイナリで Dropbox を操作できるツールを Heroku Scheduler から使えれば良さそうだ。

heroku-buildpack-dbxcli

ということで heroku-buildpack-dbxcli という Buildpack を作った。
この Buildpack を使えば、dbxcli を Heroku 上から簡単に使うことができる。

Heroku 設定

まずは以下のような backup.sh を作って git commit しておく。

#!/bin/sh

# backup xxx
$ mongodump -h xxx.mongolab.com --port xxx -d heroku_appxxx -u heroku_appxxx -p xxx -o xxx_dump --excludeCollection=system.users

# archive
$ tar cvzf xxx_dump.tgz xxx_dump

# upload to Dropbox
$ dbxcli put xxx_dump.tgz Backups/xxx_dump.tgz

次にその Git リポジトリを Heroku に push する。

$ heroku create --buildpack http://github.com/goodeggs/heroku-buildpack-mongodb.git
$ heroku buildpacks:add --index 2 http://github.com/mallowlabs/heroku-buildpack-dbxcli.git
$ heroku config:add DROPBOX_AUTH_TOKEN=<your token>
$ git push heroku master

Dropboxトークンは、手元で dbxcli で一度ログインして ~/.config/dbxcli/auth.json の内容を見て取得する(ちょっとかっこ悪い)。

あとは backup.sh を Heroku Scheduler から呼び出せば、Dropbox に mongodump の結果が保存されるようになる。

まとめ

  • dbxcli は便利!
  • Heroku Buildpacks も便利!