CrackedRuby logo

CrackedRuby

Net::IMAP

Overview

Net::IMAP provides Ruby's standard interface for communicating with IMAP email servers. The library implements the Internet Message Access Protocol for retrieving, managing, and synchronizing email messages across mailboxes and folders.

The primary class Net::IMAP handles server connections, authentication, and protocol commands. Unlike POP3 which downloads messages locally, IMAP maintains messages on the server while providing access to folder structures, message metadata, and selective content retrieval.

require 'net/imap'

# Create connection to IMAP server
imap = Net::IMAP.new('imap.example.com', 993, ssl: true)
imap.login('username', 'password')

# Select mailbox and retrieve message count
imap.select('INBOX')
message_count = imap.status('INBOX', ['MESSAGES'])['MESSAGES']
# => 1247

Net::IMAP operates through a command-response model where each method sends IMAP protocol commands to the server and returns structured response data. The library automatically handles protocol formatting, response parsing, and connection management.

# Search for recent unread messages
message_ids = imap.search(['RECENT', 'UNSEEN'])
# => [1243, 1244, 1245, 1246, 1247]

# Fetch specific message attributes
messages = imap.fetch(message_ids, ['UID', 'ENVELOPE', 'FLAGS'])
messages.each do |msg|
  envelope = msg.attr['ENVELOPE']
  puts "From: #{envelope.from[0].name} <#{envelope.from[0].mailbox}@#{envelope.from[0].host}>"
  puts "Subject: #{envelope.subject}"
end

The library supports standard IMAP features including folder management, message searching, flag operations, and partial content retrieval. Advanced capabilities include IDLE connections for push notifications, quota management, and extension support for server-specific features.

Basic Usage

Establishing connections requires specifying the server hostname, port, and security options. Most production IMAP servers use SSL encryption on port 993, though some configurations use STARTTLS on port 143.

require 'net/imap'

# SSL connection (recommended)
imap = Net::IMAP.new('imap.gmail.com', 993, ssl: true)

# STARTTLS connection
imap_starttls = Net::IMAP.new('imap.example.com', 143)
imap_starttls.starttls

Authentication supports multiple methods including LOGIN, PLAIN, and OAUTH. The login method accepts username and password credentials, while authenticate allows for advanced authentication mechanisms.

# Standard authentication
imap.login('user@example.com', 'password')

# OAuth2 authentication (Gmail example)
imap.authenticate('XOAUTH2', 'user@example.com', oauth_token)

# List available capabilities
capabilities = imap.capability
# => ["IMAP4REV1", "UNSELECT", "IDLE", "NAMESPACE", "QUOTA", ...]

Mailbox operations begin with selecting a folder, which makes it the active mailbox for subsequent commands. The select method returns mailbox information including message count and available flags.

# Select mailbox and get status
mailbox_info = imap.select('INBOX')
puts "Messages: #{mailbox_info['EXISTS']}"
puts "Recent: #{mailbox_info['RECENT']}"
puts "Unseen: #{mailbox_info['UNSEEN']}"

# List all available folders
folders = imap.list('', '*')
folders.each { |folder| puts folder.name }

Message retrieval uses sequence numbers or UIDs to identify specific messages. The fetch method retrieves message attributes, headers, or body content based on specified data items.

# Fetch recent messages with envelope and flags
recent_messages = imap.fetch(-10..-1, ['UID', 'ENVELOPE', 'FLAGS', 'RFC822.SIZE'])

recent_messages.each do |message|
  uid = message.attr['UID']
  envelope = message.attr['ENVELOPE']
  size = message.attr['RFC822.SIZE']
  
  puts "UID: #{uid}"
  puts "Subject: #{envelope.subject}"
  puts "From: #{envelope.from[0].mailbox}@#{envelope.from[0].host}"
  puts "Size: #{size} bytes"
  puts "---"
end

Search functionality allows filtering messages by criteria such as sender, subject, date ranges, or message flags. Search conditions can be combined using boolean logic for complex queries.

# Search for unread messages from specific sender
unread_from_boss = imap.search(['FROM', 'boss@company.com', 'UNSEEN'])

# Search for messages in date range with subject containing keyword
date_range = imap.search([
  'SINCE', Date.new(2024, 1, 1).strftime('%d-%b-%Y'),
  'BEFORE', Date.new(2024, 2, 1).strftime('%d-%b-%Y'),
  'SUBJECT', 'quarterly report'
])

