自作 Twitter メールゲートウェイ
たまに無性に何かプログラミングしたくなります.少し前に,Twitter 用のメールゲートウェイが欲しくなったので,せっかくだから自作しました.
特殊な機能は必要なかったので,純粋に投稿だけできるものにしました.全体を二つの機能,すなわちメールの body を 160 オクテット以内に縮める機能,そして Twitter API で投稿する機能に分けて,それぞれを独立したプログラムにしました.使う時は,パイプで繋げます.
セキュリティ的には,From のアドレスを strcmp(3) 型の比較で検査しているだけです.携帯からの投稿のみを許可するのでしたら,Received ヘッダを見て検査を厳しくしたりできそうですね.とりあえず以下にソースを.
まず,メールの body を取り出して,160 オクテットに縮める前処理プログラムです.これは prepare と名づけました.メール body の charset を ISO-2022-JP に固定しているところが情けないですが,私個人の要求にはこれで十分でした.
メッセージ長を160オクテット以内に縮める処理で,Ruby のマルチバイトに対応した正規表現の恩恵に授かっています.正規表現を使わずに同じ処理を記述するとしたら次のようになるでしょう.UTF-8 は各文字の先頭1オクテットで1文字に必要なオクテット数が分かるので,メッセージ文字列を先頭から走査して160オクテットになる直前までを残すようにします.正規表現の方が何をやっているのか一目瞭然ですよね.
#! /usr/bin/ruby -Ku require 'tmail' require 'kconv' FROM = ARGV.shift # reading mail source if ARGV[0] mail = TMail::Mail.load(ARGV[0]) else mail = TMail::Mail.parse(STDIN.read) end if mail.from[0] != FROM # p [1, mail.from] exit 1 end if mail.content_type != 'text/plain' # p [2, mail.content_type] exit 1 end message = Kconv.toutf8(mail.body) if message.length < 156 suffix = ' [M]' else suffix = '... [M]' while message.length >= 160 - suffix.length message = /.$/.match(message).pre_match end end message.chomp! message += suffix puts message
つぎは,Twitter API を使って投稿するプログラム.update と名づけた.
#! /usr/bin/ruby -Ku require 'net/http' require 'uri' ID = ARGV.shift PASSWORD = ARGV.shift source = ARGV[0] || STDIN.read exit 1 if source.length > 160 message = URI.encode(source) res = Net::HTTP.start('twitter.com') do |http| req = Net::HTTP::Post.new('/statuses/update.xml') req.basic_auth(ID, PASSWORD) http.request(req, "status=#{message}") end puts res
これらのプログラムを適当なパスに配置し,例えば $HOME/.qmail-xyzzy に以下の様に書くことで使えるようになります.
|preline /path/to/prepare dare_sore@docomo.ne.jp | /path/to/update ID PASS > $HOME/.twitter.log