Class: SMail::MIME

Inherits:
SMail
  • Object
show all
Defined in:
lib/smail/mime/date.rb,
lib/smail/mime/mime.rb,
lib/smail/mime/version.rb,
lib/smail/mime/content_fields.rb

Defined Under Namespace

Modules: VERSION Classes: ContentDisposition, ContentField, ContentType, Date

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text = '') ⇒ MIME

Returns a new instance of MIME.



9
10
11
12
13
# File 'lib/smail/mime/mime.rb', line 9

def initialize(text = '')
  super(text)
  self.content_type = self.header('content-type')
  fill_parts
end

Instance Attribute Details

#boundaryObject (readonly)

Returns the value of attribute boundary.



7
8
9
# File 'lib/smail/mime/mime.rb', line 7

def boundary
  @boundary
end

#content_typeObject

Returns the value of attribute content_type.



7
8
9
# File 'lib/smail/mime/mime.rb', line 7

def content_type
  @content_type
end

#epilogueObject

Returns the value of attribute epilogue.



6
7
8
# File 'lib/smail/mime/mime.rb', line 6

def epilogue
  @epilogue
end

#partsObject

Returns the value of attribute parts.



6
7
8
# File 'lib/smail/mime/mime.rb', line 6

def parts
  @parts
end

#preambleObject

Returns the value of attribute preamble.



6
7
8
# File 'lib/smail/mime/mime.rb', line 6

def preamble
  @preamble
end

Instance Method Details

#bodyObject

Returns the body decoded and converted to UTF-8 if necessary, if this is is a multipart message this is not what you suspect



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/smail/mime/mime.rb', line 79

def body
  if self.multipart? # what if it is message/rfc822 ?
    @preamble 
  else
    # decode
    case self.header('content-transfer-encoding')
      when 'quoted-printable'
        body = @body.decode_quoted_printable
      when 'base64'
        body = @body.decode_base64
      else
        # matches nil when there is no header or an unrecognised encoding
        body = @body
    end
    
    # convert to UTF-8 if text
    if self.content_type.media_type == 'text'
      charset = self.content_type.params['charset'] || 'us-ascii'
      body.iconv!('utf-8', charset)
    end

    body
  end
end

#body_rawObject

Returns the raw body of the email including all parts



75
# File 'lib/smail/mime/mime.rb', line 75

alias body_raw body

#consists_of_mime_types?(*types) ⇒ Boolean

Returns true if the message consists entirely of the given mime types.

For single part messages this is simple: the Content-Type of the message must by one of the supplied types.

For multipart messages it gets a bit more complicated. We try to make sure that the message can be entirely decomposed into just the supplied types.

The rules are as follows:

multipart/alternative

At least one sub-part must consist of the given types.

multipart/mixed

All sub-parts must consist of the given types.

multipart/related

The root part (usually the first part) must consist of the given types.

multipart/signed

The first part must consist of the given types.

multipart/appledouble

The second part must consist of the given types. (See RFC 1740.)

Returns:

  • (Boolean)


183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/smail/mime/mime.rb', line 183

def consists_of_mime_types?(*types)
  types = types.flatten
  type = self.content_type.type

  if self.multipart?
    case type
      when 'multipart/alternative'
        self.parts.any? {|part| part.consists_of_mime_types?(types) }
      when 'multipart/mixed'
        self.parts.all? {|part| part.consists_of_mime_types?(types) }
      when 'multipart/related'
        # FIXME: This should look for a start parameter and try that first.
        self.parts.first.consists_of_mime_types?(types)
      when 'multipart/signed'
        self.parts.first.consists_of_mime_types?(types)
      when 'multipart/appledouble'
        self.parts[1].consists_of_mime_types?(types)
      when 'message/rfc822', 'message/rfc2822'
        self.parts.first.consists_of_mime_types?(types)
      else
        false
    end
  else
    types.any? {|t| t === type }
  end
