Skip to content

Commit

Permalink
Receiving mail
Browse files Browse the repository at this point in the history
  • Loading branch information
rust committed Jan 18, 2011
1 parent fb61e60 commit 355ad8a
Show file tree
Hide file tree
Showing 10 changed files with 352 additions and 12 deletions.
1 change: 0 additions & 1 deletion .rspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@
--format
progress
mtime
-b
15 changes: 12 additions & 3 deletions lib/jpmobile/emoticon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def self.external_to_unicodecr_docomo(str)
end
end

# +str+ のなかでDoCoMo絵文字をUnicode数値文字参照に置換した文字列を返す
# +str+ のなかでau絵文字をUnicode数値文字参照に置換した文字列を返す
def self.external_to_unicodecr_au(str)
str.gsub(AU_SJIS_REGEXP) do |match|
sjis = match.unpack('n').first
Expand All @@ -49,11 +49,12 @@ def self.external_to_unicodecr_au(str)
end

# +str+ のなかでau絵文字をUnicode数値文字参照に置換した文字列を返す。(メール専用)
def self.external_to_unicodecr_au_mail(str)
def self.external_to_unicodecr_au_mail(in_str)
str = Jpmobile::Util.ascii_8bit(in_str)
str.gsub(AU_EMAILJIS_REGEXP) do |match|
jis = match.unpack('n').first
unicode = AU_EMAILJIS_TO_UNICODE[jis]
unicode ? ("&#x%04x;"%unicode) : match
unicode ? Jpmobile::Util.ascii_8bit("\x1b\x28\x42&#x%04x;\x1b\x24\x42"%unicode) : match
end
end

Expand All @@ -65,6 +66,14 @@ def self.external_to_unicodecr_softbank(str)
"&#x%04x;" % (unicode+0x1000)
end
end
def self.external_to_unicodecr_softbank_sjis(str)
# SoftBank Shift_JIS
str.gsub(SOFTBANK_SJIS_REGEXP) do |match|
sjis = match.unpack('n').first
unicode = SOFTBANK_SJIS_TO_UNICODE[sjis]
"&#x%04x;" % (unicode+0x1000)
end
end
def self.external_to_unicodecr_vodafone(str)
external_to_unicodecr_softbank(str)
end
Expand Down
126 changes: 120 additions & 6 deletions lib/jpmobile/mail.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# -*- coding: utf-8 -*-
require 'mail'

module Jpmobile
module Mail
module_function
end
end

module Mail
# encoding patch
if self.const_defined?(:Ruby19)
Expand All @@ -12,18 +18,15 @@ def self.b_value_decode(str)
str = self.decode_base64(match[2])
str.force_encoding(fix_encoding(encoding))
end
str
# if str contains some emoticon, the following line raises Encoding error
str.encode("utf-8", :invalid => :replace, :replace => "") rescue Jpmobile::Util.ascii_8bit(str)
end
end
end

class Message
attr_accessor :mobile

def mobile=(m)
@mobile = m
end

def encoded_with_jpmobile
if @mobile
header['subject'].mobile = @mobile
Expand All @@ -43,8 +46,75 @@ def encoded_with_jpmobile
end
end

def parse_message_with_jpmobile
parse_message_without_jpmobile

if !multipart? and self.header['Content-Type']
self.body.charset = case self.header['Content-Type'].value
when /iso-2022-jp/i
"ISO-2022-JP"
when /shift_jis/i
"Shift_JIS"
else
"UTF-8"
end
end
self.header['subject'].mobile = @mobile if self.header['subject']
end

def init_with_string_with_jpmobile(string)
# Jpmobile::Mobile class from 'From: ' header
s = Jpmobile::Util.ascii_8bit(string)
mobile_class = nil
s.split(/\n|\r/).each do |line|
break if line =~ /^From:/ and mobile_class = Jpmobile::Email.detect(line)
end

@mobile = (mobile_class || Jpmobile::Mobile::AbstractMobile).new(nil, nil)

init_with_string_without_jpmobile(s)

self.body.mobile = @mobile
self.body.set_encoding_jpmobile
end

def process_body_raw_with_jpmobile
process_body_raw_without_jpmobile

self.body.mobile = @mobile
end

alias_method :encoded_without_jpmobile, :encoded
alias_method :encoded, :encoded_with_jpmobile

alias_method :parse_message_without_jpmobile, :parse_message
alias_method :parse_message, :parse_message_with_jpmobile

alias_method :init_with_string_without_jpmobile, :init_with_string
alias_method :init_with_string, :init_with_string_with_jpmobile

alias_method :process_body_raw_without_jpmobile, :process_body_raw
alias_method :process_body_raw, :process_body_raw_with_jpmobile
end

class Part
def parse_message_with_jpmobile
parse_message_without_jpmobile

unless multipart?
self.body.charset = case self.header['Content-Type'].value
when /iso-2022-jp/i
"ISO-2022-JP"
when /shift_jis/i
"Shift_JIS"
else
"UTF-8"
end
end
end

alias_method :parse_message_without_jpmobile, :parse_message
alias_method :parse_message, :parse_message_with_jpmobile
end

class Body
Expand All @@ -58,18 +128,55 @@ def encoded_with_jpmobile(transfer_encoding = '8bit')
encoded_without_jpmobile(transfer_encoding)
end
end
def decoded_with_jpmobile
if @mobile and !multipart?
@raw_source = @mobile.to_mail_internal(@raw_source, nil) unless @jpmobile_decoded
@jpmobile_decoded = true
end

if @charset
@raw_source = Jpmobile::Util.force_encode(@raw_source, @charset, Jpmobile::Util::UTF8)
end

decoded_without_jpmobile
end

# fix charset
def set_charset_with_jpmobile
@charset ||= only_us_ascii? ? 'US-ASCII' : nil
end

