Skip to content

Instantly share code, notes, and snippets.

@airblade
Created October 27, 2022 14:53
Show Gist options
  • Select an option

  • Save airblade/aa4c7738089be459db1134f512e548fd to your computer and use it in GitHub Desktop.

Select an option

Save airblade/aa4c7738089be459db1134f512e548fd to your computer and use it in GitHub Desktop.

Revisions

  1. airblade created this gist Oct 27, 2022.
    67 changes: 67 additions & 0 deletions imap_with_move.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    require 'mail'
    require 'net/imap'

    # Add IMAP move to Mail.
    module Mail

    # In addition to the options supported by the IMAP class:
    #
    # move: mailbox to which to move emails. This makes the :delete_after_find flag irrelevant.
    #
    # https://github.com/mikel/mail/blob/f5801f2a1437a2625c929bf129e995f7ff829a5c/lib/mail/network/retriever_methods/imap.rb
    class IMAPWithMove < IMAP
    def find(options=nil, &block)
    options = validate_options(options)

    start do |imap|
    options[:read_only] ? imap.examine(options[:mailbox]) : imap.select(options[:mailbox])
    uids = imap.uid_search(options[:keys], options[:search_charset])
    uids.reverse! if options[:what].to_sym == :last
    uids = uids.first(options[:count]) if options[:count].is_a?(Integer)
    uids.reverse! if (options[:what].to_sym == :last && options[:order].to_sym == :asc) ||
    (options[:what].to_sym != :last && options[:order].to_sym == :desc)

    if block_given?
    uids.each do |uid|
    uid = options[:uid].to_i unless options[:uid].nil?
    fetchdata = imap.uid_fetch(uid, ['RFC822', 'FLAGS'])[0]
    new_message = Mail.new(fetchdata.attr['RFC822'])
    new_message.mark_for_delete = true if options[:delete_after_find]

    if block.arity == 4
    yield new_message, imap, uid, fetchdata.attr['FLAGS']
    elsif block.arity == 3
    yield new_message, imap, uid
    else
    yield new_message
    end

    if options[:move]
    imap.uid_move(uid, options[:move])
    else
    imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find] && new_message.is_marked_for_delete?
    end
    break unless options[:uid].nil?
    end
    imap.expunge if options[:delete_after_find]
    else
    emails = []
    uids.each do |uid|
    uid = options[:uid].to_i unless options[:uid].nil?
    fetchdata = imap.uid_fetch(uid, ['RFC822'])[0]
    emails << Mail.new(fetchdata.attr['RFC822'])
    if options[:move]
    imap.uid_move(uid, options[:move])
    else
    imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find]
    end
    break unless options[:uid].nil?
    end
    imap.expunge if options[:delete_after_find]
    emails.size == 1 && options[:count] == 1 ? emails.first : emails
    end
    end
    end
    end

    end