# Fetch full message content for first result
if date_range.any?
  full_message = imap.fetch(date_range.first, 'RFC822')[0].attr['RFC822']
  puts full_message
end

Error Handling & Debugging

Net::IMAP raises specific exception types for different error conditions. Network connectivity issues, authentication failures, and protocol errors each have distinct exception classes that enable targeted error handling.

Net::IMAP::NoResponseError occurs when the server returns a NO response, typically indicating invalid commands or insufficient permissions. Net::IMAP::BadResponseError indicates protocol violations or malformed requests.

require 'net/imap'

begin
  imap = Net::IMAP.new('imap.example.com', 993, ssl: true)
  imap.login(username, password)
  
rescue Net::IMAP::NoResponseError => e
  puts "Server rejected command: #{e.message}"
  # Common causes: invalid credentials, locked account, server maintenance
  
rescue Net::IMAP::BadResponseError => e
  puts "Protocol error: #{e.message}"
  # Usually indicates client-side bugs or unsupported server features
  
rescue Errno::ECONNREFUSED
  puts "Connection refused - server may be down or port blocked"
  
rescue Errno::ETIMEDOUT, Timeout::Error
  puts "Connection timed out - network or server issues"
  
rescue OpenSSL::SSL::SSLError => e
  puts "SSL certificate error: #{e.message}"
  # Common with self-signed certificates or hostname mismatches
end

Authentication errors require careful handling since different servers return varying error messages. Gmail returns specific error codes, while other servers may provide generic failure messages.

def secure_imap_login(server, port, username, password)
  retries = 0
  max_retries = 3
  
  begin
    imap = Net::IMAP.new(server, port, ssl: true)
    imap.login(username, password)
    return imap
    
  rescue Net::IMAP::NoResponseError => e
    case e.message
    when /Invalid credentials/i
      raise "Authentication failed: Check username and password"
    when /Account locked/i
      raise "Account temporarily locked due to failed attempts"
    when /Two-factor authentication required/i
      raise "App-specific password required for 2FA accounts"
    else
      raise "Login failed: #{e.message}"
    end
    
  rescue Errno::ECONNRESET, Errno::EPIPE => e
    retries += 1
    if retries <= max_retries
      sleep(2 ** retries)  # Exponential backoff
      retry
    else
      raise "Connection failed after #{max_retries} attempts: #{e.message}"
    end
  end
end

Debug logging helps troubleshoot protocol-level issues by capturing the raw IMAP commands and responses. Enable debugging before establishing connections to log all communication.

# Enable debug logging
Net::IMAP.debug = true

# Custom debug output to file
debug_file = File.open('imap_debug.log', 'w')
original_debug = Net::IMAP.debug
Net::IMAP.debug = debug_file

begin
  imap = Net::IMAP.new('imap.example.com', 993, ssl: true)
  imap.login(username, password)
  
  # All IMAP protocol communication logged to file
  messages = imap.fetch(1..10, ['UID', 'ENVELOPE'])
  
ensure
  debug_file.close
  Net::IMAP.debug = original_debug
end

Connection state management becomes critical for long-running applications. IMAP connections can timeout or be terminated by the server, requiring detection and reconnection logic.

class RobustIMAPClient
  def initialize(server, port, username, password)
    @server = server
    @port = port  
    @username = username
    @password = password
    @imap = nil
    connect
  end
  
  def fetch_messages(range, attributes)
    with_retry do
      ensure_connected
      @imap.select('INBOX')
      @imap.fetch(range, attributes)
    end
  end
  
  private
  
  def connect
    @imap = Net::IMAP.new(@server, @port, ssl: true)
    @imap.login(@username, @password)
  end
  
  def ensure_connected
    # Test connection with NOOP command
    @imap.noop
  rescue Net::IMAP::Error, Errno::EPIPE, Errno::ECONNRESET
    connect
  end
  
  def with_retry(max_retries: 3)
    retries = 0
    begin
      yield
    rescue Net::IMAP::Error, Errno::EPIPE, Errno::ECONNRESET => e
      retries += 1
      if retries <= max_retries
        sleep(retries * 2)
        retry
      else
        raise e
      end
    end
  end
end

Production Patterns

Production deployments require connection pooling and resource management to handle concurrent access and prevent resource exhaustion. Creating IMAP connections for every operation causes performance bottlenecks and may exceed server connection limits.

require 'thread'

