Class: MailParser::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/mailparser.rb

Overview

Mail message

Examples:

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(src, opt = {}) ⇒ Message

Returns a new instance of Message.

Parameters:

  • src (String, File, MmapScanner, #read)

    source object

  • opt (Hash) (defaults to: {})

    options

Options Hash (opt):

  • :decode_mime_header (Boolean) — default: false

    decode MIME header

  • :decode_mime_filename (Boolean) — default: false

    decode MIME encoded filename

  • :output_charset (Boolean) — default: nil

    output encoding

  • :strict (Boolean) — default: false

    raise ParseError exception when message is invalid

  • :charset_converter (Proc, Method, #call) — default: nil

    charset converter. default is MailParser::ConvCharset.conv_charset



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# 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

Instance Attribute Details

#headerMailParser::Header (readonly)

Returns:



221
222
223
# File 'lib/mailparser.rb', line 221

def header
  @header
end

#partArray<MailParser::Message> (readonly)

Returns:



221
222
223
# File 'lib/mailparser.rb', line 221

def part
  @part
end

Instance Method Details

#bodyString

Returns message body decoded and converted charset.

Returns:

  • (String)

    message body decoded and converted charset



227
228
229
230
231
232
233
234
235
236
237
# 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

#body_preconvString

Returns message body decoded and not converted charset.

Returns:

  • (String)

    message body decoded and not converted charset



240
241
242
243
244
245
246
247
248
249
250
251
252
# 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

#ccArray<MailParser::RFC2822::Mailbox>?

Returns:



291
292
293
294
295
296
297
298
299
# 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

#charsetString?

Returns:

  • (String)

    Content-Type charset attribute as lower-case

  • (nil)

    when charset attribute don't exist



336
337
338
339
340
341
342
343
344
345
# 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

#content_transfer_encodingString

Returns Content-Transfer-Encoding mechanism. default is “7bit”.

Returns:

  • (String)

    Content-Transfer-Encoding mechanism. default is "7bit"



353
354
355
356
357
358
359
360
361
# 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

#filenameString?

Returns:

  • (String)

    Content-Disposition filename attribute or Content-Type name attribute

  • (nil)

    when filename attribute don't exist



365
366
367
368
369
370
371
372
373
374
# 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

#fromMailParser::RFC2822::Mailbox?

Returns:



267
268
269
270
271
272
273
274
275
# 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

#messageMailParser::Message?

Returns:



256
257
258
259
260
261
262
263
# 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

#multipart?Boolean

Returns true if multipart type.

Returns:

  • (Boolean)

    true if multipart type



348
349
350
# File 'lib/mailparser.rb', line 348

def multipart?()
  return type == "multipart"
end

#rawString

Returns raw message.

Returns:

  • (String)

    raw message



377
378
379
# File 'lib/mailparser.rb', line 377

def raw
  return @src.to_s
end

#rawbodyString

Returns raw body.

Returns:

  • (String)

    raw body



387
388
389
# File 'lib/mailparser.rb', line 387

def rawbody
  @rawbody.to_s
end

#rawheaderString

Returns raw header.

Returns:

  • (String)

    raw header



382
383
384
# File 'lib/mailparser.rb', line 382

def rawheader
  @rawheader.to_s
end

#subjectString

Returns Subject field.

Returns:

  • (String)

    Subject field



302
303
304
305
306
307
308
309
310
# 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

#subtypeString

Returns Content-Type sub type as lower-case.

Returns:

  • (String)

    Content-Type sub type as lower-case



324
325
326
327
328
329
330
331
332
# 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

#toArray<MailParser::RFC2822::Mailbox>?

Returns:



279
280
281
282
283
284
285
286
287
# 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

#typeString

Returns Content-Type main type as lower-case.

Returns:

  • (String)

    Content-Type main type as lower-case



313
314
315
316
317
318
319
320
321
# 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