gmail-afurmanov 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ # -*- ruby -*-
2
+
3
+ $:.unshift(File.expand_path('../lib', __FILE__))
4
+ require 'gmail/version'
5
+
6
+ begin
7
+ Ore::Specification.new do |gemspec|
8
+ gemspec.version = Gmail.version
9
+ end
10
+ rescue NameError
11
+ begin
12
+ require 'ore/specification'
13
+ retry
14
+ rescue LoadError
15
+ STDERR.puts "The '#{__FILE__}' file requires Ore."
16
+ STDERR.puts "Run `gem install ore-core` to install Ore."
17
+ end
18
+ end
@@ -0,0 +1,65 @@
1
+ require 'net/imap'
2
+ require 'net/smtp'
3
+ require 'mail'
4
+ require 'date'
5
+ require 'time'
6
+
7
+ if RUBY_VERSION < "1.8.7"
8
+ require "smtp_tls"
9
+ end
10
+
11
+ class Object
12
+ def to_imap_date
13
+ Date.parse(to_s).strftime("%d-%B-%Y")
14
+ end
15
+ end
16
+
17
+ module Gmail
18
+ autoload :Version, "gmail/version"
19
+ autoload :Client, "gmail/client"
20
+ autoload :Labels, "gmail/labels"
21
+ autoload :Mailbox, "gmail/mailbox"
22
+ autoload :Message, "gmail/message"
23
+
24
+ class << self
25
+ # Creates new Gmail connection using given authorization options.
26
+ #
27
+ # ==== Examples
28
+ #
29
+ # Gmail.new(:plain, "foo@gmail.com", "password")
30
+ # Gmail.new(:xoauth, "foo@gmail.com",
31
+ # :consumer_key => "",
32
+ # :consumer_secret => "",
33
+ # :token => "",
34
+ # :secret => "")
35
+ #
36
+ # To use plain authentication mehod you can also call:
37
+ #
38
+ # Gmail.new("foo@gmail.com", "password")
39
+ #
40
+ # You can also use block-style call:
41
+ #
42
+ # Gmail.new("foo@gmail.com", "password") do |client|
43
+ # # ...
44
+ # end
45
+ #
46
+
47
+ ['', '!'].each { |kind|
48
+ define_method("new#{kind}") do |*args, &block| # def new(*args, &block)
49
+ args.unshift(:plain) unless args.first.is_a?(Symbol) # args.unshift(:plain) unless args.first.is_a?(Symbol)
50
+ client = Gmail::Client.new(*args) # client = Gmail::Client.new(*args)
51
+ client.send("connect#{kind}") and client.send("login#{kind}") # client.connect and client.login
52
+ #
53
+ if block_given? # if block_given?
54
+ yield client # yield client
55
+ client.logout # client.logout
56
+ end # end
57
+ #
58
+ client # client
59
+ end # end
60
+ }
61
+
62
+ alias :connect :new
63
+ alias :connect! :new!
64
+ end # << self
65
+ end # Gmail
@@ -0,0 +1,29 @@
1
+ module Gmail
2
+ module Client
3
+ # Raised when connection with GMail IMAP service couldn't be established.
4
+ class ConnectionError < SocketError; end
5
+ # Raised when given username or password are invalid.
6
+ class AuthorizationError < Net::IMAP::NoResponseError; end
7
+ # Raised when delivered email is invalid.
8
+ class DeliveryError < ArgumentError; end
9
+ # Raised when given client is not registered
10
+ class UnknownClient < ArgumentError; end
11
+
12
+ def self.register(name, klass)
13
+ @clients ||= {}
14
+ @clients[name] = klass
15
+ end
16
+
17
+ def self.new(name, *args)
18
+ if client = @clients[name]
19
+ client.new(*args)
20
+ else
21
+ raise UnknownClient, "No such client: #{name}"
22
+ end
23
+ end
24
+
25
+ require 'gmail/client/base'
26
+ require 'gmail/client/plain'
27
+ require 'gmail/client/xoauth'
28
+ end # Client
29
+ end # Gmail
@@ -0,0 +1,223 @@
1
+ #require 'thread'
2
+
3
+ module Gmail
4
+ module Client
5
+ class Base
6
+ # GMail IMAP defaults
7
+ GMAIL_IMAP_HOST = 'imap.gmail.com'
8
+ GMAIL_IMAP_PORT = 993
9
+
10
+ # GMail SMTP defaults
11
+ GMAIL_SMTP_HOST = "smtp.gmail.com"
12
+ GMAIL_SMTP_PORT = 587
13
+
14
+ attr_reader :username
15
+ attr_reader :options
16
+
17
+ def initialize(username, options={})
18
+ defaults = {}
19
+ @username = fill_username(username)
20
+ @options = defaults.merge(options)
21
+ # @mailbox_mutex = Mutex.new
22
+ end
23
+
24
+ # Connect to gmail service.
25
+ def connect(raise_errors=false)
26
+ @imap = Net::IMAP.new(GMAIL_IMAP_HOST, GMAIL_IMAP_PORT, true, nil, false)
27
+ rescue SocketError
28
+ raise_errors and raise ConnectionError, "Couldn't establish connection with GMail IMAP service"
29
+ end
30
+
31
+ # This version of connect will raise error on failure...
32
+ def connect!
33
+ connect(true)
34
+ end
35
+
36
+ # Return current connection. Log in automaticaly to specified account if
37
+ # it is necessary.
38
+ def connection
39
+ login and at_exit { logout } unless logged_in?
40
+ @imap
41
+ end
42
+ alias :conn :connection
43
+
44
+ # Login to specified account.
45
+ def login(*args)
46
+ raise NotImplementedError, "The `#{self.class.name}#login` method is not implemented."
47
+ end
48
+ alias :sign_in :login
49
+
50
+ # This version of login will raise error on failure...
51
+ def login!
52
+ login(true)
53
+ end
54
+ alias :sign_in! :login!
55
+
56
+ # Returns +true+ when you are logged in to specified account.
57
+ def logged_in?
58
+ !!@logged_in
59
+ end
60
+ alias :signed_in? :logged_in?
61
+
62
+ # Logout from GMail service.
63
+ def logout
64
+ @imap && logged_in? and @imap.logout
65
+ ensure
66
+ @logged_in = false
67
+ end
68
+ alias :sign_out :logout
69
+
70
+ # Return labels object, which helps you with managing your GMail labels.
71
+ # See <tt>Gmail::Labels</tt> for details.
72
+ def labels
73
+ @labels ||= Labels.new(conn)
74
+ end
75
+
76
+ # Compose new e-mail.
77
+ #
78
+ # ==== Examples
79
+ #
80
+ # mail = gmail.compose
81
+ # mail.from "test@gmail.org"
82
+ # mail.to "friend@gmail.com"
83
+ #
84
+ # ... or block style:
85
+ #
86
+ # mail = gmail.compose do
87
+ # from "test@gmail.org"
88
+ # to "friend@gmail.com"
89
+ # subject "Hello!"
90
+ # body "Hello my friend! long time..."
91
+ # end
92
+ #
93
+ # Now you can deliver your mail:
94
+ #
95
+ # gmail.deliver(mail)
96
+ def compose(mail=nil, &block)
97
+ if block_given?
98
+ mail = Mail.new(&block)
99
+ elsif !mail
100
+ mail = Mail.new
101
+ end
102
+
103
+ mail.delivery_method(*smtp_settings)
104
+ mail.from = username unless mail.from
105
+ mail
106
+ end
107
+ alias :message :compose
108
+
109
+ # Compose (optionaly) and send given email.
110
+ #
111
+ # ==== Examples
112
+ #
113
+ # gmail.deliver do
114
+ # to "friend@gmail.com"
115
+ # subject "Hello friend!"
116
+ # body "Hi! How are you?"
117
+ # end
118
+ #
119
+ # ... or with already created message:
120
+ #
121
+ # mail = Mail.new { ... }
122
+ # gmail.deliver(mail)
123
+ #
124
+ # mail = gmail.compose { ... }
125
+ # gmail.deliver(mail)
126
+ def deliver(mail=nil, raise_errors=false, &block)
127
+ mail = compose(mail, &block) if block_given?
128
+ mail.deliver!
129
+ rescue Object => ex
130
+ raise_errors and raise DeliveryError, "Couldn't deliver email: #{ex.to_s}"
131
+ end
132
+
133
+ # This version of deliver will raise error on failure...
134
+ def deliver!(mail=nil, &block)
135
+ deliver(mail, true, &block)
136
+ end
137
+
138
+ # Do something with given mailbox or within it context.
139
+ #
140
+ # ==== Examples
141
+ #
142
+ # mailbox = gmail.mailbox("INBOX")
143
+ # mailbox.emails(:all)
144
+ # mailbox.count(:unread, :before => Time.now-(20*24*3600))
145
+ #
146
+ # ... or block style:
147
+ #
148
+ # gmail.label("Work") do |mailbox|
149
+ # mailbox.emails(:unread)
150
+ # mailbox.count(:all)
151
+ # ...
152
+ # end
153
+ def mailbox(name, &block)
154
+ # @mailbox_mutex.synchronize do
155
+ name = name.to_s
156
+ mailbox = (mailboxes[name] ||= Mailbox.new(self, name))
157
+ switch_to_mailbox(name) if @current_mailbox != name
158
+
159
+ if block_given?
160
+ mailbox_stack << @current_mailbox
161
+ result = block.arity == 1 ? block.call(mailbox) : block.call
162
+ mailbox_stack.pop
163
+ switch_to_mailbox(mailbox_stack.last)
164
+ return result
165
+ end
166
+
167
+ return mailbox
168
+ # end
169
+ end
170
+ alias :in_mailbox :mailbox
171
+ alias :in_label :mailbox
172
+ alias :label :mailbox
173
+
174
+ # Alias for <tt>mailbox("INBOX")</tt>. See <tt>Gmail::Client#mailbox</tt>
175
+ # for details.
176
+ def inbox
177
+ mailbox("INBOX")
178
+ end
179
+
180
+ def mailboxes
181
+ @mailboxes ||= {}
182
+ end
183
+
184
+ def inspect
185
+ "#<Gmail::Client#{'0x%04x' % (object_id << 1)} (#{username}) #{'dis' if !logged_in?}connected>"
186
+ end
187
+
188
+ def fill_username(username)
189
+ username =~ /@/ ? username : "#{username}@gmail.com"
190
+ end
191
+
192
+ def mail_domain
193
+ username.split('@')[0]
194
+ end
195
+
196
+ private
197
+
198
+ def switch_to_mailbox(mailbox)
199
+ if mailbox
200
+ mailbox = Net::IMAP.encode_utf7(mailbox)
201
+ conn.select(mailbox)
202
+ end
203
+ @current_mailbox = mailbox
204
+ end
205
+
206
+ def mailbox_stack
207
+ @mailbox_stack ||= []
208
+ end
209
+
210
+ def smtp_settings
211
+ [:smtp, {
212
+ :address => GMAIL_SMTP_HOST,
213
+ :port => GMAIL_SMTP_PORT,
214
+ :domain => mail_domain,
215
+ :user_name => username,
216
+ :password => password,
217
+ :authentication => 'plain',
218
+ :enable_starttls_auto => true
219
+ }]
220
+ end
221
+ end # Base
222
+ end # Client
223
+ end # Gmail
@@ -0,0 +1,20 @@
1
+ module Gmail
2
+ module Client
3
+ class Plain < Base
4
+ attr_reader :password
5
+
6
+ def initialize(username, password, options={})
7
+ @password = password
8
+ super(username, options)
9
+ end
10
+
11
+ def login(raise_errors=false)
12
+ @imap and @logged_in = (login = @imap.login(username, password)) && login.name == 'OK'
13
+ rescue Net::IMAP::NoResponseError
14
+ raise_errors and raise AuthorizationError, "Couldn't login to given GMail account: #{username}"
15
+ end
16
+ end # Plain
17
+
18
+ register :plain, Plain
19
+ end # Client
20
+ end # Gmail
@@ -0,0 +1,51 @@
1
+ require 'gmail_xoauth'
2
+
3
+ module Gmail
4
+ module Client
5
+ class XOAuth < Base
6
+ attr_reader :token
7
+ attr_reader :secret
8
+ attr_reader :consumer_key
9
+ attr_reader :consumer_secret
10
+
11
+ def initialize(username, options={})
12
+ @token = options.delete(:token)
13
+ @secret = options.delete(:secret)
14
+ @consumer_key = options.delete(:consumer_key)
15
+ @consumer_secret = options.delete(:consumer_secret)
16
+
17
+ super(username, options)
18
+ end
19
+
20
+ def login(raise_errors=false)
21
+ @imap and @logged_in = (login = @imap.authenticate('XOAUTH', username,
22
+ :consumer_key => consumer_key,
23
+ :consumer_secret => consumer_secret,
24
+ :token => token,
25
+ :token_secret => secret
26
+ )) && login.name == 'OK'
27
+ rescue
28
+ raise_errors and raise AuthorizationError, "Couldn't login to given GMail account: #{username}"
29
+ end
30
+
31
+ def smtp_settings
32
+ [:smtp, {
33
+ :address => GMAIL_SMTP_HOST,
34
+ :port => GMAIL_SMTP_PORT,
35
+ :domain => mail_domain,
36
+ :user_name => username,
37
+ :password => {
38
+ :consumer_key => consumer_key,
39
+ :consumer_secret => consumer_secret,
40
+ :token => token,
41
+ :token_secret => secret
42
+ },
43
+ :authentication => :xoauth,
44
+ :enable_starttls_auto => true
45
+ }]
46
+ end
47
+ end # XOAuth
48
+
49
+ register :xoauth, XOAuth
50
+ end # Client
51
+ end # Gmail
@@ -0,0 +1,48 @@
1
+ module Gmail
2
+ class Labels
3
+ include Enumerable
4
+ attr_reader :connection
5
+ alias :conn :connection
6
+
7
+ def initialize(connection)
8
+ @connection = connection
9
+ end
10
+
11
+ # Get list of all defined labels.
12
+ def all
13
+ (conn.list("", "%")+conn.list("[Gmail]/", "%")).inject([]) do |labels,label|
14
+ label[:name].each_line {|l| labels << Net::IMAP.decode_utf7(l) }
15
+ labels
16
+ end
17
+ end
18
+ alias :list :all
19
+ alias :to_a :all
20
+
21
+ def each(*args, &block)
22
+ all.each(*args, &block)
23
+ end
24
+
25
+ # Returns +true+ when given label defined.
26
+ def exists?(label)
27
+ all.include?(label)
28
+ end
29
+ alias :exist? :exists?
30
+
31
+ # Creates given label in your account.
32
+ def create(label)
33
+ !!conn.create(Net::IMAP.encode_utf7(label)) rescue false
34
+ end
35
+ alias :new :create
36
+ alias :add :create
37
+
38
+ # Deletes given label from your account.
39
+ def delete(label)
40
+ !!conn.delete(Net::IMAP.encode_utf7(label)) rescue false
41
+ end
42
+ alias :remove :delete
43
+
44
+ def inspect
45
+ "#<Gmail::Labels#{'0x%04x' % (object_id << 1)}>"
46
+ end
47
+ end # Labels
48
+ end # Gmail