class IMAPConnectionPool
  def initialize(server, port, username, password, pool_size: 5)
    @server = server
    @port = port
    @username = username
    @password = password
    @pool = Queue.new
    @mutex = Mutex.new
    
    # Pre-populate pool
    pool_size.times { @pool << create_connection }
  end
  
  def with_connection
    connection = @pool.pop
    yield connection
  ensure
    # Validate connection before returning to pool
    begin
      connection.noop
      @pool << connection
    rescue Net::IMAP::Error
      # Replace broken connection
      @pool << create_connection
    end
  end
  
  def close_all
    until @pool.empty?
      connection = @pool.pop(true) rescue nil
      connection&.disconnect rescue nil
    end
  end
  
  private
  
  def create_connection
    imap = Net::IMAP.new(@server, @port, ssl: true)
    imap.login(@username, @password)
    imap
  end
end

# Usage in web application
pool = IMAPConnectionPool.new('imap.company.com', 993, 'app@company.com', 'password')

# Handle email processing request
def process_recent_emails(pool)
  pool.with_connection do |imap|
    imap.select('INBOX')
    recent_messages = imap.search(['RECENT'])
    
    recent_messages.first(50).each do |msg_id|
      message_data = imap.fetch(msg_id, ['UID', 'ENVELOPE', 'RFC822'])[0]
      
      # Process message in background job
      EmailProcessorJob.perform_later(
        uid: message_data.attr['UID'],
        content: message_data.attr['RFC822']
      )
    end
  end
end

Monitoring and logging provide visibility into application performance and error patterns. Track connection metrics, operation timings, and error frequencies to identify bottlenecks and reliability issues.

class MonitoredIMAPClient
  def initialize(server, port, username, password, logger: nil)
    @imap = Net::IMAP.new(server, port, ssl: true)
    @imap.login(username, password)
    @logger = logger || Logger.new(STDOUT)
    @stats = { operations: 0, errors: 0, total_time: 0 }
  end
  
  def fetch_with_monitoring(range, attributes)
    start_time = Time.now
    
    begin
      @logger.info("Fetching messages #{range} with attributes #{attributes}")
      
      result = @imap.fetch(range, attributes)
      
      elapsed = Time.now - start_time
      @stats[:operations] += 1
      @stats[:total_time] += elapsed
      
      @logger.info("Fetch completed in #{elapsed.round(3)}s, #{result.length} messages")
      result
      
    rescue Net::IMAP::Error => e
      @stats[:errors] += 1
      elapsed = Time.now - start_time
      
      @logger.error("Fetch failed after #{elapsed.round(3)}s: #{e.message}")
      raise e
    end
  end
  
  def performance_report
    return "No operations recorded" if @stats[:operations] == 0
    
    average_time = @stats[:total_time] / @stats[:operations]
    error_rate = (@stats[:errors].to_f / @stats[:operations] * 100).round(2)
    
    <<~REPORT
      IMAP Performance Report:
      Total operations: #{@stats[:operations]}
      Total errors: #{@stats[:errors]}
      Error rate: #{error_rate}%
      Average operation time: #{average_time.round(3)}s
      Total time: #{@stats[:total_time].round(3)}s
    REPORT
  end
end

Configuration management separates environment-specific settings from application code. Use environment variables or configuration files to manage server details, credentials, and operational parameters across development, staging, and production environments.

# config/imap_config.rb
class IMAPConfig
  def self.for_environment(env = ENV['RAILS_ENV'] || 'development')
    case env.to_s
    when 'production'
      {
        server: ENV.fetch('IMAP_SERVER'),
        port: ENV.fetch('IMAP_PORT', 993).to_i,
        username: ENV.fetch('IMAP_USERNAME'),
        password: ENV.fetch('IMAP_PASSWORD'),
        ssl: ENV.fetch('IMAP_SSL', 'true') == 'true',
        pool_size: ENV.fetch('IMAP_POOL_SIZE', 10).to_i,
        timeout: ENV.fetch('IMAP_TIMEOUT', 30).to_i
      }
    when 'staging'  
      {
        server: 'staging-imap.company.com',
        port: 993,
        username: ENV.fetch('STAGING_IMAP_USERNAME'),
        password: ENV.fetch('STAGING_IMAP_PASSWORD'),
        ssl: true,
        pool_size: 3,
        timeout: 15
      }
    else # development, test
      {
        server: 'localhost',
        port: 1993,
        username: 'test@example.com',
        password: 'testpass',
        ssl: false,
        pool_size: 2,
        timeout: 10
      }
    end
  end
