formからの値をArrayでserializeしてるActiveRecordのカラムに設定をする

class User < ActiveRecord::Base
  serialize :aliases, Array
end
form_for(@user) do |f|
  = f.text_field :aliases

> User.new(params[:user])

serialize Arrayにしているのでセッターには文字列設定するとエラーになっちゃう。
text_fieldヘルパーだと文字列になっているし普段serialize使わないしどうしようかなと考えた結果ラッパー作ってしまえばmodel内で収まるのでよさそうだと思った。

class User < ActiveRecord::Base
  serialize :aliases, Array

  def aliase_list=(value)
    @aliases = value.split(/,/)
  end 
  
  def aliase_list
    @aliases.join(",")
  end
end
form_for(@user) do |f|
  = f.text_field :aliase_list

viewだとセパレータ(,)以外が入力されるのでtagitとか使うのがいいのではないか。

> User.new(params[:user])
これでインスタント作れるようになった。

imap ruby

imapサーバに接続してメールを読むサンプルコード動かすも既読フラグをつけれなくてつけれなくてうーーーーんとなっていたらサンプルコードが間違っていた(´・_・`)
(docecotのdebug.logにreadonlyなのにstoreしてんぞタコって出るの期待していたけど出ませんでした)

ドキュメント見直してたら、メールボックスを選択するexamine メソッドは読み取り専用になるので、既読フラグつけれないということが発覚。
フラグをつける時には、メールボックスの選択にselectメソッドを使え、ルーク。
http://docs.ruby-lang.org/ja/2.2.0/method/Net=3a=3aIMAP/i/examine.html

[9] pry(#<ImapClient>)> imap.select('INBOX')
=> #<struct Net::IMAP::TaggedResponse tag="RUBY0003", name="OK", data=#<struct Net::IMAP::ResponseText code=#<struct Net::IMAP::ResponseCode name="READ-WRITE", data=nil>, text=" Select completed (0.000 secs).">, raw_data="RUBY0003 OK [READ-WRITE] Select completed (0.000 secs).\r\n">
[10] pry(#<ImapClient>)> imap.examine('INBOX')
=> #<struct Net::IMAP::TaggedResponse tag="RUBY0004", name="OK", data=#<struct Net::IMAP::ResponseText code=#<struct Net::IMAP::ResponseCode name="READ-ONLY", data=nil>, text=" Examine completed (0.000 secs).">, raw_data="RUBY0004 OK [READ-ONLY] Examine completed (0.000 secs).\r\n">
[11] pry(#<ImapClient>)> imap.select('INBOX')

戻り値のオブジェクトにREAD-ONLYって書いとるがな(´・_・`)



今週は、3時に寝て8時に起きるという5時間睡眠で生活した。今仕事のメインタスクはコーディングをやってる。コード書くと目が覚めるので日中は割と平気。
ただし、Twitterとか見ているとかなり眠くなって14時くらいになると30分くらい昼寝しないと厳しい。調査系タスクだと眠すぎて厳しそう。
振り返ると体にすごく悪い感じはする。それとよく寝坊しなかったなと思った。

virtual mailbox にメール配送

メールボックスへの配送にdovecot-lmtpを使っているので、local配送もlmtp使ったらいけるのは??と思ったらvirtual mailboxに配送できた。

/etc/postfix/main.cf
mydestination = localhost, jiikko.com, prpr-antena.com
local_transport = lmtp:unix:private/dovecot-lmtp
$ echo "ko" | mail 1438866268@prpr-antena.com -s "ko" 

==> /var/log/dovecot-lmtp.log <==
Aug 06 22:07:39 lmtp(7487): Info: Connect from local
Aug 06 22:07:40 lmtp(1438866268@prpr-antena.com): Info: vJMrOxtcw1U/HQAADOlgoQ: msgid=<20150806130739.E7156340679@prpr-antena.com>: saved mail to INBOX
Aug 06 22:07:40 lmtp(7487): Info: Disconnect from local: Successful quit

ローカルでvirtualmailboxのテストするの厳しい

技術検証を外のサーバでやると微妙なレイテンシあったりサーバをまだ契約してない場合まだお金払いたくないので、VirtualBoxだとかで立てたサーバでvirtualdomainのテストをやりたい。

1) mydestination

/etc/postfix/main.cf の mydestination にvirtualdomainを設定して、mailコマンド実行するとvirtualdomainのテスト(virtualdomainのメールボックスへの配送が)できるんじゃないか期待したけどダメでした。
mydestination に書いているドメインはvirtualでは配送されず、local配送になるのでUNIXユーザへ配送しようとして unkwon userになる。

2) fake dns

mxレコードを自分自身に指定できれば、mailコマンドからvirtualが配送してくれるのでは?

mxレコードを上書きするにはdnsmasqを使えばできた。
http://dev.tapweb.co.jp/2009/09/77

/etc/dnsmasq.conf
mx-host=jiikko.com, hoge.local,50
mx-host=prpr-antena.com, hoge.local,50
cname=prpr-antena.com,hoge.local
cname=jiikko.com,hoge.local
$ echo "ko" | mail 1438375085@jiikko.com -s "ko"

to=<1438375085@jiikko.com>, relay=none, delay=589, delays=589/0.02/0/0, dsn=5.4.6, status=bounced (mail for jiikko.com loops back to myself)

だめでした。

まとめ

