class MailParser::Message
Mail message @example
require 'mailparser' f = File.open('hoge.eml') m = MailParser::Message.new(f, :output_charset=>'utf-8') m.subject #=> String m.body #=> String m.part #=> Array of Mailparser::Message
Attributes
Public Class Methods
@param [String, File, MmapScanner, read] src source object @param [Hash] opt options @option opt [Boolean] :decode_mime_header (false) decode MIME header @option opt [Boolean] :decode_mime_filename (false) decode MIME encoded filename @option opt [Boolean] :output_charset (nil) output encoding @option opt [Boolean] :strict (false) raise ParseError
exception when message is invalid @option opt [Proc, Method, call] :charset_converter (nil) charset converter. default is MailParser::ConvCharset.conv_charset
# File lib/mailparser.rb, line 188 def initialize(src, opt={}) if src.is_a? String @src = MmapScanner.new src elsif src.is_a? File and src.stat.ftype == 'file' @src = MmapScanner.new src elsif src.is_a? StringIO @src = MmapScanner.new src.string elsif src.is_a? MmapScanner @src = src else tmpf = Tempfile.new 'mailparser' buf = '' while src.read(4096, buf) tmpf.write buf end tmpf.close @src = File.open(tmpf.path){|f| MmapScanner.new f} File.unlink tmpf.path end @opt = opt @from = @to = @cc = @subject = nil @type = @subtype = @charset = @content_transfer_encoding = @filename = nil @rawheader = nil @rawbody = nil @part = [] opt[:charset_converter] ||= ConvCharset.method(:conv_charset) read_header read_part end
Public Instance Methods
@return [String] message body decoded and converted charset
# File lib/mailparser.rb, line 227 def body body = body_preconv if type == 'text' and charset and @opt[:output_charset] begin body = @opt[:charset_converter].call(charset, @opt[:output_charset], body) rescue # ignore end end body end
@return [String] message body decoded and not converted charset
# File lib/mailparser.rb, line 240 def body_preconv body = @rawbody.to_s ret = case content_transfer_encoding when "quoted-printable" then RFC2045.qp_decode(body) when "base64" then RFC2045.b64_decode(body) when "uuencode", "x-uuencode", "x-uue" then decode_uuencode(body) else body end if type == 'text' and charset ret.force_encoding(charset) rescue nil end ret end
@return [Array<MailParser::RFC2822::Mailbox>] Cc field @return [nil] when Cc field don't exist
# File lib/mailparser.rb, line 291 def cc() return @cc if @cc if @header.key? "cc" then @cc = @header["cc"].flatten else @cc = [] end return @cc end
@return [String] Content-Type charset attribute as lower-case @return [nil] when charset attribute don't exist
# File lib/mailparser.rb, line 336 def charset() return @charset if @charset if @header.key? "content-type" then c = @header["content-type"][0].params["charset"] @charset = c && c.downcase else @charset = nil end return @charset end
@return [String] Content-Transfer-Encoding mechanism. default is “7bit”
# File lib/mailparser.rb, line 353 def content_transfer_encoding() return @content_transfer_encoding if @content_transfer_encoding if @header.key? "content-transfer-encoding" then @content_transfer_encoding = @header["content-transfer-encoding"][0].mechanism else @content_transfer_encoding = "7bit" end return @content_transfer_encoding end
@return [String] Content-Disposition filename attribute or Content-Type name attribute @return [nil] when filename attribute don't exist
# File lib/mailparser.rb, line 365 def filename() return @filename if @filename if @header.key? "content-disposition" and @header["content-disposition"][0].params.key? "filename" then @filename = @header["content-disposition"][0].params["filename"] elsif @header.key? "content-type" and @header["content-type"][0].params.key? "name" then @filename = @header["content-type"][0].params["name"] end @filename = RFC2047.decode(@filename, @opt) if @opt[:decode_mime_filename] and @filename return @filename end
@return [MailParser::RFC2822::Mailbox] From field @return [nil] when From field don't exist
# File lib/mailparser.rb, line 267 def from() return @from if @from if @header.key? "from" then @from = @header["from"][0][0] else @from = nil end return @from end
@return [MailParser::Message] body type is message/* @return [nil] when type is not message/*
# File lib/mailparser.rb, line 256 def message return nil unless type == "message" if ['7bit', '8bit'].include? content_transfer_encoding @rawbody.pos = 0 return Message.new(@rawbody, @opt) end return Message.new(body_preconv, @opt) end
@return [Boolean] true if multipart type
# File lib/mailparser.rb, line 348 def multipart?() return type == "multipart" end
@return [String] raw message
# File lib/mailparser.rb, line 377 def raw return @src.to_s end
@return [String] raw body
# File lib/mailparser.rb, line 387 def rawbody @rawbody.to_s end
@return [String] raw header
# File lib/mailparser.rb, line 382 def rawheader @rawheader.to_s end
@return [String] Subject field
# File lib/mailparser.rb, line 302 def subject() return @subject if @subject if @header.key? "subject" then @subject = @header["subject"].join(" ") else @subject = "" end return @subject end
@return [String] Content-Type sub type as lower-case
# File lib/mailparser.rb, line 324 def subtype() return @subtype if @subtype if @header.key? "content-type" then @subtype = @header["content-type"][0].subtype else @subtype = "plain" end return @subtype end
@return [Array<MailParser::RFC2822::Mailbox>] To field @return [nil] when To field don't exist
# File lib/mailparser.rb, line 279 def to() return @to if @to if @header.key? "to" then @to = @header["to"].flatten else @to = [] end return @to end
@return [String] Content-Type main type as lower-case
# File lib/mailparser.rb, line 313 def type() return @type if @type if @header.key? "content-type" then @type = @header["content-type"][0].type else @type = "text" end return @type end
Private Instance Methods
# File lib/mailparser.rb, line 437 def decode_plain(str) str end
# File lib/mailparser.rb, line 425 def decode_uuencode(str) ret = "" str.each_line do |line| line.chomp! next if line =~ /\A\s*\z/ next if line =~ /\Abegin \d\d\d [^ ]/ break if line =~ /\Aend\z/ ret.concat line.unpack("u").first end ret end
# File lib/mailparser.rb, line 393 def read_header() @rawheader = @src.scan_until(/^(?=\r?\n)|\z/) @header = Header.new(@opt) until @rawheader.eos? if @rawheader.skip(/(.*?)[ \t]*:[ \t]*(.*(\r?\n[ \t].*)*(\r?\n)?)/) name = @rawheader.matched(1).to_s body = @rawheader.matched(2).to_s @header.add(name, body) else @rawheader.skip(/.*\n/) or break end end @src.scan(/\r?\n/) # skip delimiter line @rawbody = @src.rest end
# File lib/mailparser.rb, line 409 def read_part() return if type != "multipart" or @src.eos? b = @header["content-type"][0].params["boundary"] return unless b re = /(?:\A|\r?\n)--#{Regexp.escape b}(?:|(--))(?:\r?\n|\z)/ @src.scan_until(re) or return # skip preamble until @src.eos? unless p = @src.scan_until(re) @part.push Message.new(@src.rest, @opt) break end @part.push Message.new(p.peek(p.size-@src.matched.length), @opt) break if @src.matched(1) end end