end

# lib/email_service.rb  
class EmailService
  def initialize
    config = IMAPConfig.for_environment
    @pool = IMAPConnectionPool.new(
      config[:server], 
      config[:port], 
      config[:username], 
      config[:password],
      pool_size: config[:pool_size]
    )
  end
  
  def process_inbox
    @pool.with_connection do |imap|
      imap.select('INBOX')
      process_recent_messages(imap)
    end
  rescue StandardError => e
    Rails.logger.error("Email processing failed: #{e.message}")
    # Send alert to monitoring service
    raise e
  end
end

Performance & Memory

Large mailboxes present significant performance challenges when fetching message data. Retrieving full message content for hundreds of messages simultaneously can cause memory exhaustion and network timeouts.

Selective fetching retrieves only required message attributes instead of complete message data. The ENVELOPE attribute provides sender, subject, and date information without downloading message bodies, reducing bandwidth and memory usage substantially.

require 'benchmark'

def compare_fetch_strategies(imap, message_range)
  puts "Comparing fetch strategies for #{message_range.size} messages"
  
  # Strategy 1: Full message fetch (memory intensive)
  full_fetch_time = Benchmark.realtime do
    full_messages = imap.fetch(message_range, 'RFC822')
    total_size = full_messages.sum { |msg| msg.attr['RFC822'].bytesize }
    puts "Full fetch: #{total_size} bytes loaded"
  end
  
  # Strategy 2: Selective attribute fetch (efficient)
  selective_fetch_time = Benchmark.realtime do
    selective_messages = imap.fetch(message_range, ['UID', 'ENVELOPE', 'FLAGS', 'RFC822.SIZE'])
    total_headers = selective_messages.size
    puts "Selective fetch: #{total_headers} message headers loaded"
  end
  
  puts "Full fetch time: #{full_fetch_time.round(3)}s"
  puts "Selective fetch time: #{selective_fetch_time.round(3)}s"
  puts "Performance improvement: #{(full_fetch_time / selective_fetch_time).round(1)}x"
end

Batch processing prevents memory buildup by processing messages in chunks rather than loading entire mailboxes. This approach maintains constant memory usage regardless of mailbox size.

class EfficientMailProcessor
  def initialize(imap, batch_size: 50)
    @imap = imap
    @batch_size = batch_size
  end
  
  def process_mailbox(mailbox_name)
    @imap.select(mailbox_name)
    total_messages = @imap.status(mailbox_name, ['MESSAGES'])['MESSAGES']
    
    puts "Processing #{total_messages} messages in batches of #{@batch_size}"
    
    (1..total_messages).each_slice(@batch_size) do |batch_range|
      process_batch(batch_range)
      
      # Force garbage collection between batches
      GC.start if batch_range.last % (batch_size * 10) == 0
      
      # Rate limiting to prevent server overload
      sleep(0.1)
    end
  end
  
  private
  
  def process_batch(message_ids)
    start_time = Time.now
    
    # Fetch minimal required data
    messages = @imap.fetch(message_ids, ['UID', 'ENVELOPE', 'FLAGS'])
    
    messages.each do |message|
      process_single_message(message)
    end
    
    batch_time = Time.now - start_time
    puts "Processed #{message_ids.size} messages in #{batch_time.round(3)}s"
  rescue Net::IMAP::Error => e
    puts "Batch processing failed for messages #{message_ids}: #{e.message}"
  end
  
  def process_single_message(message)
    uid = message.attr['UID']
    envelope = message.attr['ENVELOPE'] 
    
    # Process message metadata without loading full content
    MessageProcessor.queue_for_analysis(uid, envelope)
  end
end

Memory profiling identifies memory usage patterns and potential leaks in long-running IMAP applications. Ruby's ObjectSpace provides tools for tracking object allocation and memory consumption.

require 'objspace'

