# Copyright (C) 2003-2005 Kouichirou Eto, All rights reserved.

require "net/smtp"
$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
require "qwik/config"
require "qwik/util-kconv"

module Qwik
  class MailAddress
    def initialize(mail)
      @mail = mail.to_s
    end

    def to_s
      @mail
    end

    def valid?
      return false if @mail.nil?
      (/\A([0-9a-zA-Z_.+-]+)@([0-9a-zA-Z_.-]+)\z/ =~ @mail) != nil
    end

    def obfuscate
      @mail.sub(/(@.).*/, '\1...')
    end

    # foo@QuickML.CoM => foo@quickml.com
    # "foo"@example.com => foo@example.com
    def normalize
      name, domain = @mail.split("@")
      name.gsub!(/^"(.*)"$/, '\1')
      return name + "@" + domain.downcase if domain
      @mail
    end

    def normalize!
      @mail = normalize
    end

    def self.obfuscate(s)
      s.gsub(/([0-9a-zA-Z_.-]+)@([0-9a-zA-Z_.-]+)\.([0-9a-zA-Z_-]+)/) {|m|
	MailAddress.new(m).obfuscate
      }
    end
  end

  # FIXME: This class is too ad hoc. Use other mail library.
  class Mail
    def initialize(from=nil, to=nil, subject=nil, content=nil)
      @from, @to, @subject, @content = from, to, subject, content
    end
    attr_accessor :from, :to, :subject, :content
  end

  class Sendmail
    def initialize(config, host=nil, port=nil)
      @config = config
      @host, @port = host, port
      @host = @config.smtp_host if @host.nil?
      @port = @config.smtp_port if @port.nil?
    end

    def sendmail(mail)
      send(mail.from, mail.to, mail.subject, mail.content)
    end

    def send(from, to, subject, content, host=@host, port=@port)
      efrom    = encode_field(from.to_s)
      eto      = encode_field(to.to_s)
      esubject = encode_field(subject)
      contentorg = <<EOM
From: #{efrom}
To: #{eto}
Subject: #{esubject}
Content-Type: text/plain; charset="ISO-2022-JP"

#{content}
EOM
      content = contentorg.sjistojis
      if @config.test
	$smtp_sendmail = [host, port, from, to, content]
      else
	Net::SMTP.start(host, port) {|smtp|
	  smtp.send_mail(content, from, to)
	}
      end
      content
    end

    def encode_field (field)
      field.gsub(Regexp.new("[\x81\x40-\xef\xf7]\\S*\\s*", nil, "s")) {|x|
	x.scan(Regexp.new(".{1,10}", nil, "s")).map {|y|
	  "=?iso-2022-jp?B?" + y.tojis.to_a.pack("m").chomp + "?="
	}.join("\n ")
      }
    end
  end
end

if $0 == __FILE__
  require "test/unit"
  $debug = true
end

if $debug
  class TC_MailAddress < Test::Unit::TestCase
    def test_mailaddress
      @m = Qwik::MailAddress.new("user@e.com")
      assert_equal("user@e.com", @m.to_s)
      assert_equal(true, @m.valid?)
      assert_equal(false, Qwik::MailAddress.new(nil).valid?)
      assert_equal(false, Qwik::MailAddress.new("invalid!@example.com").valid?)
      assert_equal(true, Qwik::MailAddress.new("invalid@example").valid?)
      assert_equal(false, Qwik::MailAddress.new("invalid").valid?)
      assert_equal(false, Qwik::MailAddress.new("").valid?)
      assert_equal("user@e...", @m.obfuscate)
      assert_equal("user@e.com", @m.normalize)
      assert_equal("user@e.com",
		   Qwik::MailAddress.new("user@e.com").normalize)
      m = Qwik::MailAddress.new('"user"@e.com')
      assert_equal("user@e.com", m.normalize)
      assert_equal('"user"@e.com', m.to_s)
      m.normalize!
      assert_equal("user@e.com", m.to_s)

      # test_obfuscate_str
      assert_equal("t@e...", Qwik::MailAddress.obfuscate("t@e.com"))
      assert_equal("a t@e... b s@f... c",
		   Qwik::MailAddress.obfuscate("a t@e.com b s@f.com c"))
    end
  end

  class TC_SendMail < Test::Unit::TestCase
    def setup
      @config = Qwik::Config.new(true)
      @config.test = true
      @sendmail = Qwik::Sendmail.new(@config)
    end

    def test_sendmail
      content = <<"EOM"
From: from@example.com
To: to@example.com
Subject: testsubject
Content-Type: text/plain; charset="ISO-2022-JP"

test
EOM
      assert_equal(content,
		   @sendmail.send("from@example.com", "to@example.com",
				  "testsubject", "test"))

      # test_sendmail_encode
      assert_equal("t", @sendmail.encode_field("t"))
      assert_equal("=?iso-2022-jp?B?GyRCJCIbKEI=?=",
		   @sendmail.encode_field("あ"))
      assert_equal("=?iso-2022-jp?B?GyRCJCIkJBsoQg==?=",
		   @sendmail.encode_field("あい"))
      assert_equal("=?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQrJC0kLyQxJDMbKEI=?=\n =?iso-2022-jp?B?GyRCJDUkNyQ5JDskPRsoQg==?=", @sendmail.encode_field("あいうえおかきくけこさしすせそ"))
    end
  end
end