# set encoding to @raw_source in init
def set_encoding_jpmobile
@raw_source = Jpmobile::Util.set_encoding(@raw_source, @charset)
end

alias_method :encoded_without_jpmobile, :encoded
alias_method :encoded, :encoded_with_jpmobile

alias_method :decoded_without_jpmobile, :decoded
alias_method :decoded, :decoded_with_jpmobile

alias_method :set_charset_without_jpmobile, :set_charset
alias_method :set_charset, :set_charset_with_jpmobile
end

class UnstructuredField
attr_accessor :mobile

def do_decode
result = value.blank? ? nil : Encodings.decode_encode(value, :decode)

result = @mobile.to_mail_internal(result, value) if @mobile

result.encode!(value.encoding || "UTF-8") if RUBY_VERSION >= '1.9' && !result.blank?
result
end
end

# for subject
class SubjectField < UnstructuredField
# not folding subject
# FIXME: not folding subject -> folding
def encoded_with_jpmobile
if @mobile
# convert encoding
Expand All @@ -79,7 +186,14 @@ def encoded_with_jpmobile
end
end

def decoded_with_jpmobile
decoded_without_jpmobile
end

alias_method :encoded_without_jpmobile, :encoded
alias_method :encoded, :encoded_with_jpmobile

alias_method :decoded_without_jpmobile, :decoded
alias_method :decoded, :decoded_with_jpmobile
end
end
3 changes: 3 additions & 0 deletions lib/jpmobile/mobile/abstract_mobile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ def utf8_to_mail_encode(str)
str
end
end
def to_mail_internal(str, val)
str
end

# リクエストがこのクラスに属するか調べる
# メソッド名に関して非常に不安
Expand Down
9 changes: 9 additions & 0 deletions lib/jpmobile/mobile/au.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ def mail_charset
"ISO-2022-JP"
end

def to_mail_internal(str, val)
if Jpmobile::Util.jis?(str) or Jpmobile::Util.ascii_8bit?(str)
# 絵文字を数値参照に変換
str = Jpmobile::Emoticon.external_to_unicodecr_au_mail(Jpmobile::Util.jis(str))
str = Jpmobile::Util.jis_to_utf8(Jpmobile::Util.jis(str))
end
str
end

private
def to_mail_encoding(str)
str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
Expand Down
8 changes: 8 additions & 0 deletions lib/jpmobile/mobile/docomo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ def to_mail_body(str)
def mail_charset
"Shift_JIS"
end
def to_mail_internal(str, val)
if Jpmobile::Util.shift_jis?(str) or Jpmobile::Util.ascii_8bit?(str)
# 絵文字を数値参照に変換
str = Jpmobile::Emoticon.external_to_unicodecr_docomo(Jpmobile::Util.sjis(str))
end

str
end

# i-mode ブラウザのバージョンを返す。
# http://labs.unoh.net/2009/07/i_20.html
Expand Down
8 changes: 8 additions & 0 deletions lib/jpmobile/mobile/softbank.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ def to_mail_body(str)
def mail_charset
"Shift_JIS"
end
def to_mail_internal(str, val)
if Jpmobile::Util.shift_jis?(str) or Jpmobile::Util.ascii_8bit?(str)
# 絵文字を数値参照に変換
str = Jpmobile::Emoticon.external_to_unicodecr_softbank_sjis(Jpmobile::Util.sjis(str))
end

str
end

private
def to_mail_encoding(str)
Expand Down
101 changes: 101 additions & 0 deletions lib/jpmobile/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,5 +181,106 @@ def wavedash_to_fullwidth_tilde(utf8_str)
def fullwidth_tilde_to_wavedash(utf8_str)
utf8_str.gsub(FULLWIDTH_TILDE, WAVE_DASH)
end

def force_encode(str, from, to)
s = str.dup

if Object.const_defined?(:Encoding)
to = SJIS if to =~ /shift_jis/i

to_enc = ::Encoding.find(to)
return str if s.encoding == to_enc

from_enc = ::Encoding.find(from)

s.force_encoding(from) unless s.encoding == from_enc

s.encode(to)
else
opt = case from
when /iso-2022-jp/i
"-Jx"
when /shift_jis/i
"-Sx"
when /utf-8/i
"-Wx"
else
""
end
opt += case to
when /iso-2022-jp/i
"-j"
when /shift_jis/i
"-s"
when /utf-8/i
"-w"
else
""
end
NKF.nkf(opt, str)
end
end

def set_encoding(str, encoding)
if encoding and Object.const_defined?(:Encoding)
str.force_encoding(encoding)
end

str
end

def extract_charset(str)
case str
when /iso-2022-jp/i
"ISO-2022-JP"
when /shift_jis/i
"Shift_JIS"
when /utf-8/i
"UTF-8"
else
""
end
end

def detect_encoding(str)
if Object.const_defined?(:Encoding)
case str.encoding
when ::Encoding::ISO2022_JP
JIS
when ::Encoding::Shift_JIS, ::Encoding::Windows_31J, ::Encoding::CP932
SJIS
when ::Encoding::UTF_8
UTF8
when ::Encoding::ASCII_8BIT
BINARY
else
BINARY
end
else
case NKF.guess(str)
when NKF::SJIS
SJIS
when NKF::JIS
JIS
when NKF::UTF8
UTF8
else
BINARY
end
end
end

def ascii_8bit?(str)
detect_encoding(str) == BINARY
end
def utf8?(str)
detect_encoding(str) == UTF8
end
def shift_jis?(str)
detect_encoding(str) == SJIS
end
def jis?(str)
detect_encoding(str) == JIS
end
end
end
Loading

0 comments on commit 355ad8a

Please sign in to comment.