class MemoryProfiledIMAPClient
  def initialize(server, port, username, password)
    @imap = Net::IMAP.new(server, port, ssl: true)
    @imap.login(username, password)
  end
  
  def fetch_with_memory_tracking(range, attributes)
    # Capture memory state before operation
    ObjectSpace.garbage_collect
    memory_before = memory_usage
    objects_before = ObjectSpace.count_objects
    
    result = @imap.fetch(range, attributes)
    
    # Measure memory after operation
    memory_after = memory_usage  
    objects_after = ObjectSpace.count_objects
    
    memory_delta = memory_after - memory_before
    object_delta = objects_after[:TOTAL] - objects_before[:TOTAL]
    
    puts "Memory usage: #{memory_delta} bytes"
    puts "Objects created: #{object_delta}"
    puts "Result size: #{result.size} messages"
    
    # Analyze object types created
    new_strings = objects_after[:T_STRING] - objects_before[:T_STRING]
    new_arrays = objects_after[:T_ARRAY] - objects_before[:T_ARRAY]
    puts "New strings: #{new_strings}, New arrays: #{new_arrays}"
    
    result
  end
  
  private
  
  def memory_usage
    # Get current process memory usage (Linux/macOS)
    `ps -o rss= -p #{Process.pid}`.to_i * 1024
  rescue
    0  # Fallback if ps command unavailable
  end
end

# Example usage with memory monitoring
profiled_client = MemoryProfiledIMAPClient.new('imap.example.com', 993, 'user', 'pass')
profiled_client.fetch_with_memory_tracking(1..100, ['ENVELOPE', 'FLAGS'])

Caching frequently accessed data reduces server requests and improves response times. Cache folder lists, message counts, and recently accessed message metadata in memory or external cache stores.

require 'digest'

class CachedIMAPClient  
  def initialize(imap, cache_ttl: 300)
    @imap = imap
    @cache = {}
    @cache_ttl = cache_ttl
  end
  
  def cached_folder_list
    cache_key = 'folder_list'
    
    if cache_valid?(cache_key)
      puts "Cache hit for folder list"
      return @cache[cache_key][:data]
    end
    
    puts "Cache miss for folder list - fetching from server"
    folders = @imap.list('', '*')
    
    @cache[cache_key] = {
      data: folders,
      timestamp: Time.now
    }
    
    folders
  end
  
  def cached_message_fetch(message_ids, attributes)
    cache_key = generate_cache_key(message_ids, attributes)
    
    if cache_valid?(cache_key)
      puts "Cache hit for #{message_ids.size} messages"  
      return @cache[cache_key][:data]
    end
    
    puts "Cache miss - fetching #{message_ids.size} messages from server"
    messages = @imap.fetch(message_ids, attributes)
    
    @cache[cache_key] = {
      data: messages,
      timestamp: Time.now  
    }
    
    messages
  end
  
  def cache_stats
    total_entries = @cache.size
    expired_entries = @cache.count { |_, entry| cache_expired?(entry) }
    
    puts "Cache entries: #{total_entries}"
    puts "Expired entries: #{expired_entries}"
    puts "Hit ratio: #{@hit_ratio || 'No data'}"
  end
  
  private
  
  def cache_valid?(key)
    @cache.key?(key) && !cache_expired?(@cache[key])
  end
  
  def cache_expired?(entry)
    Time.now - entry[:timestamp] > @cache_ttl
  end
  
  def generate_cache_key(message_ids, attributes)
    content = "#{message_ids.sort.join(',')}_#{attributes.sort.join(',')}"
    Digest::SHA256.hexdigest(content)[0, 16]
  end
end

Reference

Connection Methods

Method Parameters Returns Description
Net::IMAP.new(host, port, ssl) host (String), port (Integer), ssl (Boolean/Hash) Net::IMAP Creates new IMAP connection
#starttls(options) options (Hash) Net::IMAP::TaggedResponse Starts TLS encryption
#login(user, password) user (String), password (String) Net::IMAP::TaggedResponse Authenticates with username/password
#authenticate(auth_type, *args) auth_type (String), *args (Array) Net::IMAP::TaggedResponse Authenticates using specified mechanism
#logout None Net::IMAP::TaggedResponse Closes connection and logs out
#disconnect None nil Forcibly closes connection

Mailbox Operations

Method Parameters Returns Description
#list(refname, mailbox) refname (String), mailbox (String) Array<Net::IMAP::MailboxList> Lists available mailboxes
#select(mailbox) mailbox (String) Hash Selects mailbox and returns status
#examine(mailbox) mailbox (String) Hash Selects mailbox read-only
#create(mailbox) mailbox (String) Net::IMAP::TaggedResponse Creates new mailbox
#delete(mailbox) mailbox (String) Net::IMAP::TaggedResponse Deletes mailbox
#rename(old_name, new_name) old_name (String), new_name (String) Net::IMAP::TaggedResponse Renames mailbox
#status(mailbox, attr) mailbox (String), attr (Array) Hash Gets mailbox status information

