ImapGuard

Gem Version Build Status Code Climate Inline docs

A guard for your IMAP mailboxes.

ImapGuard connects to your IMAP server and processes your emails. You can finely pick them thanks to advanced search queries and Ruby blocks. Then you can move or delete them in batch.

Of course, there is a dry-run mode (i.e. read-only) available to double check what it would do.

It can be used by a disposable script to clean things up or with a cron job to keep them tidy.

Installation

$ gem install imap_guard

Usage

Read below for detailed explanations. If you prefer a quick overview, you can take a look at this example.

Example initialization:

require 'imap_guard'

SETTINGS = {
  host: 'mail.google.com',
  port: 993,
  username: 'login',
  password: 'pass',
  read_only: true # don't perform any modification aka dry-run mode
}

guard = ImapGuard::Guard.new SETTINGS
guard. # authenticate the user
guard.select 'INBOX.ops' # select the mailbox

IMAP search query syntax can be a bit tricky. ImapGuard::Query can help you to build queries with a simple Ruby DSL:

base_query = ImapGuard::Query.new.unflagged.unanswered.seen.freeze
query = base_query.dup.before(7).subject("abc").from("root")
p query #=> ["UNFLAGGED", "UNANSWERED", "SEEN", "BEFORE", "13-Mar-2013", "SUBJECT", "abc", "FROM", "root"]
guard.delete query # will delete every emails which match this query

Unfortunately, IMAP search queries are limited too. For instance, the pattern passed to subject and from is a mere string. IMAP doesn't allow advanced filtering such as regexp matching.

To do so, you can pass an optional block to delete. The yielded object is a Mail instance of the current mail providing many methods. However, wrapping the mail into a nice Mail object is slow and you should avoid to use it if you can.

guard.delete base_query.dup.before(7).subject("Logwatch for ") do |mail|
  mail.subject =~ /\ALogwatch for \w \(Linux\)\Z/ and \
  mail.multipart? and \
  mail.parts.length == 2
end

You can always forge your own raw IMAP search queries (the RFC can help in that case):

query = 'SEEN SUBJECT "ALERT" FROM "root"'
guard.delete query do |mail|
  mail.body == "ALERT"
end

There is a move method as well:

guard.move query, 'destination_folder' do |mail|
  # and it can take a filter block like `delete`
end

Finally, this should be handled automatically but you can explicitly expunge pending emails and close the connection:

guard.expunge # effectively delete emails marked as deleted
guard.close # expunge then close the connection

Advanced features

Mailbox list

You can list all mailboxes:

p guard.list

Selected mailbox

You can output the currently selected mailbox:

p guard.mailbox # nil if none has been selected

Debug block

You can pass a block which will be yielded for each matched email:

# Print out the subject for each email
guard.debug = ->(mail) { print "#{mail.subject}: " }

You can think of it as Ruby's Object#tap method. Note this is slow since it needs to fetch the whole email to return a Mail object.

Contributing

Bug reports and patches are most welcome.

License

MIT