gmail_oauth2 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/gmail_oauth.rb +21 -0
- data/lib/gmail_oauth/attachment.rb +20 -0
- data/lib/gmail_oauth/client.rb +63 -0
- data/lib/gmail_oauth/gmail_imap_extensions.rb +57 -0
- data/lib/gmail_oauth/message.rb +36 -0
- data/lib/gmail_oauth/version.rb +3 -0
- metadata +233 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4bc71816a3aeaf18aa75b53396b71029ac1466ee
|
4
|
+
data.tar.gz: bb7a8933489d5cb03fe5cf94498fbf145b164061
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d16cfc270f1eb82ba4585ddbec94e98c9dadae7c38646527f8245d89787ef7a0d255edca81263a63570298939ec2087fd1b89754917e54a2d1d172b1d575e738
|
7
|
+
data.tar.gz: 4fc0636d9314c11b5e7f3a269631964b89bed2c551c838ae1d6770a6508dfd8fc61d1ba8a50917d500a80cd05514199e97c12f0c038b047c8277faad172cb46a
|
data/lib/gmail_oauth.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'net/imap'
|
2
|
+
require 'mail'
|
3
|
+
require 'gmail_xoauth'
|
4
|
+
require 'mimemagic'
|
5
|
+
require 'mimemagic/overlay'
|
6
|
+
require 'gmail_oauth/version'
|
7
|
+
require 'gmail_oauth/gmail_imap_extensions'
|
8
|
+
require 'gmail_oauth/client'
|
9
|
+
require 'gmail_oauth/message'
|
10
|
+
require 'gmail_oauth/attachment'
|
11
|
+
|
12
|
+
module GmailOauth
|
13
|
+
|
14
|
+
def self.authenticate(email, access_token)
|
15
|
+
imap_client = Net::IMAP.new('imap.gmail.com', 993, usessl=true, certs=nil, verify=false)
|
16
|
+
client = Client.new(imap_client, email, access_token)
|
17
|
+
client.connect
|
18
|
+
client
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class GmailOauth::Attachment
|
2
|
+
|
3
|
+
attr_reader :content, :mime_type, :file_name
|
4
|
+
|
5
|
+
def initialize(attachment)
|
6
|
+
@file_name = attachment.filename
|
7
|
+
@content = attachment.body.decoded
|
8
|
+
@mime_type = get_mime_type
|
9
|
+
end
|
10
|
+
|
11
|
+
def file_extension
|
12
|
+
@file_name.split(".").last
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_mime_type
|
16
|
+
if mime_obj = MimeMagic.by_magic(content[0..10000])
|
17
|
+
mime_obj.type
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class GmailOauth::Client
|
2
|
+
|
3
|
+
attr_reader :imap, :email, :access_token
|
4
|
+
|
5
|
+
# Initialize a new imap session and authenticate using the oauth2 access
|
6
|
+
# token.
|
7
|
+
def initialize(imap_client, email_param, access_token_param)
|
8
|
+
@imap = imap_client
|
9
|
+
@email = email_param
|
10
|
+
@access_token = access_token_param
|
11
|
+
GmailOauth::GmailImapExtensions.patch_net_imap_response_parser imap.
|
12
|
+
instance_variable_get("@parser").singleton_class
|
13
|
+
end
|
14
|
+
|
15
|
+
def connect
|
16
|
+
imap.authenticate('XOAUTH2', email, access_token)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Select appropriate mailbox. Ex: 'INBOX', '[Gmail]/All Mail',
|
20
|
+
# '[Gmail]/Drafts', '[Gmail]/Spam', '[Gmail]/Trash', '[Gmail]/Starred'
|
21
|
+
def select_mailbox(mailbox='INBOX')
|
22
|
+
imap.select(mailbox)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_uids(last_seen_uid=0)
|
26
|
+
imap.uid_search(search_param(last_seen_uid))
|
27
|
+
end
|
28
|
+
|
29
|
+
def fetch_emails(uids, &block)
|
30
|
+
messages = Array.new
|
31
|
+
uids.each_slice(10) do |grp|
|
32
|
+
connect if imap.disconnected?
|
33
|
+
emails = imap.uid_fetch(grp.compact, 'RFC822')
|
34
|
+
emails.each do |email|
|
35
|
+
message = GmailOauth::Message.new(Mail.
|
36
|
+
read_from_string(email.attr['RFC822']), email.attr['UID'])
|
37
|
+
yield(message) if block_given?
|
38
|
+
messages << message
|
39
|
+
end
|
40
|
+
end
|
41
|
+
messages
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch_threaded_emails(thread_id, &block)
|
45
|
+
email_uids = imap.uid_search("X-GM-THRID #{thread_id}")
|
46
|
+
messages = fetch_emails(email_uids)
|
47
|
+
yield(thread_id, messages) if block_given?
|
48
|
+
messages
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_thread_ids(uids)
|
52
|
+
thread_responses = imap.uid_fetch(uids, '(X-GM-THRID)')
|
53
|
+
thread_responses.map { |t| t.attr['X-GM-THRID'] }
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def search_param(last_seen_uid)
|
59
|
+
return "ALL" if last_seen_uid == 0
|
60
|
+
next_uid = last_seen_uid.to_i + 1
|
61
|
+
return "UID #{next_uid}:*"
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Net::IMAP raises an exception when fetching attributes related to
|
2
|
+
# Gmail IMAP extended attributes.
|
3
|
+
# Based on the patch by https://github.com/OXOS
|
4
|
+
# https://github.com/OXOS/gmail-oauth-thread-stats/blob/master/gmail_imap_extensions_compatibility.rb
|
5
|
+
module GmailOauth
|
6
|
+
module GmailImapExtensions
|
7
|
+
|
8
|
+
def self.patch_net_imap_response_parser(klass = Net::IMAP::ResponseParser)
|
9
|
+
klass.class_eval do
|
10
|
+
def msg_att(n)
|
11
|
+
match(Net::IMAP::ResponseParser::T_LPAR)
|
12
|
+
attr = {}
|
13
|
+
while true
|
14
|
+
token = lookahead
|
15
|
+
case token.symbol
|
16
|
+
when Net::IMAP::ResponseParser::T_RPAR
|
17
|
+
shift_token
|
18
|
+
break
|
19
|
+
when Net::IMAP::ResponseParser::T_SPACE
|
20
|
+
shift_token
|
21
|
+
token = lookahead
|
22
|
+
end
|
23
|
+
case token.value
|
24
|
+
when /\A(?:ENVELOPE)\z/ni
|
25
|
+
name, val = envelope_data
|
26
|
+
when /\A(?:FLAGS)\z/ni
|
27
|
+
name, val = flags_data
|
28
|
+
when /\A(?:INTERNALDATE)\z/ni
|
29
|
+
name, val = internaldate_data
|
30
|
+
when /\A(?:RFC822(?:\.HEADER|\.TEXT)?)\z/ni
|
31
|
+
name, val = rfc822_text
|
32
|
+
when /\A(?:RFC822\.SIZE)\z/ni
|
33
|
+
name, val = rfc822_size
|
34
|
+
when /\A(?:BODY(?:STRUCTURE)?)\z/ni
|
35
|
+
name, val = body_data
|
36
|
+
when /\A(?:UID)\z/ni
|
37
|
+
name, val = uid_data
|
38
|
+
|
39
|
+
# Gmail extension additions.
|
40
|
+
# Cargo-Cult code warning: # I have no idea why the regexp - just copying a pattern
|
41
|
+
when /\A(?:X-GM-LABELS)\z/ni
|
42
|
+
name, val = flags_data
|
43
|
+
when /\A(?:X-GM-MSGID)\z/ni
|
44
|
+
name, val = uid_data
|
45
|
+
when /\A(?:X-GM-THRID)\z/ni
|
46
|
+
name, val = uid_data
|
47
|
+
else
|
48
|
+
parse_error("unknown attribute `%s'", token.value)
|
49
|
+
end
|
50
|
+
attr[name] = val
|
51
|
+
end
|
52
|
+
return attr
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class GmailOauth::Message
|
2
|
+
|
3
|
+
attr_reader :uid, :email, :subject, :to, :from, :cc, :received_on
|
4
|
+
|
5
|
+
def initialize(email, uid = 0)
|
6
|
+
@email = email
|
7
|
+
@uid = uid
|
8
|
+
@to = email.to
|
9
|
+
@from = email.from
|
10
|
+
@subject = email.subject
|
11
|
+
@cc = email.cc
|
12
|
+
@received_on = email.date
|
13
|
+
end
|
14
|
+
|
15
|
+
["text", "html"].each do |format|
|
16
|
+
define_method("body_#{format}") do
|
17
|
+
return nil unless email.send("#{format}_part")
|
18
|
+
body = email.send("#{format}_part").body.raw_source
|
19
|
+
decoded_text = Mail::Encodings.decode_encode(body, 'UTF-8')
|
20
|
+
return Mail::Encodings.value_decode(decoded_text)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def has_attachments?
|
25
|
+
!email.attachments.blank?
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_attachments
|
29
|
+
return [] unless has_attachments?
|
30
|
+
attachments = []
|
31
|
+
email.attachments.each do |attach|
|
32
|
+
attachments << GmailOauth::Attachment.new(attach)
|
33
|
+
end
|
34
|
+
attachments
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gmail_oauth2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Karthik Mallavarapu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mail
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.6'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.6.3
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.6'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.6.3
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: gmail_xoauth
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.4'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.4.1
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.4'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.4.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: mimemagic
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.3'
|
60
|
+
type: :runtime
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0.3'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: bundler
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '1.6'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '1.6'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rake
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: coveralls
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.8'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0.8'
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: rubocop
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0.34'
|
116
|
+
type: :development
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0.34'
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: gem-release
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0.7'
|
130
|
+
type: :development
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0.7'
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: pry
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0.10'
|
144
|
+
type: :development
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - "~>"
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0.10'
|
151
|
+
- !ruby/object:Gem::Dependency
|
152
|
+
name: minitest
|
153
|
+
requirement: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - "~>"
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '5.8'
|
158
|
+
type: :development
|
159
|
+
prerelease: false
|
160
|
+
version_requirements: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - "~>"
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '5.8'
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: minitest-reporters
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - "~>"
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '1.1'
|
172
|
+
type: :development
|
173
|
+
prerelease: false
|
174
|
+
version_requirements: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - "~>"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '1.1'
|
179
|
+
- !ruby/object:Gem::Dependency
|
180
|
+
name: faker
|
181
|
+
requirement: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - "~>"
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '1.5'
|
186
|
+
type: :development
|
187
|
+
prerelease: false
|
188
|
+
version_requirements: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - "~>"
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '1.5'
|
193
|
+
description: "The library uses gmail_xoauth, mail and monkey-patched\n ruby
|
194
|
+
imap library to support gmail oauth extensions \n such
|
195
|
+
as X-GM-THRID. Supports fetching uids, emails, \n threaded
|
196
|
+
emails, attachments and much more."
|
197
|
+
email:
|
198
|
+
- karthik.mallavarapu@gmail.com
|
199
|
+
executables: []
|
200
|
+
extensions: []
|
201
|
+
extra_rdoc_files: []
|
202
|
+
files:
|
203
|
+
- lib/gmail_oauth.rb
|
204
|
+
- lib/gmail_oauth/attachment.rb
|
205
|
+
- lib/gmail_oauth/client.rb
|
206
|
+
- lib/gmail_oauth/gmail_imap_extensions.rb
|
207
|
+
- lib/gmail_oauth/message.rb
|
208
|
+
- lib/gmail_oauth/version.rb
|
209
|
+
homepage: https://github.com/karthik-mallavarapu/gmail_oauth
|
210
|
+
licenses:
|
211
|
+
- MIT
|
212
|
+
metadata: {}
|
213
|
+
post_install_message:
|
214
|
+
rdoc_options: []
|
215
|
+
require_paths:
|
216
|
+
- lib
|
217
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
218
|
+
requirements:
|
219
|
+
- - ">="
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
222
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
223
|
+
requirements:
|
224
|
+
- - ">="
|
225
|
+
- !ruby/object:Gem::Version
|
226
|
+
version: '0'
|
227
|
+
requirements: []
|
228
|
+
rubyforge_project:
|
229
|
+
rubygems_version: 2.4.5
|
230
|
+
signing_key:
|
231
|
+
specification_version: 4
|
232
|
+
summary: A ruby gem for accessing gmail using oauth2 tokens.
|
233
|
+
test_files: []
|