Message Retrieval

Method Parameters Returns Description
#fetch(set, attr) set (Integer/Range/Array), attr (String/Array) Array<Net::IMAP::FetchData> Retrieves message data
#uid_fetch(set, attr) set (Integer/Range/Array), attr (String/Array) Array<Net::IMAP::FetchData> Retrieves messages by UID
#search(keys, charset) keys (Array), charset (String) Array<Integer> Searches for messages
#uid_search(keys, charset) keys (Array), charset (String) Array<Integer> Searches returning UIDs
#sort(sort_keys, search_keys, charset) sort_keys (Array), search_keys (Array), charset (String) Array<Integer> Sorts and searches messages

Message Management

Method Parameters Returns Description
#store(set, attr, flags) set (Integer/Range/Array), attr (String), flags (Array) Array<Net::IMAP::FetchData> Modifies message flags
#uid_store(set, attr, flags) set (Integer/Range/Array), attr (String), flags (Array) Array<Net::IMAP::FetchData> Modifies flags by UID
#copy(set, mailbox) set (Integer/Range/Array), mailbox (String) Net::IMAP::TaggedResponse Copies messages to mailbox
#uid_copy(set, mailbox) set (Integer/Range/Array), mailbox (String) Net::IMAP::TaggedResponse Copies messages by UID
#move(set, mailbox) set (Integer/Range/Array), mailbox (String) Net::IMAP::TaggedResponse Moves messages to mailbox
#expunge None Array<Integer> Permanently deletes flagged messages

Fetch Attributes

Attribute Type Description
RFC822 String Complete message including headers and body
RFC822.HEADER String Message headers only
RFC822.TEXT String Message body without headers
RFC822.SIZE Integer Message size in bytes
ENVELOPE Net::IMAP::Envelope Parsed message envelope
FLAGS Array Message flags
INTERNALDATE String Server internal date
UID Integer Unique identifier
BODYSTRUCTURE Net::IMAP::BodyTypeMultipart/Basic MIME structure
BODY[HEADER] String Message headers
BODY[TEXT] String Message body text

Search Criteria

Criteria Parameters Description
ALL None All messages in mailbox
ANSWERED None Messages with \Answered flag
DELETED None Messages with \Deleted flag
FLAGGED None Messages with \Flagged flag
NEW None Messages with \Recent flag but not \Seen
OLD None Messages without \Recent flag
RECENT None Messages with \Recent flag
SEEN None Messages with \Seen flag
UNANSWERED None Messages without \Answered flag
UNDELETED None Messages without \Deleted flag
UNFLAGGED None Messages without \Flagged flag
UNSEEN None Messages without \Seen flag
FROM String Messages from specified sender
TO String Messages to specified recipient
CC String Messages with specified CC recipient
BCC String Messages with specified BCC recipient
SUBJECT String Messages with specified subject text
BODY String Messages containing specified body text
TEXT String Messages containing text in headers or body
SINCE Date Messages since specified date
BEFORE Date Messages before specified date
ON Date Messages sent on specified date
LARGER Integer Messages larger than specified size
SMALLER Integer Messages smaller than specified size

Exception Classes

Exception Inherits From Description
Net::IMAP::Error StandardError Base IMAP error class
Net::IMAP::DataFormatError Error Invalid data format received
Net::IMAP::ResponseParseError Error Cannot parse server response
Net::IMAP::ResponseError Error Server returned error response
Net::IMAP::NoResponseError ResponseError Server returned NO response
Net::IMAP::BadResponseError ResponseError Server returned BAD response
Net::IMAP::ByeResponseError ResponseError Server sent BYE response
Net::IMAP::FlagCountError Error Too many flags specified

Connection Options

Option Type Default Description
:ssl Boolean/Hash false Enable SSL/TLS encryption
:ca_file String nil Path to CA certificate file
:ca_path String nil Path to CA certificate directory
:verify_mode Integer VERIFY_PEER SSL certificate verification mode
:cert String nil Client certificate
:key String nil Client private key
:timeout Integer nil Network operation timeout in seconds

Status Attributes

Attribute Type Description
MESSAGES Integer Total number of messages
RECENT Integer Number of recent messages
UIDNEXT Integer Next UID value
UIDVALIDITY Integer UID validity value
UNSEEN Integer Number of unseen messages