imap.rb/lib/imap_server/client_handler/search.rb
2022-12-10 22:16:49 +01:00

127 lines
4.2 KiB
Ruby

class ImapServer
class ClientHandler
module Search
# <sequence set>
# Messages with message sequence numbers corresponding to the
# specified message sequence number set.
# BCC <string>
# Messages that contain the specified string in the envelope
# structure's BCC field.
# BEFORE <date>
# Messages whose internal date (disregarding time and timezone)
# is earlier than the specified date.
# BODY <string>
# Messages that contain the specified string in the body of the
# message.
# CC <string>
# Messages that contain the specified string in the envelope
# structure's CC field.
# FROM <string>
# Messages that contain the specified string in the envelope
# structure's FROM field.
# HEADER <field-name> <string>
# Messages that have a header with the specified field-name (as
# defined in [RFC-2822]) and that contains the specified string
# in the text of the header (what comes after the colon). If the
# string to search is zero-length, this matches all messages that
# have a header line with the specified field-name regardless of
# the contents.
# KEYWORD <flag>
# Messages with the specified keyword flag set.
# LARGER <n>
# Messages with an [RFC-2822] size larger than the specified
# number of octets.
# ON <date>
# Messages whose internal date (disregarding time and timezone)
# is within the specified date.
# SENTBEFORE <date>
# Messages whose [RFC-2822] Date: header (disregarding time and
# timezone) is earlier than the specified date.
# SENTON <date>
# Messages whose [RFC-2822] Date: header (disregarding time and
# timezone) is within the specified date.
# SENTSINCE <date>
# Messages whose [RFC-2822] Date: header (disregarding time and
# timezone) is within or later than the specified date.
# SINCE <date>
# Messages whose internal date (disregarding time and timezone)
# is within or later than the specified date.
# SMALLER <n>
# Messages with an [RFC-2822] size smaller than the specified
# number of octets.
# SUBJECT <string>
# Messages that contain the specified string in the envelope
# structure's SUBJECT field.
# TEXT <string>
# Messages that contain the specified string in the header or
# body of the message.
# TO <string>
# Messages that contain the specified string in the envelope
# structure's TO field.
# UNKEYWORD <flag>
# Messages that do not have the specified keyword flag set.
# Example:
# C: A282 SEARCH FLAGGED SINCE 1-Feb-1994 NOT FROM "Smith"
# S: * SEARCH 2 84 882
# S: A282 OK SEARCH completed
# C: A283 SEARCH TEXT "string not in mailbox"
# S: * SEARCH
# S: A283 OK SEARCH completed
# C: A284 SEARCH CHARSET UTF-8 TEXT {6}
# C: XXXXXX
# S: * SEARCH 43
# S: A284 OK SEARCH completed
# TODO: properly factorize the code so we get the UID and we can translate them into seq id
def handle_search(msg:, user:)
return msg.error_need_loggin if !user
return msg.respond ServerMessage.new("BAD no selected mailbox", tag: msg.tag) if !msg.handler.selected
handle_search_request(msg: msg, mailbox: msg.handler.selected)
end
private
def handle_search_request(msg:, mailbox:)
return msg.respond ServerMessage.new("KO mailbox #{mailbox_path} do not exists") if !mailbox
msg.handler.selected = mailbox
mutable_args = msg.args.dup
mutable_args << "ALL" if mutable_args.empty?
builder = Builder.new(mailbox)
while (arg = mutable_args.shift)
builder.apply_token!(arg, mutable_args)
end
mails_results = builder.conclude!
results_uids = mails_results.map { _1.uid }.join(" ")
msg.respond ServerMessage.new("SEARCH #{results_uids}")
msg.respond ServerMessage.new("OK SEARCH completed", tag: msg.tag)
end
require_relative "search/builder"
end
end
end