nu7hatch/gmail

Could this be used for non GMail accounts?

jmuheim opened this issue · 8 comments

Hello!

I have to write an email importer that connects to an IMAP account, then gets all unread email, create a new object out of every email, and then sets the emails to "read".

I tried the Mail gem, which seems nice, but it hasn't built-in support for flagging emails as read. So I stumbled over your GMail gem, which seems to use a lot of functionality of the Mail gem.

I'm a bit unsure now whether I should try to add the missed functionality to Mail myself, or whether your GMail gem could be what I need. So - is it possible to use it for other servers than GMail? And why do you think the Mail gem doesn't support so many features that your GMail gem does? Would it be hard to implement those features?

Thank you for your opinion,
Josh

As best I understand, IMAP the protocol has a SEEN flag but not an UNREAD flag. Google created this for their instance of email, which is why the gmail gem is able to do it, while the mail gem can not.

If you want to sort by unread and do many other email related things more easily, checkout contextio.com's API.

Thanks for your reply, Johnny. I'm still not really sure about how non-Gmail-servers mark their emails as read, as setting the "Seen" flag doesn't seem to do the whole trick (e.g. on AOL mail the mails still are displayed as unread after setting the Seen flag for them).

Anyways, for our application's very basic needs (we simply want to import mails and then set the Read flag) I wrote a monkey patch for the GMail gem.

require 'gmail'
module Gmail
  module Client
    # Monkey patch of the [GMail gem](https://github.com/nu7hatch/gmail) which allows to connect to email servers other than GMail (which is still default).
    #
    # @example
    #   Gmail.connect!('inquisiv@gmail.com', '???') # Connects to GMail
    # @example
    #   Gmail.connect!('inquisiv@aol.com', '???', host: 'imap.aol.com')
    # @example
    #   Gmail.connect!('john.doe@example.com', 'password', host: 'mail.example.com', port: 123)  # Port defaults to 993
    #
    # @note ONLY **RECEIVING** EMAILS FROM **IMAP** WAS TESTED SO FAR! NO GUARANTEE IS GIVEN THAT **ANYTHING ELSE** WILL WORK!
    #
    #   Also, I have no idea what happens if somebody tries to do GMail-specific actions on non-GMail servers.
    #
    # @note Context.IO may be an option if we need sophisticated mail functions: http://context.io/
    #
    # @todo Add `ssl` option!
    # @author Joshua Muheim
    class Base
      alias_method :old_initialize, :initialize

      # @!attribute [r] custom_imap_host
      #   @return [String]

      # @!attribute [r] custom_imap_port
      #   @return [Integer]

      # @param [String] username
      # @param [Hash] options
      # @option options [String] :host The IMAP host to connect to
      # @option options [Integer] :port The port to connect to
      def initialize(username, options = {})
        @custom_imap_host = options[:host].nil? ? GMAIL_IMAP_HOST : options[:host]
        @custom_imap_port = options[:port].nil? ? GMAIL_IMAP_PORT : options[:port]
        old_initialize(username, options)
      end

      # Monkey patched so it connects to `@custom_imap_host` and `@custom_imap_port` instead of `GMAIL_IMAP_HOST` and `GMAIL_IMAP_PORT`.
      def connect(raise_errors=false)
        @imap = Net::IMAP.new(@custom_imap_host, @custom_imap_port, true, nil, false)
      rescue SocketError
        raise_errors and raise ConnectionError, "Couldn't establish connection with GMail IMAP service"
      end
    end
  end
end

This works quite nicely for our purposes, but I have no idea how "valid" all this stuff really is, and in future we will have to exploit the mail functions to a higher level and therefore investigate our other possibilities anyway, but for the time being, this works.

By the way, we used the GMail gem because it allows to set the Read flag for single emails at any position of our code. This is important for us because we try to import every single mail into our system, and only when the import is successful, the Read flag should be set.

@sientia-jmu I'm just facing the exact same issue, did you mange to make it work with other email clients like yahoo for example ? any help would be highly appreciated here

I made it work with the monkey patch I posted above for AOL and my own webserver (a hosted vserver on railsplayground.net), so I guess it will work with Yahoo, too. Just check it out, and you will know in a few minutes.

      client = Gmail.connect!(
        address,
        password,
        host: host,
        port: port
      )

      client.inbox.emails(:unread).each do |email|
        puts Mail::Encodings.value_decode(email.subject)
        # do some stuff
        email.read!
      end

Thanks for your welling to help here @sientia-jmu , I tried it with yahoo and was getting the following error
`connect': SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: unknown protocol (OpenSSL::SSL::SSLError)

I used your monkey patch and then :
gmail = Gmail.new('yahoo-id', 'password', host: 'imap.mail.yahoo.com', port: 993)

Any help would be highly appreciated .

At the moment, it always connects using SSL. Maybe this is raising the error. Try to rewrite my code so SSL can be turned off (this should be really simple). I will take a look at it myself the next week.

Happy weekend! :)

I'm going to close this issue since, for the time being, accessing other IMAP servers is not within the scope of this gem.

This issue was moved to gmailgem/gmail#67