class Net::IMAP::FetchData - net-imap: Ruby Standard Library Documentation

# class Net::IMAP::FetchData

`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 Message envelope and body structure at `Net::IMAP` 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:

- `CONDSTORE` [RFC7162]:

  - `"MODSEQ"` — See `modseq`.

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

  - `"X-GM-LABELS"` — Gmail labels. Access via `attr`.

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}]`.

### Public Instance Methods

attr → hash click to toggle source

Each key specifies a message attribute, and the value is the corresponding data item. Standard data items have corresponding accessor methods. The definitions of each attribute type is documented on its accessor.

> Note: `seqno` is not a message attribute.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 119

attr_upcase → hash click to toggle source

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`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 136
    def attr_upcase; attr.transform_keys(&:upcase) end

binary(*part_nums, offset: nil) → string or nil click to toggle source

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`

    # File net-imap-0.5.4/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) → integer or nil click to toggle source

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`

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 451
    def binary_size(*part_nums)
      attr[section_attr("BINARY.SIZE", part_nums)]
    end

body → body structure or nil click to toggle source

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.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 148
    def body; attr["BODY"] end

body_structure()
Alias for: bodystructure
bodystructure → BodyStructure struct or nil click to toggle source

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

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

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 310
    def bodystructure; attr["BODYSTRUCTURE"] end

Also aliased as: body_structure
emailid → string or nil click to toggle source

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].

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 484
    def emailid; attr["EMAILID"] end

envelope → Envelope or nil click to toggle source

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`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 321
    def envelope; attr["ENVELOPE"] end

flags → array of Symbols and Strings click to toggle source

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.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 334
    def flags; attr["FLAGS"] end

header(*part_nums, offset: nil) → string or nil click to toggle source
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`

    # File net-imap-0.5.4/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(*names, part: [], offset: nil) → string or nil click to toggle source

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

    # File net-imap-0.5.4/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(*names, part: [], offset: nil) → string or nil click to toggle source

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

    # File net-imap-0.5.4/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

internal_date()
Alias for: internaldate
internaldate → Time or nil click to toggle source

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.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 349
    def internaldate
      attr["INTERNALDATE"]&.then { IMAP.decode_time _1 }
    end

Also aliased as: internal_date
message(offset: bytes) → string or nil click to toggle source

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`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 164
    def message(offset: nil) attr[body_section_attr(offset: offset)] end

mime(*part_nums) → string or nil click to toggle source
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`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 278
    def mime(part, *subparts, offset: nil)
      attr[body_section_attr([part, *subparts], "MIME", offset: offset)]
    end

modseq → Integer click to toggle source

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.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 467
    def modseq; attr["MODSEQ"] end

part(*part_nums, offset: bytes) → string or nil click to toggle source

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`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 186
    def part(index, *subparts, offset: nil)
      attr[body_section_attr([index, *subparts], offset: offset)]
    end

rfc822 → String click to toggle source

Semantically equivalent to `message` with no arguments.

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

Note

  `IMAP4rev2` deprecates `RFC822`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 362
    def rfc822; attr["RFC822"] end

rfc822_header → String click to toggle source

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`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 392
    def rfc822_header; attr["RFC822.HEADER"] end

rfc822_size -> Integer click to toggle source

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.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 381
    def rfc822_size; attr["RFC822.SIZE"] end

Also aliased as: size
rfc822_text → String click to toggle source

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`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 403
    def rfc822_text; attr["RFC822.TEXT"] end

seqno → Integer click to toggle source

The message sequence number.

Note

  This is never the unique identifier (UID), not even for the `Net::IMAP#uid_fetch` result. The UID is available from `uid`, if it was returned.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 108

size()
Alias for: rfc822_size
text(*part_nums) → string or nil click to toggle source
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`.

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 299
    def text(*part, offset: nil)
      attr[body_section_attr(part, "TEXT", offset: offset)]
    end

threadid → string or nil click to toggle source

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].

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 501
    def threadid; attr["THREADID"] end

uid → Integer click to toggle source

A number expressing the unique identifier of the message.

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

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 410
    def uid; attr["UID"] end

### Private Instance Methods

body_section_attr(...) click to toggle source

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 505
    def body_section_attr(...) section_attr("BODY", ...) end

section_attr(attr, part = [], text = nil, offset: nil) click to toggle source

    # File net-imap-0.5.4/lib/net/imap/fetch_data.rb, line 507
    def section_attr(attr, part = [], text = nil, offset: nil)
      spec = Array(part).flatten.map { Integer(_1) }
      spec << text if text
      spec = spec.join(".")
      if offset then "%s[%s]<%d>" % [attr, spec, Integer(offset)]
      else           "%s[%s]"     % [attr, spec]
      end
    end