Class: Net::IMAP::FetchData

Inherits:
Struct
  • Object
show all
Defined in:
lib/net/imap/fetch_data.rb

Overview

Net::IMAP::FetchData represents the contents of a FETCH response. Net::IMAP#fetch and Net::IMAP#uid_fetch both return an array of FetchData objects.

Fetch attributes

See [IMAP4rev1 §7.4.2] and [IMAP4rev2 §7.5.2] for a full description of the standard fetch response data items, and Net::IMAP@Message+envelope+and+body+structure for other relevant RFCs.

Static fetch data items

Most message attributes are static, and must never change for a given (server, account, mailbox, UIDVALIDITY, UID) tuple.

The static fetch data items defined by both IMAP4rev1 and IMAP4rev2 are:

  • "UID" — See #uid.

  • "BODY" — See #body.

  • "BODY[#{section_spec}]", "BODY[#{section_spec}]<#{offset}>" — See #message, #part, #header, #header_fields, #header_fields_not, #mime, and #text.

  • "BODYSTRUCTURE" — See #bodystructure.

  • "ENVELOPE" — See #envelope.

  • "INTERNALDATE" — See #internaldate.

  • "RFC822.SIZE" — See #rfc822_size.

IMAP4rev2 adds the additional fetch items from the BINARY extension [RFC3516]:

  • "BINARY[#{part}]", "BINARY[#{part}]<#{offset}>" – See #binary.

  • "BINARY.SIZE[#{part}]" – See #binary_size.

Several static message attributes in IMAP4rev1 are obsolete and been removed from IMAP4rev2:

  • "RFC822" — See #rfc822 or replace with "BODY[]" and #message.

  • "RFC822.HEADER" — See #rfc822_header or replace with "BODY[HEADER]" and #header.

  • "RFC822.TEXT" — See #rfc822_text or replace with "BODY[TEXT]" and #text.

Net::IMAP supports static attributes defined by the following extensions:

  • OBJECTID [RFC8474]

    • "EMAILID" — See #emailid.

    • "THREADID" — See #threadid.

  • X-GM-EXT-1 [non-standard Gmail extension]

    • "X-GM-MSGID" — unique message ID. Access via #attr.

    • "X-GM-THRID" — Thread ID. Access via #attr.

Note:

Additional static fields are defined in other IMAP extensions, but Net::IMAP can’t parse them yet.

Dynamic message attributes

Some message attributes can be dynamically changed, for example using the STORE command.

The only dynamic message attribute defined by IMAP4rev1 and IMAP4rev2 is:

  • "FLAGS" — See #flags.

Net::IMAP supports dynamic attributes defined by the following extensions:

Note:

Additional dynamic fields are defined in other IMAP extensions, but Net::IMAP can’t parse them yet.

Implicitly setting \Seen and using PEEK

