net-imap 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Net
4
+ class IMAP < Protocol
5
+
6
+ # Decode a string from modified UTF-7 format to UTF-8.
7
+ #
8
+ # UTF-7 is a 7-bit encoding of Unicode [UTF7]. IMAP uses a
9
+ # slightly modified version of this to encode mailbox names
10
+ # containing non-ASCII characters; see [IMAP] section 5.1.3.
11
+ #
12
+ # Net::IMAP does _not_ automatically encode and decode
13
+ # mailbox names to and from UTF-7.
14
+ def self.decode_utf7(s)
15
+ return s.gsub(/&([^-]+)?-/n) {
16
+ if $1
17
+ ($1.tr(",", "/") + "===").unpack1("m").encode(Encoding::UTF_8, Encoding::UTF_16BE)
18
+ else
19
+ "&"
20
+ end
21
+ }
22
+ end
23
+
24
+ # Encode a string from UTF-8 format to modified UTF-7.
25
+ def self.encode_utf7(s)
26
+ return s.gsub(/(&)|[^\x20-\x7e]+/) {
27
+ if $1
28
+ "&-"
29
+ else
30
+ base64 = [$&.encode(Encoding::UTF_16BE)].pack("m0")
31
+ "&" + base64.delete("=").tr("/", ",") + "-"
32
+ end
33
+ }.force_encoding("ASCII-8BIT")
34
+ end
35
+
36
+ # Formats +time+ as an IMAP-style date.
37
+ def self.format_date(time)
38
+ return time.strftime('%d-%b-%Y')
39
+ end
40
+
41
+ # Formats +time+ as an IMAP-style date-time.
42
+ def self.format_datetime(time)
43
+ return time.strftime('%d-%b-%Y %H:%M %z')
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Net
4
+ class IMAP < Protocol
5
+
6
+ # :category: Message Flags
7
+ #
8
+ # Flag indicating a message has been seen.
9
+ SEEN = :Seen
10
+
11
+ # :category: Message Flags
12
+ #
13
+ # Flag indicating a message has been answered.
14
+ ANSWERED = :Answered
15
+
16
+ # :category: Message Flags
17
+ #
18
+ # Flag indicating a message has been flagged for special or urgent
19
+ # attention.
20
+ FLAGGED = :Flagged
21
+
22
+ # :category: Message Flags
23
+ #
24
+ # Flag indicating a message has been marked for deletion. This
25
+ # will occur when the mailbox is closed or expunged.
26
+ DELETED = :Deleted
27
+
28
+ # :category: Message Flags
29
+ #
30
+ # Flag indicating a message is only a draft or work-in-progress version.
31
+ DRAFT = :Draft
32
+
33
+ # :category: Message Flags
34
+ #
35
+ # Flag indicating that the message is "recent," meaning that this
36
+ # session is the first session in which the client has been notified
37
+ # of this message.
38
+ RECENT = :Recent
39
+
40
+ # :category: Mailbox Flags
41
+ #
42
+ # Flag indicating that a mailbox context name cannot contain
43
+ # children.
44
+ NOINFERIORS = :Noinferiors
45
+
46
+ # :category: Mailbox Flags
47
+ #
48
+ # Flag indicating that a mailbox is not selected.
49
+ NOSELECT = :Noselect
50
+
51
+ # :category: Mailbox Flags
52
+ #
53
+ # Flag indicating that a mailbox has been marked "interesting" by
54
+ # the server; this commonly indicates that the mailbox contains
55
+ # new messages.
56
+ MARKED = :Marked
57
+
58
+ # :category: Mailbox Flags
59
+ #
60
+ # Flag indicating that the mailbox does not contains new messages.
61
+ UNMARKED = :Unmarked
62
+
63
+ @@max_flag_count = 10000
64
+
65
+ # Returns the max number of flags interned to symbols.
66
+ def self.max_flag_count
67
+ return @@max_flag_count
68
+ end
69
+
70
+ # Sets the max number of flags interned to symbols.
71
+ def self.max_flag_count=(count)
72
+ @@max_flag_count = count
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,527 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Net
4
+ class IMAP < Protocol
5
+
6
+ # Net::IMAP::ContinuationRequest represents command continuation requests.
7
+ #
8
+ # The command continuation request response is indicated by a "+" token
9
+ # instead of a tag. This form of response indicates that the server is
10
+ # ready to accept the continuation of a command from the client. The
11
+ # remainder of this response is a line of text.
12
+ #
13
+ # continue_req ::= "+" SPACE (resp_text / base64)
14
+ #
15
+ # ==== Fields:
16
+ #
17
+ # data:: Returns the data (Net::IMAP::ResponseText).
18
+ #
19
+ # raw_data:: Returns the raw data string.
20
+ class ContinuationRequest < Struct.new(:data, :raw_data)
21
+ end
22
+
23
+ # Net::IMAP::UntaggedResponse represents untagged responses.
24
+ #
25
+ # Data transmitted by the server to the client and status responses
26
+ # that do not indicate command completion are prefixed with the token
27
+ # "*", and are called untagged responses.
28
+ #
29
+ # response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye /
30
+ # mailbox_data / message_data / capability_data)
31
+ #
32
+ # ==== Fields:
33
+ #
34
+ # name:: Returns the name, such as "FLAGS", "LIST", or "FETCH".
35
+ #
36
+ # data:: Returns the data such as an array of flag symbols,
37
+ # a ((<Net::IMAP::MailboxList>)) object.
38
+ #
39
+ # raw_data:: Returns the raw data string.
40
+ class UntaggedResponse < Struct.new(:name, :data, :raw_data)
41
+ end
42
+
43
+ # Net::IMAP::IgnoredResponse represents intentionally ignored responses.
44
+ #
45
+ # This includes untagged response "NOOP" sent by eg. Zimbra to avoid some
46
+ # clients to close the connection.
47
+ #
48
+ # It matches no IMAP standard.
49
+ #
50
+ # ==== Fields:
51
+ #
52
+ # raw_data:: Returns the raw data string.
53
+ class IgnoredResponse < Struct.new(:raw_data)
54
+ end
55
+
56
+ # Net::IMAP::TaggedResponse represents tagged responses.
57
+ #
58
+ # The server completion result response indicates the success or
59
+ # failure of the operation. It is tagged with the same tag as the
60
+ # client command which began the operation.
61
+ #
62
+ # response_tagged ::= tag SPACE resp_cond_state CRLF
63
+ #
64
+ # tag ::= 1*<any ATOM_CHAR except "+">
65
+ #
66
+ # resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
67
+ #
68
+ # ==== Fields:
69
+ #
70
+ # tag:: Returns the tag.
71
+ #
72
+ # name:: Returns the name, one of "OK", "NO", or "BAD".
73
+ #
74
+ # data:: Returns the data. See ((<Net::IMAP::ResponseText>)).
75
+ #
76
+ # raw_data:: Returns the raw data string.
77
+ #
78
+ class TaggedResponse < Struct.new(:tag, :name, :data, :raw_data)
79
+ end
80
+
81
+ # Net::IMAP::ResponseText represents texts of responses.
82
+ # The text may be prefixed by the response code.
83
+ #
84
+ # resp_text ::= ["[" resp-text-code "]" SP] text
85
+ #
86
+ # ==== Fields:
87
+ #
88
+ # code:: Returns the response code. See ((<Net::IMAP::ResponseCode>)).
89
+ #
90
+ # text:: Returns the text.
91
+ #
92
+ class ResponseText < Struct.new(:code, :text)
93
+ end
94
+
95
+ # Net::IMAP::ResponseCode represents response codes.
96
+ #
97
+ # resp_text_code ::= "ALERT" /
98
+ # "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
99
+ # capability_data / "PARSE" /
100
+ # "PERMANENTFLAGS" SP "("
101
+ # [flag_perm *(SP flag_perm)] ")" /
102
+ # "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
103
+ # "UIDNEXT" SP nz_number / "UIDVALIDITY" SP nz_number /
104
+ # "UNSEEN" SP nz_number /
105
+ # atom [SP 1*<any TEXT-CHAR except "]">]
106
+ #
107
+ # ==== Fields:
108
+ #
109
+ # name:: Returns the name, such as "ALERT", "PERMANENTFLAGS", or "UIDVALIDITY".
110
+ #
111
+ # data:: Returns the data, if it exists.
112
+ #
113
+ class ResponseCode < Struct.new(:name, :data)
114
+ end
115
+
116
+ # Net::IMAP::MailboxList represents contents of the LIST response.
117
+ #
118
+ # mailbox_list ::= "(" #("\Marked" / "\Noinferiors" /
119
+ # "\Noselect" / "\Unmarked" / flag_extension) ")"
120
+ # SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox
121
+ #
122
+ # ==== Fields:
123
+ #
124
+ # attr:: Returns the name attributes. Each name attribute is a symbol
125
+ # capitalized by String#capitalize, such as :Noselect (not :NoSelect).
126
+ #
127
+ # delim:: Returns the hierarchy delimiter.
128
+ #
129
+ # name:: Returns the mailbox name.
130
+ #
131
+ class MailboxList < Struct.new(:attr, :delim, :name)
132
+ end
133
+
134
+ # Net::IMAP::MailboxQuota represents contents of GETQUOTA response.
135
+ # This object can also be a response to GETQUOTAROOT. In the syntax
136
+ # specification below, the delimiter used with the "#" construct is a
137
+ # single space (SPACE).
138
+ #
139
+ # quota_list ::= "(" #quota_resource ")"
140
+ #
141
+ # quota_resource ::= atom SPACE number SPACE number
142
+ #
143
+ # quota_response ::= "QUOTA" SPACE astring SPACE quota_list
144
+ #
145
+ # ==== Fields:
146
+ #
147
+ # mailbox:: The mailbox with the associated quota.
148
+ #
149
+ # usage:: Current storage usage of the mailbox.
150
+ #
151
+ # quota:: Quota limit imposed on the mailbox.
152
+ #
153
+ class MailboxQuota < Struct.new(:mailbox, :usage, :quota)
154
+ end
155
+
156
+ # Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT
157
+ # response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.)
158
+ #
159
+ # quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring)
160
+ #
161
+ # ==== Fields:
162
+ #
163
+ # mailbox:: The mailbox with the associated quota.
164
+ #
165
+ # quotaroots:: Zero or more quotaroots that affect the quota on the
166
+ # specified mailbox.
167
+ #
168
+ class MailboxQuotaRoot < Struct.new(:mailbox, :quotaroots)
169
+ end
170
+
171
+ # Net::IMAP::MailboxACLItem represents the response from GETACL.
172
+ #
173
+ # acl_data ::= "ACL" SPACE mailbox *(SPACE identifier SPACE rights)
174
+ #
175
+ # identifier ::= astring
176
+ #
177
+ # rights ::= astring
178
+ #
179
+ # ==== Fields:
180
+ #
181
+ # user:: Login name that has certain rights to the mailbox
182
+ # that was specified with the getacl command.
183
+ #
184
+ # rights:: The access rights the indicated user has to the
185
+ # mailbox.
186
+ #
187
+ class MailboxACLItem < Struct.new(:user, :rights, :mailbox)
188
+ end
189
+
190
+ # Net::IMAP::Namespace represents a single [RFC-2342] namespace.
191
+ #
192
+ # Namespace = nil / "(" 1*( "(" string SP (<"> QUOTED_CHAR <"> /
193
+ # nil) *(Namespace_Response_Extension) ")" ) ")"
194
+ #
195
+ # Namespace_Response_Extension = SP string SP "(" string *(SP string)
196
+ # ")"
197
+ #
198
+ # ==== Fields:
199
+ #
200
+ # prefix:: Returns the namespace prefix string.
201
+ # delim:: Returns nil or the hierarchy delimiter character.
202
+ # extensions:: Returns a hash of extension names to extension flag arrays.
203
+ #
204
+ class Namespace < Struct.new(:prefix, :delim, :extensions)
205
+ end
206
+
207
+ # Net::IMAP::Namespaces represents the response from [RFC-2342] NAMESPACE.
208
+ #
209
+ # Namespace_Response = "*" SP "NAMESPACE" SP Namespace SP Namespace SP
210
+ # Namespace
211
+ #
212
+ # ; The first Namespace is the Personal Namespace(s)
213
+ # ; The second Namespace is the Other Users' Namespace(s)
214
+ # ; The third Namespace is the Shared Namespace(s)
215
+ #
216
+ # ==== Fields:
217
+ #
218
+ # personal:: Returns an array of Personal Net::IMAP::Namespace objects.
219
+ # other:: Returns an array of Other Users' Net::IMAP::Namespace objects.
220
+ # shared:: Returns an array of Shared Net::IMAP::Namespace objects.
221
+ #
222
+ class Namespaces < Struct.new(:personal, :other, :shared)
223
+ end
224
+
225
+ # Net::IMAP::StatusData represents the contents of the STATUS response.
226
+ #
227
+ # ==== Fields:
228
+ #
229
+ # mailbox:: Returns the mailbox name.
230
+ #
231
+ # attr:: Returns a hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT",
232
+ # "UIDVALIDITY", "UNSEEN". Each value is a number.
233
+ #
234
+ class StatusData < Struct.new(:mailbox, :attr)
235
+ end
236
+
237
+ # Net::IMAP::FetchData represents the contents of the FETCH response.
238
+ #
239
+ # ==== Fields:
240
+ #
241
+ # seqno:: Returns the message sequence number.
242
+ # (Note: not the unique identifier, even for the UID command response.)
243
+ #
244
+ # attr:: Returns a hash. Each key is a data item name, and each value is
245
+ # its value.
246
+ #
247
+ # The current data items are:
248
+ #
249
+ # [BODY]
250
+ # A form of BODYSTRUCTURE without extension data.
251
+ # [BODY[<section>]<<origin_octet>>]
252
+ # A string expressing the body contents of the specified section.
253
+ # [BODYSTRUCTURE]
254
+ # An object that describes the [MIME-IMB] body structure of a message.
255
+ # See Net::IMAP::BodyTypeBasic, Net::IMAP::BodyTypeText,
256
+ # Net::IMAP::BodyTypeMessage, Net::IMAP::BodyTypeMultipart.
257
+ # [ENVELOPE]
258
+ # A Net::IMAP::Envelope object that describes the envelope
259
+ # structure of a message.
260
+ # [FLAGS]
261
+ # A array of flag symbols that are set for this message. Flag symbols
262
+ # are capitalized by String#capitalize.
263
+ # [INTERNALDATE]
264
+ # A string representing the internal date of the message.
265
+ # [RFC822]
266
+ # Equivalent to +BODY[]+.
267
+ # [RFC822.HEADER]
268
+ # Equivalent to +BODY.PEEK[HEADER]+.
269
+ # [RFC822.SIZE]
270
+ # A number expressing the [RFC-822] size of the message.
271
+ # [RFC822.TEXT]
272
+ # Equivalent to +BODY[TEXT]+.
273
+ # [UID]
274
+ # A number expressing the unique identifier of the message.
275
+ #
276
+ class FetchData < Struct.new(:seqno, :attr)
277
+ end
278
+
279
+ # Net::IMAP::Envelope represents envelope structures of messages.
280
+ #
281
+ # ==== Fields:
282
+ #
283
+ # date:: Returns a string that represents the date.
284
+ #
285
+ # subject:: Returns a string that represents the subject.
286
+ #
287
+ # from:: Returns an array of Net::IMAP::Address that represents the from.
288
+ #
289
+ # sender:: Returns an array of Net::IMAP::Address that represents the sender.
290
+ #
291
+ # reply_to:: Returns an array of Net::IMAP::Address that represents the reply-to.
292
+ #
293
+ # to:: Returns an array of Net::IMAP::Address that represents the to.
294
+ #
295
+ # cc:: Returns an array of Net::IMAP::Address that represents the cc.
296
+ #
297
+ # bcc:: Returns an array of Net::IMAP::Address that represents the bcc.
298
+ #
299
+ # in_reply_to:: Returns a string that represents the in-reply-to.
300
+ #
301
+ # message_id:: Returns a string that represents the message-id.
302
+ #
303
+ class Envelope < Struct.new(:date, :subject, :from, :sender, :reply_to,
304
+ :to, :cc, :bcc, :in_reply_to, :message_id)
305
+ end
306
+
307
+ #
308
+ # Net::IMAP::Address represents electronic mail addresses.
309
+ #
310
+ # ==== Fields:
311
+ #
312
+ # name:: Returns the phrase from [RFC-822] mailbox.
313
+ #
314
+ # route:: Returns the route from [RFC-822] route-addr.
315
+ #
316
+ # mailbox:: nil indicates end of [RFC-822] group.
317
+ # If non-nil and host is nil, returns [RFC-822] group name.
318
+ # Otherwise, returns [RFC-822] local-part.
319
+ #
320
+ # host:: nil indicates [RFC-822] group syntax.
321
+ # Otherwise, returns [RFC-822] domain name.
322
+ #
323
+ class Address < Struct.new(:name, :route, :mailbox, :host)
324
+ end
325
+
326
+ #
327
+ # Net::IMAP::ContentDisposition represents Content-Disposition fields.
328
+ #
329
+ # ==== Fields:
330
+ #
331
+ # dsp_type:: Returns the disposition type.
332
+ #
333
+ # param:: Returns a hash that represents parameters of the Content-Disposition
334
+ # field.
335
+ #
336
+ class ContentDisposition < Struct.new(:dsp_type, :param)
337
+ end
338
+
339
+ # Net::IMAP::ThreadMember represents a thread-node returned
340
+ # by Net::IMAP#thread.
341
+ #
342
+ # ==== Fields:
343
+ #
344
+ # seqno:: The sequence number of this message.
345
+ #
346
+ # children:: An array of Net::IMAP::ThreadMember objects for mail
347
+ # items that are children of this in the thread.
348
+ #
349
+ class ThreadMember < Struct.new(:seqno, :children)
350
+ end
351
+
352
+ # Net::IMAP::BodyTypeBasic represents basic body structures of messages.
353
+ #
354
+ # ==== Fields:
355
+ #
356
+ # media_type:: Returns the content media type name as defined in [MIME-IMB].
357
+ #
358
+ # subtype:: Returns the content subtype name as defined in [MIME-IMB].
359
+ #
360
+ # param:: Returns a hash that represents parameters as defined in [MIME-IMB].
361
+ #
362
+ # content_id:: Returns a string giving the content id as defined in [MIME-IMB].
363
+ #
364
+ # description:: Returns a string giving the content description as defined in
365
+ # [MIME-IMB].
366
+ #
367
+ # encoding:: Returns a string giving the content transfer encoding as defined in
368
+ # [MIME-IMB].
369
+ #
370
+ # size:: Returns a number giving the size of the body in octets.
371
+ #
372
+ # md5:: Returns a string giving the body MD5 value as defined in [MD5].
373
+ #
374
+ # disposition:: Returns a Net::IMAP::ContentDisposition object giving
375
+ # the content disposition.
376
+ #
377
+ # language:: Returns a string or an array of strings giving the body
378
+ # language value as defined in [LANGUAGE-TAGS].
379
+ #
380
+ # extension:: Returns extension data.
381
+ #
382
+ # multipart?:: Returns false.
383
+ #
384
+ class BodyTypeBasic < Struct.new(:media_type, :subtype,
385
+ :param, :content_id,
386
+ :description, :encoding, :size,
387
+ :md5, :disposition, :language,
388
+ :extension)
389
+ def multipart?
390
+ return false
391
+ end
392
+
393
+ # Obsolete: use +subtype+ instead. Calling this will
394
+ # generate a warning message to +stderr+, then return
395
+ # the value of +subtype+.
396
+ def media_subtype
397
+ warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
398
+ return subtype
399
+ end
400
+ end
401
+
402
+ # Net::IMAP::BodyTypeText represents TEXT body structures of messages.
403
+ #
404
+ # ==== Fields:
405
+ #
406
+ # lines:: Returns the size of the body in text lines.
407
+ #
408
+ # And Net::IMAP::BodyTypeText has all fields of Net::IMAP::BodyTypeBasic.
409
+ #
410
+ class BodyTypeText < Struct.new(:media_type, :subtype,
411
+ :param, :content_id,
412
+ :description, :encoding, :size,
413
+ :lines,
414
+ :md5, :disposition, :language,
415
+ :extension)
416
+ def multipart?
417
+ return false
418
+ end
419
+
420
+ # Obsolete: use +subtype+ instead. Calling this will
421
+ # generate a warning message to +stderr+, then return
422
+ # the value of +subtype+.
423
+ def media_subtype
424
+ warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
425
+ return subtype
426
+ end
427
+ end
428
+
429
+ # Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages.
430
+ #
431
+ # ==== Fields:
432
+ #
433
+ # envelope:: Returns a Net::IMAP::Envelope giving the envelope structure.
434
+ #
435
+ # body:: Returns an object giving the body structure.
436
+ #
437
+ # And Net::IMAP::BodyTypeMessage has all methods of Net::IMAP::BodyTypeText.
438
+ #
439
+ class BodyTypeMessage < Struct.new(:media_type, :subtype,
440
+ :param, :content_id,
441
+ :description, :encoding, :size,
442
+ :envelope, :body, :lines,
443
+ :md5, :disposition, :language,
444
+ :extension)
445
+ def multipart?
446
+ return false
447
+ end
448
+
449
+ # Obsolete: use +subtype+ instead. Calling this will
450
+ # generate a warning message to +stderr+, then return
451
+ # the value of +subtype+.
452
+ def media_subtype
453
+ warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
454
+ return subtype
455
+ end
456
+ end
457
+
458
+ # Net::IMAP::BodyTypeAttachment represents attachment body structures
459
+ # of messages.
460
+ #
461
+ # ==== Fields:
462
+ #
463
+ # media_type:: Returns the content media type name.
464
+ #
465
+ # subtype:: Returns +nil+.
466
+ #
467
+ # param:: Returns a hash that represents parameters.
468
+ #
469
+ # multipart?:: Returns false.
470
+ #
471
+ class BodyTypeAttachment < Struct.new(:media_type, :subtype,
472
+ :param)
473
+ def multipart?
474
+ return false
475
+ end
476
+ end
477
+
478
+ # Net::IMAP::BodyTypeMultipart represents multipart body structures
479
+ # of messages.
480
+ #
481
+ # ==== Fields:
482
+ #
483
+ # media_type:: Returns the content media type name as defined in [MIME-IMB].
484
+ #
485
+ # subtype:: Returns the content subtype name as defined in [MIME-IMB].
486
+ #
487
+ # parts:: Returns multiple parts.
488
+ #
489
+ # param:: Returns a hash that represents parameters as defined in [MIME-IMB].
490
+ #
491
+ # disposition:: Returns a Net::IMAP::ContentDisposition object giving
492
+ # the content disposition.
493
+ #
494
+ # language:: Returns a string or an array of strings giving the body
495
+ # language value as defined in [LANGUAGE-TAGS].
496
+ #
497
+ # extension:: Returns extension data.
498
+ #
499
+ # multipart?:: Returns true.
500
+ #
501
+ class BodyTypeMultipart < Struct.new(:media_type, :subtype,
502
+ :parts,
503
+ :param, :disposition, :language,
504
+ :extension)
505
+ def multipart?
506
+ return true
507
+ end
508
+
509
+ # Obsolete: use +subtype+ instead. Calling this will
510
+ # generate a warning message to +stderr+, then return
511
+ # the value of +subtype+.
512
+ def media_subtype
513
+ warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
514
+ return subtype
515
+ end
516
+ end
517
+
518
+ class BodyTypeExtension < Struct.new(:media_type, :subtype,
519
+ :params, :content_id,
520
+ :description, :encoding, :size)
521
+ def multipart?
522
+ return false
523
+ end
524
+ end
525
+
526
+ end
527
+ end