class QuickML::Mail

Attributes

bare[RW]
body[RW]
charset[R]
content_type[R]
mail_from[RW]
recipients[R]

Public Class Methods

address_of_domain?(address, domain) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 179
def self.address_of_domain? (address, domain)
  re = '[.@]' + Regexp.quote(domain) + '$'
  domainpat = Regexp.new(re, Regexp::IGNORECASE)
  return true if domainpat =~ address
  return false
end
boundary(ct) click to toggle source
class method
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 54
def self.boundary(ct)
 #if /^multipart\/\w+;\s*boundary=("?)(.*)\1/i =~ ct
  if /^multipart\/\w+;/i =~ ct and /[\s;]boundary=("?)(.*)\1/i =~ ct
    return $2 
  end
  return nil
end
clean_subject(s, name) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 166
def self.clean_subject(s, name)
  s = Mail.decode_subject(s)
  s.gsub!(/(?:\[#{Regexp.quote(name)}:\d+\])/, '')
  s.sub!(/(?:Re:\s*)+/i, 'Re: ')
  return s
end
collect_address(field) click to toggle source
Class methods.
# File vendor/qwik/lib/qwik/mail-header.rb, line 102
def self.collect_address (field)
  address_regex =
    /(("?)[-0-9a-zA-Z_.+?\/]+\2@[-0-9a-zA-Z]+\.[-0-9a-zA-Z.]+)/ #/
  addresses = []
  parts = Mail.remove_comment_in_field(field).split(',')
  parts.each {|part|
    if (/<(.*?)>/ =~ part) || (address_regex =~ part)
      addresses.push(MailAddress.normalize($1))
    end
  }
  return addresses.uniq
end
content_type(default_content_type, charset) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 186
def self.content_type(default_content_type, charset)
  return default_content_type + "; charset=#{charset}" if charset
  return default_content_type
end
create() { || ... } click to toggle source

Create a new mail

# File vendor/qwik/lib/qwik/mail-parse.rb, line 45
def self.create
  mail = Mail.new
  mail.read(yield)
  mail.store_addresses
  return mail
end
decode_base64(str) click to toggle source
# File vendor/qwik/lib/qwik/mail-body.rb, line 75
def self.decode_base64(str)
  return Base64.decode64(str)
end
decode_body(enc, body) click to toggle source
# File vendor/qwik/lib/qwik/mail-body.rb, line 68
def self.decode_body(enc, body)
  return Mail.decode_base64(body) if /base64/i =~ enc
  return Mail.decode_uuencode(body) if /x-uuencode/i =~ enc
  return Mail.decode_quoted_printable(body) if /quoted-printable/i =~ enc
  return body
end
decode_quoted_printable(str) click to toggle source
# File vendor/qwik/lib/qwik/mail-body.rb, line 89
def self.decode_quoted_printable(str)
  str = str.gsub(/[ \t]+$/no, '')
  str.gsub!(/=\r?\n/no, '')
  str.gsub!(/=([0-9A-F][0-9A-F])/no) { $1.hex.chr }
  return str
end
decode_subject(s) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 148
def self.decode_subject(s)
  s = join_lines(s) if multiline?(s)
  s = SubjectDecoder.decode(s)
  s.tosjis
end
decode_uuencode(str) click to toggle source
# File vendor/qwik/lib/qwik/mail-body.rb, line 79
def self.decode_uuencode(str)
  uu = ''
  str.each {|line|
    next  if /\Abegin/ =~ line
    break if /\Aend/ =~ line
    uu << line
  }
  return uu.unpack('u').first
end
empty_body?(body) click to toggle source
Class methods.
# File vendor/qwik/lib/qwik/mail-body.rb, line 54
def self.empty_body?(body)
  return false if 100 < body.length
  # Substitute spaces in Shift_JIS to ordinaly spaces.
  body = body.tosjis.gsub("\201@") { ' ' }
  return true if /\A\s*\Z/s =~ body
  return false
end
encode_field(field) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 140
def self.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
generate() { || ... } click to toggle source

Generate a mail for test.

# File vendor/qwik/lib/qwik/mail-parse.rb, line 53
def self.generate
  mail = Mail.new
  mail.read(yield.set_sourcecode_charset.to_mail_charset)
  mail.store_addresses
  return mail
end
get_charset(contenttype) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 130
def self.get_charset(contenttype)
  return $2.downcase if /charset=("?)([-\w]+)\1/ =~ contenttype
  return nil
end
get_content_type(contenttype) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 135
def self.get_content_type(contenttype)
  return $1.downcase if /([-\w]+\/[-\w]+)/ =~ contenttype
  return nil
end
get_filename(disp) click to toggle source
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 70
def self.get_filename(disp)
  return nil if disp.nil?
  type, fdesc = disp.split(';', 2)
  return nil if fdesc.nil?
  fdesc = fdesc.strip
  if /\Afilename=/ =~ fdesc
    fdesc.sub!(/\Afilename=/, '')
    fdesc.sub!(/\A\"/, '')
    fdesc.sub!(/\"\z/, '')

    # FIXME: It is not sure that the filename is encoded in JIS.
    # FIXME: It is using nkf for decode MIME encode.
    str = fdesc.set_mail_charset.to_page_charset
    str = str.to_filename_charset

    return str
  end
  return nil
end
get_unified_subject(s, name) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 115
def self.get_unified_subject(s, name)
  s = Mail.clean_subject(s, name)
  s.sub!(/(?:Re:\s*)+/i, '')
  s.sub!(/\A\s+/, '')
  s.sub!(/\s+\z/, '')
  s.gsub!(/\s+/, ' ')       # Thanks to Mr. Atsushi SHICHI.
  return s
end
join_lines(s) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 158
def self.join_lines(s)
  result = s.dup
  result.gsub!(/\?=\s*\n\s+=\?/, '?==?')
  result.gsub!(/\n\s+/, ' ')
  result.gsub!(/\n/, '')
  return result
end
join_parts(parts, boundary) click to toggle source

group-mail.rb:168: mail.body = Mail.join_parts(parts, mail.boundary) ml-processor.rb:188: body = Mail.join_parts(parts, @mail.boundary)

# File vendor/qwik/lib/qwik/mail-body.rb, line 98
def self.join_parts (parts, boundary)
  body = ''
  body << "--#{boundary}\n"
  body << parts.join("--#{boundary}\n")
  body << "--#{boundary}--\n"
  return body
end
multiline?(s) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 154
def self.multiline?(s)
  /\n/ =~ s
end
new() click to toggle source
# File vendor/qwik/lib/qwik/mail.rb, line 19
def initialize
  @mail_from = nil
  @recipients = []
  @header = []
  @body = ''
  @charset = nil
  @content_type = nil
  @bare = nil
end
plain_text_body?(ct, cte) click to toggle source
# File vendor/qwik/lib/qwik/mail-body.rb, line 62
def self.plain_text_body?(ct, cte)
  return true if (ct.empty? || /\btext\/plain\b/i =~ ct) &&
    (cte.empty? || /^[78]bit$/i =~ cte || /^base64$/i =~ cte || /quoted-printable/i =~ cte)
  return false
end
remove_comment_in_field(field) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 124
def self.remove_comment_in_field (field)
  field = field.tosjis
  true while field.sub!(/\([^()]*?\)/, '')
  return field
end
rewrite_subject(s, name, count) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 173
def self.rewrite_subject (s, name, count)
  s = Mail.clean_subject(s, name)
  s = "[#{name}:#{count}] " + s
  return Mail.encode_field(s)
end
split_body(body, boundary) click to toggle source
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 62
def self.split_body(body, boundary)
  return [body] if boundary.nil? || boundary.empty?
  parts = body.split(/^--#{Regexp.escape(boundary)}-*\n/)
  parts.shift       # Remove the first empty string.
  parts.pop if /\A\s*\z/ =~ parts.last
  return parts
end

Public Instance Methods

[](key) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 38
def [] (key)
  field = @header.find {|field|
    key.downcase == field.first.downcase
  }
  return '' if field.nil?
  return field.last
end
[]=(key, value) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 25
def []=(key, value)
  return nil if ! $test     # Only for test.
  field = @header.find {|field|
    key.downcase == field.first.downcase
  }
  if field
    field[1] = value
  else
    @header << [key, value]
  end
  return nil
end
add_recipient(address) click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 83
def add_recipient (address)
  @recipients.push(MailAddress.normalize(address))
end
boundary() click to toggle source
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 21
def boundary
  return Mail.boundary(self['Content-Type'])
end
clear_recipients() click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 87
def clear_recipients
  @recipients = []
end
collect_cc() click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 96
def collect_cc
  return Mail.collect_address(self['Cc']) if self['Cc']
  return []
end
collect_to() click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 91
def collect_to
  return Mail.collect_address(self['To']) if self['To']
  return []
end
decoded_body() click to toggle source

by eto

# File vendor/qwik/lib/qwik/mail-body.rb, line 49
def decoded_body
  return Mail.decode_body(self['Content-Transfer-Encoding'], @body)
end
each_field() { |first, last| ... } click to toggle source

group.rb:265: mail.each_field {|key, value| mail-body.rb:18: self.each_field {|key, value|

# File vendor/qwik/lib/qwik/mail-header.rb, line 54
def each_field
  @header.each {|field|
    yield(field.first, field.last)
  }
end
each_part() { |self| ... } click to toggle source
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 41
def each_part(&block)
  if multipart?
    self.parts.each {|str|
      submail = Mail.new
      submail.read(str)
      submail.each_part(&block)    # Recursive.
    }
  else
    yield(self)
  end
end
empty_body?() click to toggle source

ml-processor.rb:102: @mail.empty_body? ||

# File vendor/qwik/lib/qwik/mail-body.rb, line 27
def empty_body?
  return Mail.empty_body?(@body)
end
filename() click to toggle source
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 25
def filename
  return Mail.get_filename(self['Content-Disposition'])
end
from() click to toggle source
Address methods.
# File vendor/qwik/lib/qwik/mail-header.rb, line 71
def from
  address = @mail_from
  address = Mail.collect_address(self['From'])[0] if ! self['From'].empty?
  address = 'unknown' if address.nil? || address.empty?
  address = MailAddress.normalize(address)
  return address
end
get_body() click to toggle source
# File vendor/qwik/lib/qwik/mail-body.rb, line 38
def get_body
  body = ''
  self.each_part {|mail|
    if mail.plain_text_body?
      body << mail.body.chomp.chomp+"\n"
    end
  }
  return body
end
get_unified_subject(name) click to toggle source
Get value.
# File vendor/qwik/lib/qwik/mail-header.rb, line 61
def get_unified_subject(name)
  return Mail.get_unified_subject(self['Subject'], name)
end
header() click to toggle source
Basic header methods.
# File vendor/qwik/lib/qwik/mail-header.rb, line 20
def header
  return nil if ! $test     # Only for test.
  return @header
end
looping?() click to toggle source

ml-processor.rb:37: if @mail.looping?

# File vendor/qwik/lib/qwik/mail-header.rb, line 66
def looping?
  return ! self['X-QuickML'].empty?
end
multipart?() click to toggle source
Multipart methods.
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 17
def multipart?
  return !!boundary
end
nuparts() click to toggle source
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 33
def nuparts
  boundary = self.boundary
  return [self.body] if boundary.nil? || boundary.empty?
  parts = @body.split(/^--#{Regexp.escape(boundary)}-*\n/)
  parts.shift       # Remove the first empty string.
  return parts
end
parts() click to toggle source
# File vendor/qwik/lib/qwik/mail-multipart.rb, line 29
def parts
  return Mail.split_body(self.body, self.boundary)
end
plain_text_body?() click to toggle source

group-mail.rb:38: if mail.plain_text_body? group-site.rb:116: if sub_mail.plain_text_body?

# File vendor/qwik/lib/qwik/mail-body.rb, line 33
def plain_text_body?
  Mail.plain_text_body?(self['Content-Type'],
                        self['Content-Transfer-Encoding'])
end
read(string) click to toggle source

Construct a mail from a mail string.

# File vendor/qwik/lib/qwik/mail-parse.rb, line 17
def read (string)
  @bare = string || ''

  header, body = @bare.split(/\n\n/, 2)
  @body = body || ''

  attr = nil
  header.split("\n").each {|line|
    line = line.xchomp
    if /^(\S+):\s*(.*)/ =~ line
      attr = $1
      push_field(attr, $2)
    elsif attr
      concat_field(line)
    end
  }
  @charset = Mail.get_charset(self['Content-Type'])
  @content_type = Mail.get_content_type(self['Content-Type'])
end
store_addresses() click to toggle source
# File vendor/qwik/lib/qwik/mail-parse.rb, line 37
def store_addresses
  @mail_from = self.from
  (self.collect_to + self.collect_cc).each {|addr|
    self.add_recipient(addr)
  }
end
to_s() click to toggle source
# File vendor/qwik/lib/qwik/mail-body.rb, line 16
def to_s
  str = ''
  self.each_field {|key, value|
    str << "#{key}: #{value}\n"
  }
  str << "\n"
  str << @body
  return str
end
unshift_field(key, value) click to toggle source

ml-session.rb:214: mail.unshift_field(‘Received’, received_field)

# File vendor/qwik/lib/qwik/mail-header.rb, line 47
def unshift_field (key, value)
  # Use Array for preserving order of the header
  @header.unshift([key, value])
end
valid?() click to toggle source
# File vendor/qwik/lib/qwik/mail-header.rb, line 79
def valid?
  return (! @recipients.empty?) && !!@mail_from
end

Private Instance Methods

concat_field(value) click to toggle source
# File vendor/qwik/lib/qwik/mail-parse.rb, line 68
def concat_field (value)
  lastfield = @header.last
  @header.pop
  push_field(lastfield.first, lastfield.last + "\n" + value)
end
push_field(key, value) click to toggle source
# File vendor/qwik/lib/qwik/mail-parse.rb, line 62
def push_field (key, value)
  # Use Array for preserving order of the header
  field = [key, value]
  @header.push(field)
end