class Mail::Body

the boundary, followed by a closing boundary string and then the epilogue.
On encoding, the body will return the preamble, then each part joined by
overwrite this if it needs to be changed.
object for use on encoding itself back out to a string. You can
The boundary that is used to split up the Body is also stored in the Body
each part gets initialized into a Mail::Part object.
anything that appears after the closing boundary to the epilogue, then
assigning anything that appears before the first part to the preamble, and
Once split is called, Mail::Body will slice itself up on this boundary,
boundaries in a body in the case of a nested MIME text).
of knowing what the correct boundary is for itself (there could be many
#split with the correct boundary. This is because the body object has no way
A body has to be told to split itself up into a multipart message by calling
block of text, or (if it is a multipart message) as an array of blocks of text.
used in the MIME standard, it just looks at its content as either a single
as a single object. The body itself has no information about boundaries
The body is where the text of the email is stored. Mail treats the body
= Body

def <<( val )

def <<( val )
  if @parts
    @parts << val
  else
    @parts = Mail::PartsList.new[val]
  end
end

def ==(other)

body == "The body" #=> true
body.encoding = 'base64'
body = Mail::Body.new("VGhlIGJvZHk=\n")

body == 'The body' #=> true
body = Mail::Body.new('The body')

body == body #=> true
body = Mail::Body.new('The body')

Examples:

body with a string.
Matches this body with another body. Also matches the decoded value of this
def ==(other)
  if other.class == String
    self.decoded == other
  else
    super
  end
end

def =~(regexp)

body =~ /The/ #=> 0
body.encoding = 'base64'
body = Mail::Body.new("VGhlIGJvZHk=\n")

body =~ /The/ #=> 0
body = Mail::Body.new('The body')

Examples:

Accepts a string and performs a regular expression against the decoded text
def =~(regexp)
  self.decoded =~ regexp
end

def ascii_only?

def ascii_only?
  unless defined? @ascii_only
    @ascii_only = raw_source.ascii_only?
  end
  @ascii_only
end

def crlf_boundary

def crlf_boundary
  "\r\n--#{boundary}\r\n"
end

def decoded

def decoded
  if !Encodings.defined?(encoding)
    raise UnknownEncodingType, "Don't know how to decode #{encoding}, please call #encoded and decode it yourself."
  else
    Encodings.get_encoding(encoding).decode(raw_source)
  end
end

def default_encoding

def default_encoding
  ascii_only? ? '7bit' : '8bit'
end

def empty?

def empty?
  !!raw_source.to_s.empty?
end

def encoded(transfer_encoding = nil)

TODO: Validate that preamble and epilogue are valid for requested encoding
Calling this directly is not a good idea, but supported for compatibility
identiy encoding (i.e. no encoding).
Returns a body encoded using transfer_encoding. Multipart always uses an
def encoded(transfer_encoding = nil)
  if multipart?
    self.sort_parts!
    encoded_parts = parts.map { |p| p.encoded }
    ([preamble] + encoded_parts).join(crlf_boundary) + end_boundary + epilogue.to_s
  else
    dec = Mail::Encodings.get_encoding(encoding)
    enc =
      if Utilities.blank?(transfer_encoding)
        dec
      else
        negotiate_best_encoding(transfer_encoding)
      end
    if dec.nil?
      # Cannot decode, so skip normalization
      raw_source
    else
      # Decode then encode to normalize and allow transforming 
      # from base64 to Q-P and vice versa
      decoded = dec.decode(raw_source)
      if defined?(Encoding) && charset && charset != "US-ASCII"
        decoded = decoded.encode(charset)
        decoded.force_encoding('BINARY') unless Encoding.find(charset).ascii_compatible?
      end
      enc.encode(decoded)
    end
  end
end

def encoding(val = nil)

def encoding(val = nil)
  if val
    self.encoding = val
  else
    @encoding
  end
end

def encoding=( val )

def encoding=( val )
  @encoding =
    if val == "text" || Utilities.blank?(val)
      default_encoding
    else
      val
    end
end

def end_boundary

def end_boundary
  "\r\n--#{boundary}--\r\n"
end

def extract_parts

split parts by boundary, ignore first part if empty, append final part when closing boundary was missing
def extract_parts
  parts_regex = /
    (?:                    # non-capturing group
      \A                |  # start of string OR
      \r\n                 # line break
     )
    (
      --#{Regexp.escape(boundary || "")}  # boundary delimiter
      (?:--)?                             # with non-capturing optional closing
    )
    (?=\s*$)                              # lookahead matching zero or more spaces followed by line-ending
  /x
  parts = raw_source.split(parts_regex).each_slice(2).to_a
  parts.each_with_index { |(part, _), index| parts.delete_at(index) if index > 0 && Utilities.blank?(part) }
  if parts.size > 1
    final_separator = parts[-2][1]
    parts << [""] if final_separator != "--#{boundary}--"
  end
  parts.map(&:first)
end

def include?(other)

body.include?('The') #=> true
body.encoding = 'base64'
body = Mail::Body.new("VGhlIGJvZHk=\n")

body.include?('The') #=> true
body = Mail::Body.new('The body')

Examples:

Accepts anything that responds to #to_s and checks if it's a substring of the decoded text
def include?(other)
  self.decoded.include?(other.to_s)
end

def init_with(coder)

def init_with(coder)
  coder.map.each { |k, v| instance_variable_set(:"@#{k}", v) }
  @parts = Mail::PartsList.new(coder['parts'])
end

def initialize(string = '')

def initialize(string = '')
  @boundary = nil
  @preamble = nil
  @epilogue = nil
  @charset  = nil
  @part_sort_order = [ "text/plain", "text/enriched", "text/html", "multipart/alternative" ]
  @parts = Mail::PartsList.new
  if Utilities.blank?(string)
    @raw_source = ''
  else
    # Do join first incase we have been given an Array in Ruby 1.9
    if string.respond_to?(:join)
      @raw_source = ::Mail::Utilities.to_crlf(string.join(''))
    elsif string.respond_to?(:to_s)
      @raw_source = ::Mail::Utilities.to_crlf(string.to_s)
    else
      raise "You can only assign a string or an object that responds_to? :join or :to_s to a body."
    end
  end
  @encoding = default_encoding
  set_charset
end

def match(regexp)

body.match(/The/) #=> #
body.encoding = 'base64'
body = Mail::Body.new("VGhlIGJvZHk=\n")

body.match(/The/) #=> #
body = Mail::Body.new('The body')

Examples:

Accepts a string and performs a regular expression against the decoded text
def match(regexp)
  self.decoded.match(regexp)
end

def multipart?

Returns true if there are parts defined in the body
def multipart?
  true unless parts.empty?
end

def negotiate_best_encoding(message_encoding, allowed_encodings = nil)

def negotiate_best_encoding(message_encoding, allowed_encodings = nil)
  Mail::Encodings::TransferEncoding.negotiate(message_encoding, encoding, raw_source, allowed_encodings)
end

def set_charset

def set_charset
  @charset = ascii_only? ? 'US-ASCII' : nil
end

def set_sort_order(order)

with any other content type coming after.
Defaults to 'text/plain', then 'text/enriched', then 'text/html', then 'multipart/alternative'
Allows you to set the sort order of the parts, overriding the default sort order.
def set_sort_order(order)
  @part_sort_order = order
end

def sort_parts!

sort_parts! is also called from :encode, so there is no need for you to call this explicitly

set with :set_sort_order.
Allows you to sort the parts according to the default sort order, or the sort order you
def sort_parts!
  @parts.each do |p|
    p.body.set_sort_order(@part_sort_order)
    p.body.sort_parts!
  end
  @parts.sort!(@part_sort_order)
end

def split!(boundary)

def split!(boundary)
  self.boundary = boundary
  parts = extract_parts
  # Make the preamble equal to the preamble (if any)
  self.preamble = parts[0].to_s.strip
  # Make the epilogue equal to the epilogue (if any)
  self.epilogue = parts[-1].to_s.strip
  parts[1...-1].to_a.each { |part| @parts << Mail::Part.new(part) }
  self
end

def to_s

def to_s
  decoded
end