Unless the mailbox is has been opened as read-only, fetching BODY[#{section}] or BINARY[#{section}] will implicitly set the \Seen flag. To avoid this, fetch using BODY.PEEK[#{section}] or BINARY.PEEK[#{section}] instead.

Note that the data will always be returned without ".PEEK", in BODY[#{specifier}] or BINARY[#{section}].

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#attrObject

Returns the value of attribute attr

Returns:

  • (Object)

    the current value of attr



106
107
108
# File 'lib/net/imap/fetch_data.rb', line 106

def attr
  @attr
end

#seqnoObject

Returns the value of attribute seqno

Returns:

  • (Object)

    the current value of seqno



106
107
108
# File 'lib/net/imap/fetch_data.rb', line 106

def seqno
  @seqno
end

Instance Method Details

#attr_upcaseObject

:call-seq: attr_upcase -> hash

A transformation of #attr, with all the keys converted to upper case.

Header field names are case-preserved but not case-sensitive, so this is used by #header_fields and #header_fields_not.



136
# File 'lib/net/imap/fetch_data.rb', line 136

def attr_upcase; attr.transform_keys(&:upcase) end

#binary(*part_nums, offset: nil) ⇒ Object

:call-seq:

binary(*part_nums, offset: nil) -> string or nil

Returns the binary representation of a particular MIME part, which has already been decoded according to its Content-Transfer-Encoding.

See #part for a description of part_nums and offset.

This is the same as getting the value of "BINARY[#{part_nums.join(".")}]" or "BINARY[#{part_nums.join(".")}]<#{offset}>" from #attr.

The server must support either IMAP4rev2 or the BINARY extension [RFC3516].

See also: #binary_size, #mime



430
431
432
# File 'lib/net/imap/fetch_data.rb', line 430

def binary(*part_nums, offset: nil)
  attr[section_attr("BINARY", part_nums, offset: offset)]
end

#binary_size(*part_nums) ⇒ Object

:call-seq:

binary_size(*part_nums) -> integer or nil

Returns the decoded size of a particular MIME part (the size to expect in response to a BINARY fetch request).

See #part for a description of part_nums.

This is the same as getting the value of "BINARY.SIZE[#{part_nums.join(".")}]" from #attr.

The server must support either IMAP4rev2 or the BINARY extension [RFC3516].

See also: #binary, #mime



451
452
453
# File 'lib/net/imap/fetch_data.rb', line 451

def binary_size(*part_nums)
  attr[section_attr("BINARY.SIZE", part_nums)]
end

#bodyObject

:call-seq:

body -> body structure or nil

Returns an alternate form of #bodystructure, without any extension data.

This is the same as getting the value for "BODY" from #attr.

Note

Use #message, #part, #header, #header_fields, #header_fields_not, #text, or #mime to retrieve BODY[#{section_spec}] attributes.



148
# File 'lib/net/imap/fetch_data.rb', line 148

def body; attr["BODY"] end

#bodystructureObject Also known as: body_structure

:call-seq:

bodystructure -> BodyStructure struct or nil

A BodyStructure object that describes the message, if it was fetched.

This is the same as getting the value for "BODYSTRUCTURE" from #attr.



310
# File 'lib/net/imap/fetch_data.rb', line 310

def bodystructure; attr["BODYSTRUCTURE"] end

#emailidObject

:call-seq: emailid -> string or nil

An ObjectID that uniquely identifies the immutable content of a single message.

The server must return the same EMAILID for both the source and destination messages after a COPY or MOVE command. However, it is possible for different messages with the same EMAILID to have different mutable attributes, such as flags.

This is the same as getting the value for "EMAILID" from #attr.

The server must support the OBJECTID extension [RFC8474].



484
# File 'lib/net/imap/fetch_data.rb', line 484

def emailid; attr["EMAILID"] end

#envelopeObject

:call-seq: envelope -> Envelope or nil

An Envelope object that describes the envelope structure of a message. See the documentation for Envelope for a description of the envelope structure attributes.

This is the same as getting the value for "ENVELOPE" from #attr.



321
# File 'lib/net/imap/fetch_data.rb', line 321

def envelope; attr["ENVELOPE"] end

#flagsObject

:call-seq: flags -> array of Symbols and Strings

A array of flags that are set for this message. System flags are symbols that have been capitalized by String#capitalize. Keyword flags are strings and their case is not changed.

This is the same as getting the value for "FLAGS" from #attr.

Note

The FLAGS field is dynamic, and can change for a uniquely identified message.



334
# File 'lib/net/imap/fetch_data.rb', line 334

def flags; attr["FLAGS"] end

#header(*part_nums, fields: nil, except: nil, offset: nil) ⇒ Object

:call-seq:

header(*part_nums,                offset: nil) -> string or nil
header(*part_nums, fields: names, offset: nil) -> string or nil
header(*part_nums, except: names, offset: nil) -> string or nil

The [RFC5322] header of a message or of an encapsulated [MIME-IMT] MESSAGE/RFC822 or MESSAGE/GLOBAL message.

Headers can be parsed using the “mail” gem.

See #part for a description of part_nums and offset.

Without fields or except

This is the same as getting the value from #attr for one of:

  • BODY[HEADER]

  • BODY[HEADER]<#{offset}>

  • BODY[#{part_nums.join "."}.HEADER]"

  • BODY[#{part_nums.join "."}.HEADER]<#{offset}>"

With fields

When fields is sent, returns a subset of the header which contains only the header fields that match one of the names in the list.

This is the same as getting the value from #attr_upcase for one of:

  • BODY[HEADER.FIELDS (#{names.join " "})]

  • BODY[HEADER.FIELDS (#{names.join " "})]<#{offset}>

  • BODY[#{part_nums.join "."}.HEADER.FIELDS (#{names.join " "})]

  • BODY[#{part_nums.join "."}.HEADER.FIELDS (#{names.join " "})]<#{offset}>

See also: #header_fields

With except

When except is sent, returns a subset of the header which contains only the header fields that do not match one of the names in the list.

This is the same as getting the value from #attr_upcase for one of:

  • BODY[HEADER.FIELDS.NOT (#{names.join " "})]

  • BODY[HEADER.FIELDS.NOT (#{names.join " "})]<#{offset}>

  • BODY[#{part_nums.join "."}.HEADER.FIELDS.NOT (#{names.join " "})]

  • BODY[#{part_nums.join "."}.HEADER.FIELDS.NOT (#{names.join " "})]<#{offset}>

See also: #header_fields_not



234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/net/imap/fetch_data.rb', line 234

def header(*part_nums, fields: nil, except: nil, offset: nil)
  fields && except and
    raise ArgumentError, "conflicting 'fields' and 'except' arguments"
  if fields
    text = "HEADER.FIELDS (%s)"     % [fields.join(" ").upcase]
    attr_upcase[body_section_attr(part_nums, text, offset: offset)]
  elsif except
    text = "HEADER.FIELDS.NOT (%s)" % [except.join(" ").upcase]
    attr_upcase[body_section_attr(part_nums, text, offset: offset)]
  else
    attr[body_section_attr(part_nums, "HEADER", offset: offset)]
  end
end

#header_fields(first, *rest, part: [], offset: nil) ⇒ Object

:call-seq:

header_fields(*names, part: [], offset: nil) -> string or nil

The result from #header when called with fields: names.



252
253
254
# File 'lib/net/imap/fetch_data.rb', line 252

def header_fields(first, *rest, part: [], offset: nil)
  header(*part, fields: [first, *rest], offset: offset)
end

#header_fields_not(first, *rest, part: [], offset: nil) ⇒ Object

:call-seq:

header_fields_not(*names, part: [], offset: nil) -> string or nil

The result from #header when called with except: names.



260
261
262
# File 'lib/net/imap/fetch_data.rb', line 260

def header_fields_not(first, *rest, part: [], offset: nil)
  header(*part, except: [first, *rest], offset: offset)
end

#internaldateObject Also known as: internal_date

:call-seq: internaldate -> Time or nil

The internal date and time of the message on the server. This is not the date and time in the [RFC5322] header, but rather a date and time which reflects when the message was received.

This is similar to getting the value for "INTERNALDATE" from #attr.

Note

attr["INTERNALDATE"] returns a string, and this method returns a Time object.



349
350
351
# File 'lib/net/imap/fetch_data.rb', line 349

def internaldate
  attr["INTERNALDATE"]&.then { IMAP.decode_time _1 }
end

#message(offset: nil) ⇒ Object

:call-seq:

message(offset: bytes) -> string or nil

The RFC5322 expression of the entire message, as a string.

See #part for a description of offset.

RFC5322 messages can be parsed using the “mail” gem.

This is the same as getting the value for "BODY[]" or "BODY[]<#{offset}>" from #attr.

See also: #header, #text, and #mime.



164
# File 'lib/net/imap/fetch_data.rb', line 164

def message(offset: nil) attr[body_section_attr(offset: offset)] end

#mime(part, *subparts, offset: nil) ⇒ Object

:call-seq:

mime(*part_nums)                -> string or nil
mime(*part_nums, offset: bytes) -> string or nil

The [MIME-IMB] header for a message part, if it was fetched.

See #part for a description of part_nums and offset.

This is the same as getting the value for "BODY[#{part_nums}.MIME]" or "BODY[#{part_nums}.MIME]<#{offset}>" from #attr.

See also: #message, #header, and #text.



278
279
280
# File 'lib/net/imap/fetch_data.rb', line 278

def mime(part, *subparts, offset: nil)
  attr[body_section_attr([part, *subparts], "MIME", offset: offset)]
end

#modseqObject

:call-seq: modseq -> Integer

The modification sequence number associated with this IMAP message.

This is the same as getting the value for "MODSEQ" from #attr.

The server must support the CONDSTORE extension [RFC7162].

Note

The MODSEQ field is dynamic, and can change for a uniquely identified message.



467
# File 'lib/net/imap/fetch_data.rb', line 467

def modseq; attr["MODSEQ"] end

#part(index, *subparts, offset: nil) ⇒ Object

:call-seq:

part(*part_nums, offset: bytes) -> string or nil

The string representation of a particular MIME part.

part_nums forms a path of MIME part numbers, counting up from 1, which may specify an arbitrarily nested part, similarly to Array#dig. Messages that don’t use MIME, or MIME messages that are not multipart and don’t hold an encapsulated message, only have part 1.

If a zero-based offset is given, the returned string is a substring of the entire contents, starting at that origin octet. This means that BODY[]<0> MAY be truncated, but BODY[] is never truncated.

This is the same as getting the value of "BODY[#{part_nums.join(".")}]" or "BODY[#{part_nums.join(".")}]<#{offset}>" from #attr.

See also: #message, #header, #text, and #mime.



186
187
188
# File 'lib/net/imap/fetch_data.rb', line 186

def part(index, *subparts, offset: nil)
  attr[body_section_attr([index, *subparts], offset: offset)]
end

#rfc822Object

:call-seq: rfc822 -> String

Semantically equivalent to #message with no arguments.

This is the same as getting the value for "RFC822" from #attr.

Note

IMAP4rev2 deprecates RFC822.



362
# File 'lib/net/imap/fetch_data.rb', line 362

def rfc822; attr["RFC822"] end

#rfc822_headerObject

:call-seq: rfc822_header -> String

Semantically equivalent to #header, with no arguments.

This is the same as getting the value for "RFC822.HEADER" from #attr.

Note

IMAP4rev2 deprecates RFC822.HEADER.



392
# File 'lib/net/imap/fetch_data.rb', line 392

def rfc822_header; attr["RFC822.HEADER"] end

#rfc822_sizeObject Also known as: size

:call-seq: rfc822_size -> Integer

A number expressing the [RFC5322] size of the message.

This is the same as getting the value for "RFC822.SIZE" from #attr.

Note

IMAP was originally developed for the older RFC822 standard, and as a consequence several fetch items in IMAP incorporate “RFC822” in their name. With the exception of RFC822.SIZE, there are more modern replacements; for example, the modern version of RFC822.HEADER is BODY.PEEK[HEADER]. In all cases, “RFC822” should be interpreted as a reference to the updated RFC5322 standard.



381
# File 'lib/net/imap/fetch_data.rb', line 381

def rfc822_size; attr["RFC822.SIZE"] end

#rfc822_textObject

:call-seq: rfc822_text -> String

Semantically equivalent to #text, with no arguments.

This is the same as getting the value for "RFC822.TEXT" from #attr.

Note

IMAP4rev2 deprecates RFC822.TEXT.



403
# File 'lib/net/imap/fetch_data.rb', line 403

def rfc822_text; attr["RFC822.TEXT"] end

#text(*part, offset: nil) ⇒ Object

:call-seq:

text(*part_nums)                -> string or nil
text(*part_nums, offset: bytes) -> string or nil

The text body of a message or a message part, if it was fetched, omitting the [RFC5322] header.

See #part for a description of part_nums and offset.

This is the same as getting the value from #attr for one of:

  • "BODY[TEXT]",

  • "BODY[TEXT]<#{offset}>",

  • "BODY[#{section}.TEXT]", or

  • "BODY[#{section}.TEXT]<#{offset}>".

See also: #message, #header, and #mime.



299
300
301
# File 'lib/net/imap/fetch_data.rb', line 299

def text(*part, offset: nil)
  attr[body_section_attr(part, "TEXT", offset: offset)]
end

#threadidObject

:call-seq: threadid -> string or nil

An ObjectID that uniquely identifies a set of messages that the server believes should be grouped together.

It is generally based on some combination of References, In-Reply-To, and Subject, but the exact implementation is left up to the server implementation. The server should return the same thread identifier for related messages, even if they are in different mailboxes.

This is the same as getting the value for "THREADID" from #attr.

The server must support the OBJECTID extension [RFC8474].



501
# File 'lib/net/imap/fetch_data.rb', line 501

def threadid; attr["THREADID"] end

#uidObject

:call-seq: uid -> Integer

A number expressing the unique identifier of the message.

This is the same as getting the value for "UID" from #attr.



410
# File 'lib/net/imap/fetch_data.rb', line 410

def uid; attr["UID"] end