end

#dateObject

Returns the date from the Date header as a DateTime object.



65
66
67
68
69
70
71
# File 'lib/smail/mime/mime.rb', line 65

def date
  date = self.header('date')
  return nil unless date
  SMail::MIME::Date.parse(date)
  #(year, month, day, hour, minute, second, timezone, weekday) = ParseDate.parsedate(date)
  #Time.gm(second, minute, hour, day, month, year, weekday, nil, nil, timezone)
end

#describe_mime_structure(depth = 0) ⇒ Object

Returns a string description of the MIME structure of this message.

This is useful for debugging and testing. The returned string is formatted as shown in the following example:

multipart/mixed
  multipart/alternative
    text/plain
    multipart/related
      text/html
      image/gif
  application/octet-stream


115
116
117
118
119
120
121
122
123
124
# File 'lib/smail/mime/mime.rb', line 115

def describe_mime_structure(depth = 0)
  result = ('  '*depth) + self.content_type.type + "\n"
  if self.multipart?
    self.parts.each do |part|
      result << part.describe_mime_structure(depth+1)
    end
  end
  result.chomp! if depth == 0
  result
end

#flatten_body(*types) ⇒ Object

Pulls out any body parts matching the given MIME types and puts them into an array.

This is useful for pulling out parts in the appropriate order for rendering. For example calling:

message.flatten_body('text/plain', /^application\/.*$)

should return all the text parts and attached files in the order in which they appear in the original message.

The various multipart subtypes are handled sensibly. For example, for multipart/alternative messages, the best matching part (i.e. the last part consisting entirely of the given types) is used.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/smail/mime/mime.rb', line 138

def flatten_body(*types)
  types = types.flatten
  if self.multipart?
    case self.content_type.type
      when 'multipart/alternative'
        part = self.parts.reverse.find {|part| part.consists_of_mime_types?(types) }
        part ? part.flatten_body(types) : []
      when 'multipart/mixed', 'multipart/related'
        # FIXME: For multipart/related, this should look for a start parameter and try that first.    
        parts = self.parts.collect {|part| part.flatten_body(types) }
        parts.flatten
      when 'multipart/signed'
        self.parts.first.flatten_body(types)
      when 'multipart/appledouble'
        self.parts[1].flatten_body(types)
      else
        # FIXME: should we also have an entry for message/rfc822 etc.
        []
    end
  else
    self.consists_of_mime_types?(types) ? [self] : []
  end
end

#multipart?Boolean

Is this a multipart message

Returns:

  • (Boolean)


35
36
37
# File 'lib/smail/mime/mime.rb', line 35

def multipart?
  @content_type.composite?
end

#sizeObject

Returns the size of the message in bytes.



16
17
18
# File 'lib/smail/mime/mime.rb', line 16

def size
  self.to_s.length
end

#subjectObject

Returns the subject in UTF-8



45
46
47
# File 'lib/smail/mime/mime.rb', line 45

def subject
  SMail::MIME.decode_field(subject_raw)
end

#subject=(text) ⇒ Object

Sets the subject, performs any necessary encoding



50
51
52
# File 'lib/smail/mime/mime.rb', line 50

def subject=(text)
  self.subject_raw = SMail::MIME.encode_field(text)
end

#subject_rawObject

Returns the raw potentially MIME encoded subject



55
56
57
# File 'lib/smail/mime/mime.rb', line 55

def subject_raw
  self.header('subject')
end

#subject_raw=(text) ⇒ Object

Set the subject directly, any necessary MIME encoding is up to the caller



60
61
62
# File 'lib/smail/mime/mime.rb', line 60

def subject_raw=(text)
  self.header_set('subject', text)
end

#versionObject

Returns the MIME-Version as a string (unlikely to be anything but ‘1.0’)



40
41
42
# File 'lib/smail/mime/mime.rb', line 40

def version
  self.header('mime-version') || '1.0'
end