# Web::Interface::RubyMail
# Copyright(c) 2002 MoonWolf <moonwolf@moonwolf.com>
require 'web/interface/basic'

module Web
  module Interface
    class RubyMail < Basic
      EOL = "\r\n"
      def initialize(opt={})
        require 'rmail/parser'
        require 'rmail/message'
        require 'rmail/address'
        require 'rmail/serialize'
        require 'net/smtp'
        require 'nkf'
        @opt       = opt
        @input     = opt[:stdin]   || $stdin
        @output    = opt[:stdout]  || $stdout
        @env       = opt[:env]     || ENV
        @smtp      = opt[:smtp]    || 'localhost'
        @from      = opt[:from]
        @eof       = false
      end
      
      # 標準入力からRequestを組み立てる
      def request(arg={})
        return nil if @eof
        @eof = true
        super
        req = Web::Request.new
        #
        parser = RMail::Parser.new
        msg = parser.parse(@input)
        #
        req.request_id   = msg.header['message-id'] || Web::Common::unique_id
        if msg.multipart?
          req.method = 'POST'
        else
          req.method = 'GET'
        end
        from = RMail::Address.parse(msg.header['from'])[0]
        to   = RMail::Address.parse(msg.header['to'])[0]
        req.query_string = ''
        req.script_name  = $0
        req.path_info    = to   ? to.local    : ''
        req.host         = to   ? to.domain   : ''
        req.remote_addr  = ''
        req.remote_host  = from ? from.domain : ''
        req.remote_ident = ''
        req.remote_user  = from ? from.local  : ''
        # env
        req.env['GATEWAY_INTERFACE'] = 'NoraMail/0.1'
        req.env['SERVER_PROTOCOL']   = 'SMTP'
        
        # header
        if len = msg.header['content-length']
          req.header['CONTENT-LENGTH'] = len
        end
        type = msg.header['content-type']
        req.header['CONTENT-TYPE'] = type if type
        msg.header.each {|key,value|
          req.header.add key,value
        }
        
        # cookie
        #if cookie = req.header['COOKIE']
        #  req.cookies.parse(cookie)
        #end
        
        
        ## param
        cmd = nil
        charset = nil
        if msg.multipart?
          msg.each_part {|part|
            type= part.header['content-type']
            if cmd==nil && type=~/text\/plain(\s*;\s*charset="?(.+?)"?)/i
              charset = $2
              cmd = part.body
            end
          }
        else
          type = msg.header['content-type']
          if type=~/text\/plain(\s*;\s*charset="?.+??"?)/i
            charset = $1
            cmd = msg.body
          end
        end
        
        case charset
        when /ISO-2022-JP/i
          cmd = NKF.nkf('-Je', cmd)
        when /Shift_JIS/i
          cmd = NKF.nkf('-Se', cmd)
        end
        
        cmd.scan(/^([a-zA-Z0-9_\-]+)\s*=(?:"(.*?)"|(.*?)\n)/m) {
          key = $1
          value = $2 || $3
          if req.method = 'GET'
            req.query.add key,value
          else
            req.form.add key,value
          end
        }
        
        get_session_id req
        req
      end # CGI#request
      
      def response(req, rsp)
        super
        msg = RMail::Message.new
        
        type = rsp.header['content-type']
        charset = nil
        if type=~/charset=(".+?"|[^ \t\n]+)/i
          charset = $1 || $2
        end
        body = rsp.body
        case charset
        when /ISO-2022-JP/i
        when /EUC-JP/i
          body = NKF.nkf('-Ej', body)
          type.sub!(/euc-jp/i,'ISO-2022-JP')
        when /Shift_JIS/i
          body = NKF.nkf('-Sj', body)
          type.sub!(/Shift_JIS/i,'ISO-2022-JP')
        end

        from   = @opt[:from]
        from_a = RMail::Address.new(from)
        to     = req.header['from']
        to_a   = RMail::Address.new(to)
        msg.header['from'] = from
        msg.header['to']   = to
        msg.header['content-type'] = type
        subject= req.header['subject']
        subject.sub!(/^(Re:\s*)+/,'')
        msg.header['subject'] = 'Re: ' + subject
        msg.body = body
        
        Net::SMTP.start(@smtp, 25) {|smtp|
          mailsrc = ''
          s = RMail::Serialize.new(mailsrc)
          s.serialize(msg)
          smtp.send_mail( mailsrc, from_a.address, to_a.address )
        }
        
        #
        req.cleanup
      end # CGI#response
    end # CGI
  end # Interface
end # Web