postmapでクエリのテストできるみたいなのでこれで少しはカバーできそう。

$ sudo postmap -q 1438375085@jiikko.com mysql:/etc/postfix/virtual.mysql
1438375085@jiikko.com,deployer@localhost
$ sudo postmap -q 1438375085@jiikko.com mysql:/etc/postfix/vmailbox.mysql     
jiikko.com/1438375085/

メールボックスへの配送もしてくれたらimapクライアントからの接続テストもできたのに....

warning: do not list domain localhost in BOTH mydestination and virtual_mailbox_domains

歌丸です。

virtual_mailbox_domains と mydestination の両方に"localhost"を記述していないのに、タイトルにある文字列がwaringとして出てたのでそれを潰した話。

設定ファイル

/etc/postfix/main.cf
virtual_mailbox_domains = mysql:/etc/postfix/virtual_domain.mysql
mydestination = localhost
/etc/postfix/virtual_domain.mysql
hosts = 127.0.0.1                                                                                                                                                                                                                                                                                                          
user = postfix
dbname = postfix
query = SELECT virtual_domains.name FROM virtual_domains;
# queryには全件返してる。

メールを受信したタイミングでコマンドを実行したいの図

外から受け取るメール => virtual mailbox へ配送
                                   => virtual_alias_maps => aliases => pipeからのコマンド実行

調べる

タイトルのログは、virtual_mailbox_domains のルックアップテーブル形式にmysqlを使っている時だけ吐いているっぽい。

virtual_mailbox_domains = jiikko.com, prpr-antena.com 

だと吐かない。


postfix mysqlのドキュメント読んだら、全件返すな自分自身返せ(意訳)と書いてた(´・_・`)
http://www.postfix.org/mysql_table.5.html

なので

/etc/postfix/virtual_domain.mysql
hosts = 127.0.0.1                                                                                                                                                                                                                                                                                                          
user = postfix
dbname = postfix
query = SELECT virtual_domains.name FROM virtual_domains where name = %d;

とすればOK。

英語厳しいしむちゃくちゃ眠い。六花の勇者がもしろい(原作買いました)。

dovecot quota した

quotaは、メールボックスの残り容量に上限を設ける機能で今回その設定をした。

postfixでローカルの配送をする場合、quotaにはmboxのみ対応していてmaildirでもquotaを設定するにはDVAというパッチを当てる必要があるらしい。
(なんで公式にmaildirに対応しないんだろう?2012年より前からパッチ充てるフローがあるあるみたい)

パッチあてるかーと思ってquotaについて調査している時、ちょうど1週間くらいDVAをホストしているsourceforgeがサイトダウンしている時期だった。ので代替案を探していたら、dovecotのlmtpでローカル配送をすればpostfixにパッチなしでmaildirのquotaを使えるとどこかの記事に書いて有ったのでlmtpを使ったらできた。

lmtpという実態がいまいちわからないんだけど、local配送をlmtpにすることでpostfixのキューを減らせたり、パフォーマンスがいい、そしてldaよりイイとのことらしい。
(ちなみにldaは、必要になったらプロセスを都度作成しては終わったら消えるみたいなのだけど、lmtpだとプロセスが常駐しているようでオーバーヘッド少ないみたい。)

設定内容は、postfixのmain.cfにdovecot-lmtpを参照するよう書けば動くので完全にブラックボックスです。本当にありがとうございました。

##
## LMTP specific settings
##

protocol lmtp {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins quota
  info_log_path = /var/log/dovecot-lmtp.log

  userdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf.ext
  }
}

service lmtp {
  executable = lmtp -L
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    user = postfix
    group = postfix
    mode = 0600
  }
}

設定内容はdovecot公式に書いている通りすれば、maildirのrootにmaildirsizeというファイルが作成される。上限を超えるとbounceしてくれてた。
http://wiki2.dovecot.org/Quota/Configuration

それとimapクライアントからquotaの情報もとれた。

2.1.0 :017 > imap.getquotaroot("INBOX")
 => [#<struct Net::IMAP::MailboxQuotaRoot mailbox="INBOX", quotaroots=["User quota"]>, #<struct Net::IMAP::MailboxQuota mailbox="User quota", usage="33", quota="10240">] 

以上。

lmtp

postfixでローカル配送するのに、lmtpを使うとパフォーマンスがいいらしいのでlmtp使ってみたがログに `passdb didn't return userdb entries, trying the next userdb` とでてくる(´・ω・`)

==> /var/log/dovecot-debug.log <==
Jul 23 22:23:54 auth: Debug: prefetch(koji@jiikko.com): passdb didn't return userdb entries, trying the next userdb

protocal lmtp内に `/etc/dovecot/conf.d/auth-sql.conf.ext` で使っているusedbをコピペしたら↑のログでなくなった。

protocol lmtp {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins quota
  info_log_path = /var/log/dovecot-lmtp.log

  userdb { 
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf.ext
  }
}

service lmtp {
  executable = lmtp -L
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    user = postfix
    group = postfix
    mode = 0600
  }
}

ちなみにlmtp使うと上記にあるuserdb分のDBクエリが発生しているので、local配送と比べてDBクエリが1つ多くなる。あんま変わらないんだろうけどちょっと気になった。
まあpostfixDVAパッチあてなくてもquota(maildirsize)が使えるっぽいのでlmtp一択なのですが。