gmailer 0.0.8 → 0.0.9
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.
- data/CHANGES +6 -0
- data/README +35 -57
- data/gmailer.rb +1602 -1383
- metadata +2 -2
data/CHANGES
CHANGED
data/README
CHANGED
|
@@ -5,55 +5,20 @@
|
|
|
5
5
|
== Synopsis
|
|
6
6
|
==== A typical code sequence for fetching gmails
|
|
7
7
|
|
|
8
|
-
gmail = GMailer.new
|
|
9
|
-
gmail.set_login_info(name, pwd)
|
|
10
|
-
if gmail.connect
|
|
11
|
-
gmail.fetch_box(GM_LABEL, "my_label", 0)
|
|
12
|
-
snapshot = gmail.snapshot(GM_LABEL)
|
|
13
|
-
if snapshot
|
|
14
|
-
puts "Total # of conversations of my_label = " + snapshot.box_total.to_s
|
|
15
|
-
end
|
|
16
|
-
gmail.disconnect
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
Or more simpler
|
|
20
|
-
|
|
21
|
-
GMailer.connect(name, pwd) do |gmail|
|
|
22
|
-
snapshot = gmail.fetch_box(GM_LABEL, "my_label", 0)
|
|
23
|
-
if snapshot
|
|
24
|
-
puts "Total # of conversations of my_label = " + snapshot.box_total.to_s
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
Or even
|
|
29
|
-
|
|
30
8
|
GMailer.connect(name, pwd) do |g|
|
|
31
|
-
g.
|
|
32
|
-
puts "Total # of conversations of my_label = " +
|
|
9
|
+
g.messages(:label=>"my_label") {|ml|
|
|
10
|
+
puts "Total # of conversations of my_label = " + ml.total.to_s
|
|
33
11
|
}
|
|
34
12
|
end
|
|
35
13
|
|
|
36
14
|
|
|
37
15
|
=== Sending new gmails with gmailer
|
|
38
16
|
|
|
39
|
-
gmail = GMailer.new
|
|
40
|
-
gmail.set_login_info(name, pwd)
|
|
41
|
-
if gmail.connect
|
|
42
|
-
to = "who@what.com, my_friend@his_company.com, god@heaven.org"
|
|
43
|
-
cc = "foo@bar.com"
|
|
44
|
-
subject = "Hello There!"
|
|
45
|
-
message = "Hi...\n\nBlah blah blah~..."
|
|
46
|
-
attachments = ["./my_pic.jpg", "./my_cv.txt"]
|
|
47
|
-
gmail.send(to, subject, message, cc, '','', '', attachments, false, '')
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
Or shorter
|
|
51
|
-
|
|
52
17
|
GMailer.connect(name, pwd) do |g|
|
|
53
18
|
# 'From' default gmail.com account
|
|
54
19
|
g.send(
|
|
55
|
-
:to => "who@what.com, my_friend@his_company.com, god@heaven.org"
|
|
56
|
-
:cc => "foo@bar.com"
|
|
20
|
+
:to => "who@what.com, my_friend@his_company.com, god@heaven.org",
|
|
21
|
+
:cc => "foo@bar.com",
|
|
57
22
|
:subject => "Hello There!",
|
|
58
23
|
:body => "Hi...\n\nBlah blah blah~...",
|
|
59
24
|
:files => ["./my_pic.jpg", "./my_cv.txt"])
|
|
@@ -61,8 +26,8 @@ Or shorter
|
|
|
61
26
|
# multiple verified email addresses and choose one 'From:' email address
|
|
62
27
|
g.send(
|
|
63
28
|
:from => "verified@email.com",
|
|
64
|
-
:to => "who@what.com, my_friend@his_company.com, god@heaven.org"
|
|
65
|
-
:cc => "foo@bar.com"
|
|
29
|
+
:to => "who@what.com, my_friend@his_company.com, god@heaven.org",
|
|
30
|
+
:cc => "foo@bar.com",
|
|
66
31
|
:subject => "Hello There!",
|
|
67
32
|
:body => "Hi...\n\nBlah blah blah~...",
|
|
68
33
|
:files => ["./my_pic.jpg", "./my_cv.txt"])
|
|
@@ -71,19 +36,6 @@ Or shorter
|
|
|
71
36
|
|
|
72
37
|
=== Playing around with contact list
|
|
73
38
|
|
|
74
|
-
gmail = GMailer.new
|
|
75
|
-
gmail.set_login_info(name, pwd)
|
|
76
|
-
if gmail.connect
|
|
77
|
-
gmail.fetch_box(GM_CONTACT, "freq", 0)
|
|
78
|
-
snapshot = gmail.snapshot(GM_CONTACT)
|
|
79
|
-
puts "Your frequently used addresses:"
|
|
80
|
-
snapshot.contacts.each { |item|
|
|
81
|
-
puts "Name: " + item["name"] + ", Email: " + item["email"]
|
|
82
|
-
}
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
Or shorter
|
|
86
|
-
|
|
87
39
|
GMailer.connect(name, pwd) do |g|
|
|
88
40
|
puts "Your frequently used addresses:"
|
|
89
41
|
g.fetch(:contact=>"freq").each do |item|
|
|
@@ -172,17 +124,17 @@ GMailer.connect(:username=>name,:password=>pwd) do |g|
|
|
|
172
124
|
g.report_spam(msgid)
|
|
173
125
|
|
|
174
126
|
#report a message as not spam
|
|
175
|
-
g.
|
|
127
|
+
g.report_not_spam(msgid)
|
|
176
128
|
end
|
|
177
129
|
|
|
178
130
|
=== Trash In & Out and delete a message
|
|
179
131
|
|
|
180
132
|
GMailer.connect(:username=>name,:password=>pwd) do |g|
|
|
181
133
|
#move a message to trash
|
|
182
|
-
g.
|
|
134
|
+
g.trash(msgid)
|
|
183
135
|
|
|
184
136
|
#move a message from trash to inbox
|
|
185
|
-
g.
|
|
137
|
+
g.untrash(msgid)
|
|
186
138
|
|
|
187
139
|
#delete a trash message forever
|
|
188
140
|
g.delete_trash(msgid)
|
|
@@ -194,6 +146,26 @@ GMailer.connect(:username=>name,:password=>pwd) do |g|
|
|
|
194
146
|
g.delete_message(msgid)
|
|
195
147
|
end
|
|
196
148
|
|
|
149
|
+
=== Show Original Message
|
|
150
|
+
|
|
151
|
+
GMailer.connect(:username=>name,:password=>pwd) do |g|
|
|
152
|
+
#show original
|
|
153
|
+
g.show_original(msgid)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
=== Fetch messages with filter
|
|
157
|
+
|
|
158
|
+
GMailer.connect(:username=>name,:password=>pwd) do |g|
|
|
159
|
+
g.messages(:standard=>'all',:read=>false).each {|msg|
|
|
160
|
+
msg.apply_star
|
|
161
|
+
msg.apply_label(label)
|
|
162
|
+
puts "subject: " + msg.subject
|
|
163
|
+
puts "from: " + msg.sender
|
|
164
|
+
puts msg.body
|
|
165
|
+
puts msg.original
|
|
166
|
+
}
|
|
167
|
+
end
|
|
168
|
+
|
|
197
169
|
== Class Methods
|
|
198
170
|
GMailer.new(charset='UTF-8')
|
|
199
171
|
Returns a new GMailer object and set up charset.
|
|
@@ -279,6 +251,12 @@ apply_star(msgid)
|
|
|
279
251
|
remove_star(msgid)
|
|
280
252
|
To remove starring from a message
|
|
281
253
|
|
|
254
|
+
trash(msgid)
|
|
255
|
+
To move a message to trash
|
|
256
|
+
|
|
257
|
+
untrash(msgid)
|
|
258
|
+
To move a message out of trash
|
|
259
|
+
|
|
282
260
|
archive(msgid)
|
|
283
261
|
To archive a message
|
|
284
262
|
|
data/gmailer.rb
CHANGED
|
@@ -25,6 +25,7 @@ GM_CONVERSATION = 0x004
|
|
|
25
25
|
GM_QUERY = 0x008
|
|
26
26
|
GM_CONTACT = 0x010
|
|
27
27
|
GM_PREFERENCE = 0x020
|
|
28
|
+
GM_SHOWORIGINAL = 0x040
|
|
28
29
|
|
|
29
30
|
GM_ACT_CREATELABEL = 1
|
|
30
31
|
GM_ACT_DELETELABEL = 2
|
|
@@ -48,167 +49,1605 @@ GM_ACT_TRASHMSG = 19 # trash individual message
|
|
|
48
49
|
GM_ACT_DELSPAM = 20 # delete spam, forever
|
|
49
50
|
GM_ACT_DELTRASH = 21 # delete trash message, forever
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
# np.set_debug_output($stderr)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
52
|
+
module GMailer
|
|
53
|
+
VERSION = "0.0.9"
|
|
54
|
+
attr_accessor :connection
|
|
55
|
+
|
|
56
|
+
# the main class.
|
|
57
|
+
class Connection
|
|
58
|
+
@cookie_str
|
|
59
|
+
@login
|
|
60
|
+
@pwd
|
|
61
|
+
@raw # raw packets
|
|
62
|
+
@contact_raw # raw packets for address book
|
|
63
|
+
@timezone
|
|
64
|
+
@created
|
|
65
|
+
@proxy_host
|
|
66
|
+
@proxy_port
|
|
67
|
+
@proxy_user
|
|
68
|
+
@proxy_pass
|
|
69
|
+
|
|
70
|
+
def encode(str)
|
|
71
|
+
return str if @charset.upcase == 'UTF-8'
|
|
72
|
+
begin
|
|
73
|
+
require 'Win32API'
|
|
74
|
+
str += "\0"
|
|
75
|
+
ostr = "\0" * str.length*2
|
|
76
|
+
multiByteToWideChar = Win32API.new('kernel32','MultiByteToWideChar',['L','L','P','L','P','L'],'L')
|
|
77
|
+
multiByteToWideChar.Call(0,0,str,-1,ostr,str.length*2)
|
|
78
|
+
(ostr.strip + "\0").unpack("S*").pack("U*")
|
|
79
|
+
rescue LoadError
|
|
80
|
+
require 'iconv'
|
|
81
|
+
Iconv::iconv('UTF-8',@charset,str)[0]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
#
|
|
86
|
+
# return GMailer
|
|
87
|
+
# desc Constructor
|
|
88
|
+
#
|
|
89
|
+
def initialize(*param)
|
|
90
|
+
@login = ''
|
|
91
|
+
@pwd = ''
|
|
92
|
+
@raw = {}
|
|
93
|
+
@proxy_host = nil
|
|
94
|
+
@proxy_port = 0
|
|
95
|
+
@proxy_user = nil
|
|
96
|
+
@proxy_pass = nil
|
|
97
|
+
@proxy = false
|
|
98
|
+
@type = 0
|
|
99
|
+
if param.length==1 && param[0].class==Hash
|
|
100
|
+
param = param[0]
|
|
101
|
+
set_login_info(param[:username]||'',param[:password]||'')
|
|
102
|
+
@proxy_host = param[:proxy_host]
|
|
103
|
+
@proxy = !@proxy_host.nil?
|
|
104
|
+
@proxy_port = param[:proxy_port] || 80
|
|
105
|
+
@proxy_user = param[:proxy_user]
|
|
106
|
+
@proxy_pass = param[:proxy_pass]
|
|
107
|
+
@charset = param[:charset] || 'UTF-8'
|
|
108
|
+
elsif param.length==0
|
|
109
|
+
@charset = 'UTF-8'
|
|
110
|
+
elsif param.length==1
|
|
111
|
+
@charset = param[0]
|
|
112
|
+
elsif param.length==2
|
|
113
|
+
@charset = 'UTF-8'
|
|
114
|
+
set_login_info(param[0],param[1])
|
|
115
|
+
elsif param.length==3
|
|
116
|
+
@charset = param[2]
|
|
117
|
+
set_login_info(param[0],param[1])
|
|
118
|
+
else
|
|
119
|
+
raise ArgumentError, 'Invalid argument'
|
|
120
|
+
end
|
|
121
|
+
connect_no_cookie
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
#
|
|
125
|
+
# return void
|
|
126
|
+
# param string my_login
|
|
127
|
+
# param string my_pwd
|
|
128
|
+
# param int my_tz
|
|
129
|
+
# desc Set GMail login information.
|
|
130
|
+
#
|
|
131
|
+
def set_login_info(my_login, my_pwd, my_tz=0)
|
|
132
|
+
@login = my_login
|
|
133
|
+
@pwd = my_pwd
|
|
134
|
+
@timezone = (my_tz*-60).to_i.to_s
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
#
|
|
138
|
+
# return bool
|
|
139
|
+
# desc Connect to GMail without setting any session/cookie.
|
|
140
|
+
#
|
|
141
|
+
def connect_no_cookie()
|
|
142
|
+
|
|
143
|
+
postdata = "service=mail&Email=" + URI.escape(@login) + "&Passwd=" + URI.escape(@pwd) + "&null=Sign%20in&continue=" +
|
|
144
|
+
URI.escape('https://mail.google.com/mail/?ui=html&zy=l') + "&rm=false&PersistentCookie=yes"
|
|
145
|
+
|
|
146
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 443)
|
|
147
|
+
np.use_ssl = true
|
|
148
|
+
np.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
149
|
+
result = ''
|
|
150
|
+
response = nil
|
|
151
|
+
# np.set_debug_output($stderr)
|
|
152
|
+
np.start { |http|
|
|
153
|
+
response = http.post(GM_LNK_LOGIN, postdata,{'User-agent' => GM_USER_AGENT} )
|
|
154
|
+
result = response.body
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if result.include?("errormsg")
|
|
158
|
+
@cookie_str = ''
|
|
159
|
+
return false
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
cookies = __cookies(response['set-cookie'])
|
|
163
|
+
arr = URI::split(response["Location"])
|
|
164
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(arr[2], 443)
|
|
165
|
+
np.use_ssl = true
|
|
166
|
+
np.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
167
|
+
result = ''
|
|
168
|
+
response = nil
|
|
169
|
+
# np.set_debug_output($stderr)
|
|
170
|
+
np.start { |http|
|
|
171
|
+
response = http.get(arr[5]+'?'+arr[7], {'Cookie' => cookies,'User-agent' => GM_USER_AGENT} )
|
|
172
|
+
result = response.body
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
arr = URI::split(response["Location"])
|
|
176
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(arr[2], 443)
|
|
177
|
+
np.use_ssl = true
|
|
178
|
+
np.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
179
|
+
result = ''
|
|
180
|
+
response = nil
|
|
181
|
+
# np.set_debug_output($stderr)
|
|
182
|
+
np.start { |http|
|
|
183
|
+
response = http.get(arr[5]+'?'+arr[7], {'Cookie' => cookies,'User-agent' => GM_USER_AGENT} )
|
|
184
|
+
result = response.body
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@loc = response["Location"]
|
|
188
|
+
cookies += ';' + __cookies(response['set-cookie'])
|
|
189
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(arr[2], 443)
|
|
190
|
+
np.use_ssl = true
|
|
191
|
+
np.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
192
|
+
# np.set_debug_output($stderr)
|
|
193
|
+
np.start { |http|
|
|
194
|
+
response = http.get(@loc, {'Cookie' => cookies,'User-agent' => GM_USER_AGENT} )
|
|
195
|
+
result = response.body
|
|
196
|
+
}
|
|
197
|
+
cookies += ';' + __cookies(response['set-cookie'])
|
|
198
|
+
|
|
199
|
+
@cookie_str = cookies + ";TZ=" + @timezone
|
|
200
|
+
|
|
201
|
+
return true
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
#
|
|
205
|
+
# return bool
|
|
206
|
+
# desc Connect to GMail with default session management settings.
|
|
207
|
+
#
|
|
208
|
+
def connect()
|
|
209
|
+
connect_no_cookie()
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
#
|
|
215
|
+
# return bool
|
|
216
|
+
# desc See if it is connected to GMail.
|
|
217
|
+
#
|
|
218
|
+
def connected?
|
|
219
|
+
!@cookie_str.empty?
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
#
|
|
223
|
+
# return bool
|
|
224
|
+
# param string query
|
|
225
|
+
# desc Fetch contents by URL query.
|
|
226
|
+
#
|
|
227
|
+
def __fetch(query)
|
|
228
|
+
if connected?
|
|
229
|
+
query += "&zv=" + (rand(2000)*2147483.648).to_i.to_s
|
|
230
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
231
|
+
# np.set_debug_output($stderr)
|
|
232
|
+
inbox = ''
|
|
233
|
+
np.start { |http|
|
|
234
|
+
response = http.get(GM_LNK_GMAIL + "?" + query,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT })
|
|
235
|
+
inbox = response.body
|
|
236
|
+
}
|
|
237
|
+
if @type == GM_SHOWORIGINAL
|
|
238
|
+
@raw = inbox
|
|
239
|
+
else
|
|
240
|
+
state = 0
|
|
241
|
+
tmp = ''
|
|
242
|
+
inbox.each do |l|
|
|
243
|
+
if /^D\(.*\);$/.match(l)
|
|
244
|
+
state = 0
|
|
245
|
+
tmp += l
|
|
246
|
+
elsif l[0,3]=='D(['
|
|
247
|
+
state = 1
|
|
248
|
+
tmp += l.chomp
|
|
249
|
+
elsif l[0,2]==');'
|
|
250
|
+
state = 2
|
|
251
|
+
tmp += ")\n"
|
|
252
|
+
elsif state == 1
|
|
253
|
+
tmp += l.chomp
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
inbox = tmp
|
|
257
|
+
matches = inbox.scan(/D\((.*)\)/).flatten
|
|
258
|
+
packets = {}
|
|
259
|
+
matches.each {|x|
|
|
260
|
+
tmp = eval(x.gsub(",,",",'',").gsub(",,",",'',").gsub(",]",",'']").gsub('#{','#\{'))
|
|
261
|
+
if (packets[tmp[0]] || (tmp[0]=="mi"||tmp[0]=="mb"||tmp[0]=="di"))
|
|
262
|
+
if (tmp[0]=="t"||tmp[0]=="ts"||tmp[0]=="a"||tmp[0]=="cl")
|
|
263
|
+
packets[tmp[0]] += tmp[1..-1]
|
|
264
|
+
end
|
|
265
|
+
if (tmp[0]=="mi"||tmp[0]=="mb"||tmp[0]=="di")
|
|
266
|
+
if !packets["mg"].nil?
|
|
267
|
+
packets["mg"].push(tmp)
|
|
268
|
+
else
|
|
269
|
+
packets["mg"] = [tmp]
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
else
|
|
273
|
+
packets[tmp[0]] = tmp
|
|
274
|
+
end
|
|
275
|
+
}
|
|
276
|
+
if packets["cl"] && packets["cl"].length > 1
|
|
277
|
+
packets["ce"] = []
|
|
278
|
+
for i in 1 .. packets["cl"].length-1
|
|
279
|
+
packets["ce"].push(packets["cl"][i])
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
@raw = packets
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
true
|
|
286
|
+
else # not logged in yet
|
|
287
|
+
false
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
private :__fetch
|
|
291
|
+
|
|
292
|
+
#
|
|
293
|
+
# return bool
|
|
294
|
+
# param constant type
|
|
295
|
+
# param mixed box
|
|
296
|
+
# param int pos
|
|
297
|
+
# desc Fetch contents from GMail by type.
|
|
298
|
+
#
|
|
299
|
+
def fetch_box(type, box, pos)
|
|
300
|
+
@type = type
|
|
301
|
+
if connected?
|
|
302
|
+
case type
|
|
303
|
+
when GM_STANDARD
|
|
304
|
+
q = "search=" + box.downcase + "&view=tl&start=" + pos.to_s
|
|
305
|
+
|
|
306
|
+
when GM_LABEL
|
|
307
|
+
q = "search=cat&cat=" + box.to_s + "&view=tl&start=" + pos.to_s
|
|
308
|
+
|
|
309
|
+
when GM_CONVERSATION
|
|
310
|
+
q = "search=inbox&ser=1&view=cv"
|
|
311
|
+
if (box.class==Array)
|
|
312
|
+
q += "&th=" + box[0].to_s
|
|
313
|
+
for i in 1 .. box.length
|
|
314
|
+
q += "&msgs=" + box[i].to_s
|
|
315
|
+
end
|
|
316
|
+
else
|
|
317
|
+
q += "&th=" + box.to_s
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
when GM_SHOWORIGINAL
|
|
321
|
+
q = "view=om&th=" + box.to_s
|
|
322
|
+
|
|
323
|
+
when GM_QUERY
|
|
324
|
+
q = "search=query&q=" + URI.escape(box.to_s) + "&view=tl&start=" + pos.to_s
|
|
325
|
+
|
|
326
|
+
when GM_PREFERENCE
|
|
327
|
+
q = "view=pr&pnl=g"
|
|
328
|
+
|
|
329
|
+
when GM_CONTACT
|
|
330
|
+
if box.downcase == "all"
|
|
331
|
+
q = "view=cl&search=contacts&pnl=a"
|
|
332
|
+
else
|
|
333
|
+
q = "view=cl&search=contacts&pnl=d"
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
else
|
|
337
|
+
q = "search=inbox&view=tl&start=0&init=1"
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
__fetch(q)
|
|
341
|
+
else
|
|
342
|
+
false
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
#
|
|
347
|
+
# return snapshot
|
|
348
|
+
# param constant type
|
|
349
|
+
# param mixed box
|
|
350
|
+
# param int pos
|
|
351
|
+
# desc Fetch contents from GMail by type.
|
|
352
|
+
#
|
|
353
|
+
def fetch(hash_param)
|
|
354
|
+
type = GM_STANDARD
|
|
355
|
+
box = "inbox"
|
|
356
|
+
pos = 0
|
|
357
|
+
@filter = {}
|
|
358
|
+
hash_param.keys.each do |k|
|
|
359
|
+
case k
|
|
360
|
+
when :label
|
|
361
|
+
type = GM_LABEL
|
|
362
|
+
box = hash_param[k]
|
|
363
|
+
when :standard
|
|
364
|
+
type = GM_STANDARD
|
|
365
|
+
box = hash_param[k]
|
|
366
|
+
when :conversation
|
|
367
|
+
type = GM_CONVERSATION
|
|
368
|
+
box = hash_param[k]
|
|
369
|
+
when :show_original
|
|
370
|
+
type = GM_SHOWORIGINAL
|
|
371
|
+
box = hash_param[k]
|
|
372
|
+
when :preference
|
|
373
|
+
type = GM_PREFERENCE
|
|
374
|
+
box = hash_param[k]
|
|
375
|
+
when :contact
|
|
376
|
+
type = GM_CONTACT
|
|
377
|
+
box = hash_param[k]
|
|
378
|
+
when :query
|
|
379
|
+
type = GM_QUERY
|
|
380
|
+
box = hash_param[k]
|
|
381
|
+
when :pos
|
|
382
|
+
pos = hash_param[k].to_i
|
|
383
|
+
when :read
|
|
384
|
+
@filter[:read] = hash_param[k]
|
|
385
|
+
when :star
|
|
386
|
+
@filter[:star] = hash_param[k]
|
|
387
|
+
else
|
|
388
|
+
raise ArgumentError, 'Invalid hash argument'
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
box = "inbox" unless box
|
|
392
|
+
fetch_box(type,box,pos)
|
|
393
|
+
if type == GM_SHOWORIGINAL
|
|
394
|
+
snapshot = @raw
|
|
395
|
+
else
|
|
396
|
+
snapshot = snapshot(type)
|
|
397
|
+
end
|
|
398
|
+
if block_given?
|
|
399
|
+
yield(snapshot)
|
|
400
|
+
elsif type == GM_CONTACT
|
|
401
|
+
snapshot.contacts
|
|
402
|
+
else
|
|
403
|
+
snapshot
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
#
|
|
408
|
+
# return string[]
|
|
409
|
+
# param string[] convs
|
|
410
|
+
# param string path
|
|
411
|
+
# desc Save all attaching files of conversations to a path.
|
|
412
|
+
#
|
|
413
|
+
def attachments_of(convs, path)
|
|
414
|
+
|
|
415
|
+
if connected?
|
|
416
|
+
if (convs.class != Array)
|
|
417
|
+
convs = [convs] # array wrapper
|
|
418
|
+
end
|
|
419
|
+
final = []
|
|
420
|
+
convs.each { |v|
|
|
421
|
+
if v["attachment"]
|
|
422
|
+
v["attachment"].each { |vv|
|
|
423
|
+
f = path+"/"+vv["filename"]
|
|
424
|
+
f = path+"/"+vv["filename"]+"."+rand(2000).to_s while (FileTest.exist?(f))
|
|
425
|
+
if attachment(vv["id"],v["id"],f,false)
|
|
426
|
+
final.push(f)
|
|
427
|
+
end
|
|
428
|
+
}
|
|
429
|
+
end
|
|
430
|
+
}
|
|
431
|
+
final
|
|
432
|
+
else
|
|
433
|
+
nil
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
#
|
|
438
|
+
# return string[]
|
|
439
|
+
# param string[] convs
|
|
440
|
+
# param string path
|
|
441
|
+
# desc Save all attaching files of conversations to a path.
|
|
442
|
+
#
|
|
443
|
+
def zip_attachments_of(convs, path)
|
|
444
|
+
|
|
445
|
+
if connected?
|
|
446
|
+
if (convs.class != Array)
|
|
447
|
+
convs = [convs] # array wrapper
|
|
448
|
+
end
|
|
449
|
+
final = []
|
|
450
|
+
convs.each {|v|
|
|
451
|
+
if v["attachment"]
|
|
452
|
+
f = path+"/attachment.zip"
|
|
453
|
+
f = path+"/attachment."+rand(2000).to_s+".zip" while (FileTest.exist?(f))
|
|
454
|
+
if attachment(v["attachment"][0]["id"],v["id"],f,true)
|
|
455
|
+
final.push(f)
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
}
|
|
459
|
+
final
|
|
460
|
+
else
|
|
461
|
+
nil
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
#
|
|
466
|
+
# return bool
|
|
467
|
+
# param string attid
|
|
468
|
+
# param string msgid
|
|
469
|
+
# param string filename
|
|
470
|
+
# desc Save attachment with attachment ID attid and message ID msgid to file with name filename.
|
|
471
|
+
#
|
|
472
|
+
def attachment(attid, msgid, filename, zipped=false)
|
|
473
|
+
|
|
474
|
+
if connected?
|
|
475
|
+
|
|
476
|
+
if !zipped
|
|
477
|
+
query = GM_LNK_ATTACHMENT + "&attid=" + URI.escape(attid) + "&th=" + URI.escape(msgid)
|
|
478
|
+
else
|
|
479
|
+
query = GM_LNK_ATTACHMENT_ZIPPED + "&th=" + URI.escape(msgid)
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
File.open(filename,"wb") { |f|
|
|
483
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
484
|
+
np.start { |http|
|
|
485
|
+
response = http.get(query,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT })
|
|
486
|
+
f.write(response.body)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
true
|
|
490
|
+
else
|
|
491
|
+
false
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
#
|
|
496
|
+
# return array of labels
|
|
497
|
+
# desc get label lists
|
|
498
|
+
#
|
|
499
|
+
def labels()
|
|
500
|
+
if connected?
|
|
501
|
+
fetch(:standard=>"inbox") {|s| s.label_list }
|
|
502
|
+
else
|
|
503
|
+
nil
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
#
|
|
508
|
+
# return string
|
|
509
|
+
# param string label
|
|
510
|
+
# desc validate label
|
|
511
|
+
#
|
|
512
|
+
def validate_label(label)
|
|
513
|
+
label.strip!
|
|
514
|
+
if label==''
|
|
515
|
+
raise ArgumentError, 'Error: Labels cannot empty string'
|
|
516
|
+
end
|
|
517
|
+
if label.length > 40
|
|
518
|
+
raise ArgumentError, 'Error: Labels cannot contain more than 40 characters'
|
|
519
|
+
end
|
|
520
|
+
if label.include?('^')
|
|
521
|
+
raise ArgumentError, "Error: Labels cannot contain the character '^'"
|
|
522
|
+
end
|
|
523
|
+
label
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
#
|
|
527
|
+
# return boolean
|
|
528
|
+
# param string label
|
|
529
|
+
# desc create label
|
|
530
|
+
#
|
|
531
|
+
def create_label(label)
|
|
532
|
+
if connected?
|
|
533
|
+
perform_action(GM_ACT_CREATELABEL, '', validate_label(label))
|
|
534
|
+
else
|
|
535
|
+
false
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
#
|
|
540
|
+
# return boolean
|
|
541
|
+
# param string label
|
|
542
|
+
# desc create label
|
|
543
|
+
#
|
|
544
|
+
def delete_label(label)
|
|
545
|
+
if connected?
|
|
546
|
+
perform_action(GM_ACT_DELETELABEL, '', validate_label(label))
|
|
547
|
+
else
|
|
548
|
+
false
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
#
|
|
553
|
+
# return boolean
|
|
554
|
+
# param string old_label
|
|
555
|
+
# param string new_label
|
|
556
|
+
# desc create label
|
|
557
|
+
#
|
|
558
|
+
def rename_label(old_label,new_label)
|
|
559
|
+
if connected?
|
|
560
|
+
perform_action(GM_ACT_RENAMELABEL, '',
|
|
561
|
+
validate_label(old_label) +'^' + validate_label(new_label))
|
|
562
|
+
else
|
|
563
|
+
false
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
#
|
|
568
|
+
# return boolean
|
|
569
|
+
# param string msgid
|
|
570
|
+
# param string label
|
|
571
|
+
# desc apply label to message
|
|
572
|
+
#
|
|
573
|
+
def apply_label(id,label)
|
|
574
|
+
if connected?
|
|
575
|
+
perform_action(GM_ACT_APPLYLABEL, id, validate_label(label))
|
|
576
|
+
else
|
|
577
|
+
false
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
#
|
|
582
|
+
# return boolean
|
|
583
|
+
# param string msgid
|
|
584
|
+
# param string label
|
|
585
|
+
# desc remove label from message
|
|
586
|
+
#
|
|
587
|
+
def remove_label(id,label)
|
|
588
|
+
if connected?
|
|
589
|
+
perform_action(GM_ACT_REMOVELABEL, id, validate_label(label))
|
|
590
|
+
else
|
|
591
|
+
false
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
#
|
|
596
|
+
# return boolean
|
|
597
|
+
# param string hash_param
|
|
598
|
+
# desc remove label from message
|
|
599
|
+
#
|
|
600
|
+
def update_preference(hash_param)
|
|
601
|
+
if connected?
|
|
602
|
+
args = {}
|
|
603
|
+
hash_param.keys.each do |k|
|
|
604
|
+
case k
|
|
605
|
+
when :max_page_size
|
|
606
|
+
args['p_ix_nt'] = hash_param[k]
|
|
607
|
+
when :keyboard_shortcuts
|
|
608
|
+
args['p_bx_hs'] = hash_param[k] ? '1' : '0'
|
|
609
|
+
when :indicators
|
|
610
|
+
args['p_bx_sc'] = hash_param[k] ? '1' : '0'
|
|
611
|
+
when :display_language
|
|
612
|
+
args['p_sx_dl'] = hash_param[k]
|
|
613
|
+
when :signature
|
|
614
|
+
args['p_sx_sg'] = hash_param[k]
|
|
615
|
+
when :reply_to
|
|
616
|
+
args['p_sx_rt'] = hash_param[k]
|
|
617
|
+
when :snippets
|
|
618
|
+
args['p_bx_ns'] = hash_param[k] ? '0' : '1'
|
|
619
|
+
when :display_name
|
|
620
|
+
args['p_sx_dn'] = hash_param[k]
|
|
621
|
+
end
|
|
622
|
+
end
|
|
623
|
+
param = '&' + args.to_a.map {|x| x.join('=')}.join('&')
|
|
624
|
+
perform_action(GM_ACT_PREFERENCE,'', param)
|
|
625
|
+
else
|
|
626
|
+
false
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
#
|
|
631
|
+
# return boolean
|
|
632
|
+
# param string msgid
|
|
633
|
+
# desc apply star to a message
|
|
634
|
+
#
|
|
635
|
+
def apply_star(msgid)
|
|
636
|
+
if connected?
|
|
637
|
+
perform_action(GM_ACT_STAR,msgid, '')
|
|
638
|
+
else
|
|
639
|
+
false
|
|
640
|
+
end
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
#
|
|
644
|
+
# return boolean
|
|
645
|
+
# param string msgid
|
|
646
|
+
# desc remove star from a message
|
|
647
|
+
#
|
|
648
|
+
def remove_star(msgid)
|
|
649
|
+
if connected?
|
|
650
|
+
perform_action(GM_ACT_UNSTAR,msgid, '')
|
|
651
|
+
else
|
|
652
|
+
false
|
|
653
|
+
end
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
#
|
|
657
|
+
# return boolean
|
|
658
|
+
# param string msgid
|
|
659
|
+
# desc report a message as spam
|
|
660
|
+
#
|
|
661
|
+
def report_spam(msgid)
|
|
662
|
+
if connected?
|
|
663
|
+
perform_action(GM_ACT_SPAM,msgid, '')
|
|
664
|
+
else
|
|
665
|
+
false
|
|
666
|
+
end
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
#
|
|
670
|
+
# return boolean
|
|
671
|
+
# param string msgid
|
|
672
|
+
# desc report a message as not spam
|
|
673
|
+
#
|
|
674
|
+
def report_not_spam(msgid)
|
|
675
|
+
if connected?
|
|
676
|
+
perform_action(GM_ACT_UNSPAM,msgid, '')
|
|
677
|
+
else
|
|
678
|
+
false
|
|
679
|
+
end
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
#
|
|
683
|
+
# return boolean
|
|
684
|
+
# param string msgid
|
|
685
|
+
# desc delete a spam message forever
|
|
686
|
+
#
|
|
687
|
+
def delete_spam(msgid)
|
|
688
|
+
if connected?
|
|
689
|
+
perform_action(GM_ACT_DELSPAM,msgid, '')
|
|
690
|
+
else
|
|
691
|
+
false
|
|
692
|
+
end
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
#
|
|
696
|
+
# return boolean
|
|
697
|
+
# param string msgid
|
|
698
|
+
# desc mark a message as read
|
|
699
|
+
#
|
|
700
|
+
def mark_read(msgid)
|
|
701
|
+
if connected?
|
|
702
|
+
perform_action(GM_ACT_READ,msgid, '')
|
|
703
|
+
else
|
|
704
|
+
false
|
|
705
|
+
end
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
#
|
|
709
|
+
# return boolean
|
|
710
|
+
# param string msgid
|
|
711
|
+
# desc mark a message as unread
|
|
712
|
+
#
|
|
713
|
+
def mark_unread(msgid)
|
|
714
|
+
if connected?
|
|
715
|
+
perform_action(GM_ACT_UNREAD,msgid, '')
|
|
716
|
+
else
|
|
717
|
+
false
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
#
|
|
722
|
+
# return original message string
|
|
723
|
+
# param string msgid
|
|
724
|
+
# desc show original message format
|
|
725
|
+
#
|
|
726
|
+
def show_original(msgid)
|
|
727
|
+
if connected?
|
|
728
|
+
fetch(:show_original=>msgid)
|
|
729
|
+
else
|
|
730
|
+
false
|
|
731
|
+
end
|
|
732
|
+
end
|
|
733
|
+
|
|
734
|
+
#
|
|
735
|
+
# return boolean
|
|
736
|
+
# param string msgid
|
|
737
|
+
# desc move a message to trash
|
|
738
|
+
#
|
|
739
|
+
def trash(msgid)
|
|
740
|
+
if connected?
|
|
741
|
+
perform_action(GM_ACT_TRASH,msgid, '')
|
|
742
|
+
else
|
|
743
|
+
false
|
|
744
|
+
end
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
#
|
|
748
|
+
# return boolean
|
|
749
|
+
# param string msgid
|
|
750
|
+
# desc move a message from trash to inbox
|
|
751
|
+
#
|
|
752
|
+
def untrash(msgid)
|
|
753
|
+
if connected?
|
|
754
|
+
perform_action(GM_ACT_UNTRASH,msgid, '')
|
|
755
|
+
else
|
|
756
|
+
false
|
|
757
|
+
end
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
#
|
|
761
|
+
# return boolean
|
|
762
|
+
# param string msgid
|
|
763
|
+
# desc delete a trash message forever
|
|
764
|
+
#
|
|
765
|
+
def delete_trash(msgid)
|
|
766
|
+
if connected?
|
|
767
|
+
perform_action(GM_ACT_DELTRASH,msgid, '')
|
|
768
|
+
else
|
|
769
|
+
false
|
|
770
|
+
end
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
#
|
|
774
|
+
# return boolean
|
|
775
|
+
# param string msgid
|
|
776
|
+
# desc delete a message forever
|
|
777
|
+
#
|
|
778
|
+
def delete_message(msgid)
|
|
779
|
+
if connected?
|
|
780
|
+
perform_action(GM_ACT_DELFOREVER,msgid, '')
|
|
781
|
+
else
|
|
782
|
+
false
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
#
|
|
787
|
+
# return boolean
|
|
788
|
+
# param string msgid
|
|
789
|
+
# desc archive a message
|
|
790
|
+
#
|
|
791
|
+
def archive(msgid)
|
|
792
|
+
if connected?
|
|
793
|
+
perform_action(GM_ACT_ARCHIVE,msgid, '')
|
|
794
|
+
else
|
|
795
|
+
false
|
|
796
|
+
end
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
#
|
|
800
|
+
# return boolean
|
|
801
|
+
# param string msgid
|
|
802
|
+
# desc archive a message
|
|
803
|
+
#
|
|
804
|
+
def unarchive(msgid)
|
|
805
|
+
if connected?
|
|
806
|
+
perform_action(GM_ACT_INBOX,msgid, '')
|
|
807
|
+
else
|
|
808
|
+
false
|
|
809
|
+
end
|
|
810
|
+
end
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
#
|
|
814
|
+
# return hash of preference
|
|
815
|
+
# desc get preferences
|
|
816
|
+
#
|
|
817
|
+
def preference()
|
|
818
|
+
if connected?
|
|
819
|
+
fetch(:preference=>"all").preference
|
|
820
|
+
else
|
|
821
|
+
nil
|
|
822
|
+
end
|
|
823
|
+
end
|
|
824
|
+
|
|
825
|
+
#
|
|
826
|
+
# return array of messages
|
|
827
|
+
# desc get message lists
|
|
828
|
+
#
|
|
829
|
+
def messages(hash_param)
|
|
830
|
+
if connected?
|
|
831
|
+
ml = fetch(hash_param).message_list
|
|
832
|
+
@filter.keys.each do |k|
|
|
833
|
+
case k
|
|
834
|
+
when :read
|
|
835
|
+
ml.box = ml.box.find_all { |x| x['read?'] == @filter[k] }
|
|
836
|
+
when :star
|
|
837
|
+
ml.box = ml.box.find_all { |x| x['star?'] == @filter[k] }
|
|
838
|
+
end
|
|
839
|
+
end
|
|
840
|
+
ml.connection = self
|
|
841
|
+
if block_given?
|
|
842
|
+
yield(ml)
|
|
843
|
+
else
|
|
844
|
+
ml
|
|
845
|
+
end
|
|
846
|
+
else
|
|
847
|
+
nil
|
|
848
|
+
end
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
#
|
|
852
|
+
# return string
|
|
853
|
+
# param string query
|
|
854
|
+
# desc Dump everything to output.
|
|
855
|
+
#
|
|
856
|
+
def dump(query)
|
|
857
|
+
page = ''
|
|
858
|
+
if connected?
|
|
859
|
+
query += "&zv=" + (rand(2000)*2147483.648).to_i.to_s
|
|
860
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
861
|
+
np.start { |http|
|
|
862
|
+
response = http.get(GM_LNK_GMAIL + "?"+query,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT })
|
|
863
|
+
page = response.body
|
|
864
|
+
}
|
|
865
|
+
else # not logged in yet
|
|
866
|
+
|
|
867
|
+
end
|
|
868
|
+
page
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
def stripslashes(string)
|
|
872
|
+
encode(string.gsub("\\\"", "\"").gsub("\\'", "'").gsub("\\\\", "\\"))
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
#
|
|
877
|
+
# return bool
|
|
878
|
+
# param string to
|
|
879
|
+
# param string subject
|
|
880
|
+
# param string body
|
|
881
|
+
# param string cc
|
|
882
|
+
# param string bcc
|
|
883
|
+
# param string msg_id
|
|
884
|
+
# param string thread_id
|
|
885
|
+
# param string[] files
|
|
886
|
+
# desc Send GMail.
|
|
887
|
+
#
|
|
888
|
+
def send(*param)
|
|
889
|
+
if param.length==1 && param[0].class==Hash
|
|
890
|
+
param = param[0]
|
|
891
|
+
from = param[:from] || ''
|
|
892
|
+
to = param[:to] || ''
|
|
893
|
+
subject = param[:subject] || ''
|
|
894
|
+
body = param[:body] || ''
|
|
895
|
+
cc = param[:cc] || ''
|
|
896
|
+
bcc = param[:bcc] || ''
|
|
897
|
+
msg_id = param[:msg_id] || ''
|
|
898
|
+
thread_id = param[:msg_id] || ''
|
|
899
|
+
files = param[:files] || []
|
|
900
|
+
draft = param[:draft] || false
|
|
901
|
+
draft_id = param[:draft_id] || ''
|
|
902
|
+
elsif param.length==10
|
|
903
|
+
to, subject, body, cc, bcc, msg_id, thread_id, files, draft, draft_id = param
|
|
904
|
+
elsif param.length==11
|
|
905
|
+
from, to, subject, body, cc, bcc, msg_id, thread_id, files, draft, draft_id = param
|
|
906
|
+
else
|
|
907
|
+
raise ArgumentError, 'Invalid argument'
|
|
908
|
+
end
|
|
909
|
+
|
|
910
|
+
if connected?
|
|
911
|
+
other_emails = fetch(:preference=>"all").other_emails
|
|
912
|
+
if other_emails.length>0
|
|
913
|
+
other_emails.each {|v|
|
|
914
|
+
from = v['email'] if from=='' && v['default']
|
|
915
|
+
}
|
|
916
|
+
from = @login + 'gmail.com' if from==''
|
|
917
|
+
else
|
|
918
|
+
from = nil
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
postdata = {}
|
|
922
|
+
if draft
|
|
923
|
+
postdata["view"] = "sd"
|
|
924
|
+
postdata["draft"] = draft_id
|
|
925
|
+
postdata["rm"] = msg_id
|
|
926
|
+
postdata["th"] = thread_id
|
|
927
|
+
else
|
|
928
|
+
postdata["view"] = "sm"
|
|
929
|
+
postdata["draft"] = draft_id
|
|
930
|
+
postdata["rm"] = msg_id
|
|
931
|
+
postdata["th"] = thread_id
|
|
932
|
+
end
|
|
933
|
+
postdata["msgbody"] = stripslashes(body)
|
|
934
|
+
postdata["from"] = stripslashes(from) if from
|
|
935
|
+
postdata["to"] = stripslashes(to)
|
|
936
|
+
postdata["subject"] = stripslashes(subject)
|
|
937
|
+
postdata["cc"] = stripslashes(cc)
|
|
938
|
+
postdata["bcc"] = stripslashes(bcc)
|
|
939
|
+
|
|
940
|
+
postdata["cmid"] = 1
|
|
941
|
+
postdata["ishtml"] = 0
|
|
942
|
+
|
|
943
|
+
cc = @cookie_str.split(';')
|
|
944
|
+
cc.each {|cc_part|
|
|
945
|
+
cc_parts = cc_part.split('=')
|
|
946
|
+
if(cc_parts[0]=='GMAIL_AT')
|
|
947
|
+
postdata["at"] = cc_parts[1]
|
|
948
|
+
break
|
|
949
|
+
end
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
boundary = "----#{Time.now.to_i}#{(rand(2000)*2147483.648).to_i}"
|
|
953
|
+
postdata2 = []
|
|
954
|
+
postdata.each {|k,v|
|
|
955
|
+
postdata2.push("Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n#{v}\r\n")
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
files.each_with_index {|f,i|
|
|
959
|
+
content = File.open(f,'rb') { |c| c.read }
|
|
960
|
+
postdata2.push("Content-Disposition: form-data; name=\"file#{i}\"; filename=\"#{File.basename(f)}\"\r\n" +
|
|
961
|
+
"Content-Transfer-Encoding: binary\r\n" +
|
|
962
|
+
"Content-Type: application/octet-stream\r\n\r\n" + content + "\r\n")
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
postdata = postdata2.collect { |p|
|
|
966
|
+
"--" + boundary + "\r\n" + p
|
|
967
|
+
}.join('') + "--" + boundary + "--\r\n"
|
|
968
|
+
|
|
969
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
970
|
+
response = nil
|
|
971
|
+
# np.set_debug_output($stderr)
|
|
972
|
+
np.start { |http|
|
|
973
|
+
response = http.post(GM_LNK_GMAIL, postdata,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT,'Content-type' => 'multipart/form-data; boundary=' + boundary } )
|
|
974
|
+
}
|
|
975
|
+
true
|
|
976
|
+
else
|
|
977
|
+
false
|
|
978
|
+
end
|
|
979
|
+
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
#
|
|
983
|
+
# return bool
|
|
984
|
+
# param constant act
|
|
985
|
+
# param string[] id
|
|
986
|
+
# param string para
|
|
987
|
+
# desc Perform action on messages.
|
|
988
|
+
#
|
|
989
|
+
def perform_action(act, id, para)
|
|
990
|
+
|
|
991
|
+
if connected?
|
|
992
|
+
|
|
993
|
+
if (act == GM_ACT_DELFOREVER)
|
|
994
|
+
perform_action(GM_ACT_TRASH, id, 0) # trash it before
|
|
995
|
+
end
|
|
996
|
+
postdata = "act="
|
|
997
|
+
|
|
998
|
+
action_codes = ["ib", "cc_", "dc_", "nc_", "ac_", "rc_", "prefs", "st", "xst",
|
|
999
|
+
"sp", "us", "rd", "ur", "tr", "dl", "rc_^i", "ib", "ib", "dd", "dm", "dl", "dl"]
|
|
1000
|
+
postdata += action_codes[act] ? action_codes[act] : action_codes[GM_ACT_INBOX]
|
|
1001
|
+
if act == GM_ACT_RENAMELABEL then
|
|
1002
|
+
paras = para.split('^')
|
|
1003
|
+
para = validate_label(paras[0])+'^'+validate_label(paras[1])
|
|
1004
|
+
elsif ([GM_ACT_APPLYLABEL,GM_ACT_REMOVELABEL,GM_ACT_CREATELABEL,
|
|
1005
|
+
GM_ACT_DELETELABEL,].include?(act))
|
|
1006
|
+
para = validate_label(para)
|
|
1007
|
+
end
|
|
1008
|
+
if ([GM_ACT_APPLYLABEL,GM_ACT_REMOVELABEL,GM_ACT_CREATELABEL,
|
|
1009
|
+
GM_ACT_DELETELABEL,GM_ACT_RENAMELABEL,GM_ACT_PREFERENCE].include?(act))
|
|
1010
|
+
postdata += para.to_s
|
|
1011
|
+
end
|
|
1012
|
+
|
|
1013
|
+
cc = @cookie_str.split(';')
|
|
1014
|
+
cc.each {|cc_part|
|
|
1015
|
+
cc_parts = cc_part.split('=')
|
|
1016
|
+
if(cc_parts[0]=='GMAIL_AT')
|
|
1017
|
+
postdata += "&at=" + cc_parts[1]
|
|
1018
|
+
break
|
|
1019
|
+
end
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
if (act == GM_ACT_TRASHMSG)
|
|
1023
|
+
postdata += "&m=" + id.to_s
|
|
1024
|
+
else
|
|
1025
|
+
if id.class==Array
|
|
1026
|
+
id.each {|t| postdata += "&t="+t.to_s }
|
|
1027
|
+
else
|
|
1028
|
+
postdata += "&t="+id.to_s
|
|
1029
|
+
end
|
|
1030
|
+
end
|
|
1031
|
+
postdata += "&vp="
|
|
1032
|
+
|
|
1033
|
+
if [GM_ACT_UNTRASH,GM_ACT_DELFOREVER,GM_ACT_DELTRASH].include?(act)
|
|
1034
|
+
link = GM_LNK_GMAIL+"?search=trash&view=tl&start=0"
|
|
1035
|
+
elsif (act == GM_ACT_DELSPAM)
|
|
1036
|
+
link = GM_LNK_GMAIL+"?search=spam&view=tl&start=0"
|
|
1037
|
+
else
|
|
1038
|
+
link = GM_LNK_GMAIL+"?search=query&q=&view=tl&start=0"
|
|
1039
|
+
end
|
|
1040
|
+
|
|
1041
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
1042
|
+
# np.set_debug_output($stderr)
|
|
1043
|
+
np.start { |http|
|
|
1044
|
+
response = http.post(link, postdata,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT} )
|
|
1045
|
+
result = response.body
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
return true
|
|
1049
|
+
else
|
|
1050
|
+
return false
|
|
1051
|
+
end
|
|
1052
|
+
|
|
1053
|
+
end
|
|
1054
|
+
|
|
1055
|
+
#
|
|
1056
|
+
# return void
|
|
1057
|
+
# desc Disconnect from GMail.
|
|
1058
|
+
#
|
|
1059
|
+
def disconnect()
|
|
1060
|
+
|
|
1061
|
+
response = nil
|
|
1062
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
1063
|
+
# np.set_debug_output($stderr)
|
|
1064
|
+
np.start { |http|
|
|
1065
|
+
response = http.get(GM_LNK_LOGOUT,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT })
|
|
1066
|
+
}
|
|
1067
|
+
arr = URI::split(response["Location"])
|
|
1068
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(arr[2], 80)
|
|
1069
|
+
# np.set_debug_output($stderr)
|
|
1070
|
+
np.start { |http|
|
|
1071
|
+
response = http.get(arr[5]+'?'+arr[7], {'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT} )
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
@cookie_str = ''
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
#
|
|
1078
|
+
# return GMailSnapshot
|
|
1079
|
+
# param constant type
|
|
1080
|
+
# desc Get GMSnapshot by type.
|
|
1081
|
+
#
|
|
1082
|
+
def snapshot(type)
|
|
1083
|
+
if [GM_STANDARD,GM_LABEL,GM_CONVERSATION,GM_QUERY,GM_PREFERENCE,GM_CONTACT].include?(type)
|
|
1084
|
+
return GMailSnapshot.new(type, @raw, @charset)
|
|
1085
|
+
else
|
|
1086
|
+
return GMailSnapshot.new(GM_STANDARD, @raw, @charset) # assuming normal by default
|
|
1087
|
+
end
|
|
1088
|
+
end
|
|
1089
|
+
|
|
1090
|
+
def snap(type)
|
|
1091
|
+
action = GM_STANDARD
|
|
1092
|
+
case type
|
|
1093
|
+
when :standard
|
|
1094
|
+
action = GM_STANDARD
|
|
1095
|
+
when :label
|
|
1096
|
+
action = GM_LABEL
|
|
1097
|
+
when :conversation
|
|
1098
|
+
action = GM_CONVERSATION
|
|
1099
|
+
when :query
|
|
1100
|
+
action = GM_QUERY
|
|
1101
|
+
when :preference
|
|
1102
|
+
action = GM_PREFERENCE
|
|
1103
|
+
when :contact
|
|
1104
|
+
action = GM_CONTACT
|
|
1105
|
+
else
|
|
1106
|
+
raise ArgumentError, 'Invalid type'
|
|
1107
|
+
end
|
|
1108
|
+
snapshot(action)
|
|
1109
|
+
end
|
|
1110
|
+
|
|
1111
|
+
#
|
|
1112
|
+
# return bool
|
|
1113
|
+
# param string email
|
|
1114
|
+
# desc Send Gmail invite to email
|
|
1115
|
+
#
|
|
1116
|
+
def invite(email)
|
|
1117
|
+
|
|
1118
|
+
if connected?
|
|
1119
|
+
|
|
1120
|
+
postdata = "act=ii&em=" + URI.escape(email)
|
|
1121
|
+
|
|
1122
|
+
cc = @cookie_str.split(';')
|
|
1123
|
+
cc.each {|cc_part|
|
|
1124
|
+
cc_parts = cc_part.split('=')
|
|
1125
|
+
if(cc_parts[0]=='GMAIL_AT')
|
|
1126
|
+
postdata += "&at=" + cc_parts[1]
|
|
1127
|
+
break
|
|
1128
|
+
end
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
link = GM_LNK_GMAIL + "?view=ii"
|
|
1132
|
+
|
|
1133
|
+
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
1134
|
+
np.use_ssl = true
|
|
1135
|
+
np.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
1136
|
+
# np.set_debug_output($stderr)
|
|
1137
|
+
np.start { |http|
|
|
1138
|
+
response = http.post(link, postdata,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT} )
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
true
|
|
1142
|
+
else
|
|
1143
|
+
false
|
|
1144
|
+
end
|
|
1145
|
+
|
|
1146
|
+
end
|
|
1147
|
+
|
|
1148
|
+
#
|
|
1149
|
+
# return string[]
|
|
1150
|
+
# desc (Static) Get names of standard boxes.
|
|
1151
|
+
#
|
|
1152
|
+
def standard_box()
|
|
1153
|
+
["Inbox","Starred","Sent","Drafts","All","Spam","Trash"]
|
|
1154
|
+
end
|
|
1155
|
+
|
|
1156
|
+
#
|
|
1157
|
+
# return string
|
|
1158
|
+
# param string header
|
|
1159
|
+
# desc (Static Private) Extract cookies from header.
|
|
1160
|
+
#
|
|
1161
|
+
def __cookies(header)
|
|
1162
|
+
return '' unless header
|
|
1163
|
+
arr = []
|
|
1164
|
+
header.split(', ').each { |x|
|
|
1165
|
+
if x.include?('GMT')
|
|
1166
|
+
arr[-1] += ", " + x
|
|
1167
|
+
else
|
|
1168
|
+
arr.push x
|
|
1169
|
+
end
|
|
1170
|
+
}
|
|
1171
|
+
arr.delete_if {|x| x.include?('LSID=EXPIRED') }
|
|
1172
|
+
arr.map! {|x| x.split(';')[0]}
|
|
1173
|
+
arr.join(';')
|
|
1174
|
+
end
|
|
1175
|
+
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
class GMailSnapshot
|
|
1180
|
+
|
|
1181
|
+
GM_STANDARD = 0x001
|
|
1182
|
+
GM_LABEL = 0x002
|
|
1183
|
+
GM_CONVERSATION = 0x004
|
|
1184
|
+
GM_QUERY = 0x008
|
|
1185
|
+
GM_CONTACT = 0x010
|
|
1186
|
+
GM_PREFERENCE = 0x020
|
|
1187
|
+
|
|
1188
|
+
def decode(str)
|
|
1189
|
+
return str if @charset.upcase == 'UTF-8'
|
|
1190
|
+
begin
|
|
1191
|
+
require 'Win32API'
|
|
1192
|
+
str = str.unpack("U*").pack("S*") + "\0"
|
|
1193
|
+
ostr = "\0" * str.length*2
|
|
1194
|
+
wideCharToMultiByte = Win32API.new('kernel32','WideCharToMultiByte',['L','L','P','L','P','L','L','L'],'L')
|
|
1195
|
+
wideCharToMultiByte.Call(0,0,str,-1,ostr,str.length*2,0,0)
|
|
1196
|
+
ostr.strip
|
|
1197
|
+
rescue LoadError
|
|
1198
|
+
require 'iconv'
|
|
1199
|
+
Iconv::iconv(@charset,'UTF-8',str)[0]
|
|
1200
|
+
end
|
|
1201
|
+
end
|
|
1202
|
+
|
|
1203
|
+
def strip_tags(str,allowable_tags='')
|
|
1204
|
+
str.gsub(/<[^>]*>/, '')
|
|
1205
|
+
end
|
|
1206
|
+
|
|
1207
|
+
#
|
|
1208
|
+
# return GMailSnapshot
|
|
1209
|
+
# param constant type
|
|
1210
|
+
# param array raw
|
|
1211
|
+
# desc Constructor.
|
|
1212
|
+
#
|
|
1213
|
+
attr_reader :gmail_ver, :quota_mb, :quota_per, :preference
|
|
1214
|
+
attr_reader :std_box_new, :have_invit, :label_list, :label_new
|
|
1215
|
+
attr_reader :message_list
|
|
1216
|
+
attr_reader :message
|
|
1217
|
+
attr_reader :contacts, :other_emails
|
|
1218
|
+
|
|
1219
|
+
def initialize(type, raw, charset='UTF-8')
|
|
1220
|
+
@charset = charset
|
|
1221
|
+
if (raw.class!=Hash)
|
|
1222
|
+
@created = 0
|
|
1223
|
+
return nil
|
|
1224
|
+
elsif (raw.empty?)
|
|
1225
|
+
@created = 0
|
|
1226
|
+
return nil
|
|
1227
|
+
end
|
|
1228
|
+
if [GM_STANDARD,GM_LABEL,GM_CONVERSATION,GM_QUERY].include?(type)
|
|
1229
|
+
@gmail_ver = raw["v"][1]
|
|
1230
|
+
if raw["qu"]
|
|
1231
|
+
@quota_mb = raw["qu"][1]
|
|
1232
|
+
@quota_per = raw["qu"][3]
|
|
1233
|
+
end
|
|
1234
|
+
if (raw["ds"].class!=Array)
|
|
1235
|
+
@created = 0
|
|
1236
|
+
return nil
|
|
1237
|
+
end
|
|
1238
|
+
@std_box_new = raw["ds"][1..-1]
|
|
1239
|
+
#if (isset(raw["p"])) {
|
|
1240
|
+
# @owner = raw["p"][5][1]
|
|
1241
|
+
# @owner_email = raw["p"][6][1]
|
|
1242
|
+
#end
|
|
1243
|
+
@have_invit = raw["i"][1]
|
|
1244
|
+
@label_list = []
|
|
1245
|
+
@label_new = []
|
|
1246
|
+
raw["ct"][1].each {|v|
|
|
1247
|
+
@label_list.push(v[0])
|
|
1248
|
+
@label_new.push(v[1])
|
|
1249
|
+
}
|
|
1250
|
+
if raw["ts"]
|
|
1251
|
+
@view = (GM_STANDARD|GM_LABEL|GM_QUERY)
|
|
1252
|
+
@message_list = MessageList.new(raw["ts"][5],raw["ts"][3],raw["ts"][1])
|
|
1253
|
+
end
|
|
1254
|
+
@box = []
|
|
1255
|
+
if raw["t"]
|
|
1256
|
+
raw["t"].each {|t|
|
|
1257
|
+
if (t != "t")
|
|
1258
|
+
b = {
|
|
1259
|
+
"id"=>t[0],
|
|
1260
|
+
"is_read"=>(t[1] != 1 ? 1 : 0),
|
|
1261
|
+
"read?"=>(t[1] != 1),
|
|
1262
|
+
"new?"=>(t[1] == 1),
|
|
1263
|
+
"is_starred"=>(t[2] == 1 ? 1 : 0),
|
|
1264
|
+
"star?"=>(t[2] == 1),
|
|
1265
|
+
"date"=>decode(strip_tags(t[3])),
|
|
1266
|
+
"sender"=>decode(strip_tags(t[4])),
|
|
1267
|
+
"flag"=>t[5],
|
|
1268
|
+
"subject"=>decode(strip_tags(t[6])),
|
|
1269
|
+
"snippet"=>decode(t[7].gsub('"','"').gsub('…','...')),
|
|
1270
|
+
"labels"=>t[8].empty? ? [] : t[8].map{|tt|decode(tt)},
|
|
1271
|
+
"attachment"=>t[9].empty? ? []: decode(t[9]).split(","),
|
|
1272
|
+
"msgid"=>t[10]
|
|
1273
|
+
}
|
|
1274
|
+
@box.push(b)
|
|
1275
|
+
end
|
|
1276
|
+
}
|
|
1277
|
+
end
|
|
1278
|
+
|
|
1279
|
+
if (!raw["cs"].nil?)
|
|
1280
|
+
@view = GM_CONVERSATION
|
|
1281
|
+
@conv_title = raw["cs"][2]
|
|
1282
|
+
@conv_total = raw["cs"][8]
|
|
1283
|
+
@conv_id = raw["cs"][1]
|
|
1284
|
+
@conv_labels = raw["cs"][5].empty? ? '' : raw["cs"][5]
|
|
1285
|
+
if !@conv_labels.empty?
|
|
1286
|
+
ij = @conv_labels.index("^i")
|
|
1287
|
+
if !ij.nil?
|
|
1288
|
+
@conv_labels[ij] = "Inbox"
|
|
1289
|
+
end
|
|
1290
|
+
ij = @conv_labels.index("^s")
|
|
1291
|
+
if !ij.nil?
|
|
1292
|
+
@conv_labels[ij] = "Spam"
|
|
1293
|
+
end
|
|
1294
|
+
ij = @conv_labels.index("^k")
|
|
1295
|
+
if !ij.nil?
|
|
1296
|
+
@conv_labels[ij] = "Trash"
|
|
1297
|
+
end
|
|
1298
|
+
ij = @conv_labels.index("^t")
|
|
1299
|
+
if !ij.nil?
|
|
1300
|
+
@conv_labels[ij] = '' # Starred
|
|
1301
|
+
end
|
|
1302
|
+
ij = @conv_labels.index("^r")
|
|
1303
|
+
if !ij.nil?
|
|
1304
|
+
@conv_labels[ij] = "Drafts"
|
|
1305
|
+
end
|
|
1306
|
+
end
|
|
1307
|
+
|
|
1308
|
+
@conv_starred = false
|
|
1309
|
+
|
|
1310
|
+
@conv = []
|
|
1311
|
+
b = {}
|
|
1312
|
+
raw["mg"].each {|r|
|
|
1313
|
+
if (r[0] == "mb")
|
|
1314
|
+
b["body"] = '' if b["body"].nil?
|
|
1315
|
+
b["body"] += r[1]
|
|
1316
|
+
if (r[2] == 0)
|
|
1317
|
+
b["body"] = decode(b["body"])
|
|
1318
|
+
@conv.push(b)
|
|
1319
|
+
b = {}
|
|
1320
|
+
end
|
|
1321
|
+
elsif (r[0] == "mi")
|
|
1322
|
+
if !b.empty?
|
|
1323
|
+
@conv.push(b)
|
|
1324
|
+
b = {}
|
|
1325
|
+
end
|
|
1326
|
+
b = {}
|
|
1327
|
+
b["index"] = r[2]
|
|
1328
|
+
b["id"] = r[3]
|
|
1329
|
+
b["is_star"] = r[4]
|
|
1330
|
+
if (b["is_star"] == 1)
|
|
1331
|
+
@conv_starred = true
|
|
1332
|
+
end
|
|
1333
|
+
b["sender"] = decode(r[6])
|
|
1334
|
+
b["sender_email"] = r[8].gsub("\"",'') # remove annoying d-quotes in address
|
|
1335
|
+
b["recv"] = r[9]
|
|
1336
|
+
b["recv_email"] = r[11].to_s.gsub("\"",'')
|
|
1337
|
+
b["reply_email"] = r[14].to_s.gsub("\"",'')
|
|
1338
|
+
b["dt_easy"] = r[10]
|
|
1339
|
+
b["dt"] = r[15]
|
|
1340
|
+
b["subject"] = decode(r[16])
|
|
1341
|
+
b["snippet"] = decode(r[17])
|
|
1342
|
+
b["attachment"] = []
|
|
1343
|
+
r[18].each {|bb|
|
|
1344
|
+
b["attachment"].push({"id"=>bb[0],"filename"=>bb[1],"type"=>bb[2],"size"=>bb[3]})
|
|
1345
|
+
}
|
|
1346
|
+
b["is_draft"] = false
|
|
1347
|
+
b["body"] = ''
|
|
1348
|
+
elsif (r[0] == "di")
|
|
1349
|
+
if !b.empty?
|
|
1350
|
+
@conv.push(b)
|
|
1351
|
+
b = {}
|
|
1352
|
+
end
|
|
1353
|
+
b = {}
|
|
1354
|
+
b["index"] = r[2]
|
|
1355
|
+
b["id"] = r[3]
|
|
1356
|
+
b["is_star"] = r[4]
|
|
1357
|
+
@conv_starred = (b["is_star"] == 1)
|
|
1358
|
+
b["sender"] = decode(r[6])
|
|
1359
|
+
b["sender_email"] = r[8].gsub("\"",'') # remove annoying d-quotes in address
|
|
1360
|
+
b["recv"] = r[9]
|
|
1361
|
+
b["recv_email"] = r[11].gsub("\"",'')
|
|
1362
|
+
b["reply_email"] = r[14].gsub("\"",'')
|
|
1363
|
+
b["cc_email"] = r[12].gsub("\"",'')
|
|
1364
|
+
b["bcc_email"] = r[13].gsub("\"",'')
|
|
1365
|
+
b["dt_easy"] = r[10]
|
|
1366
|
+
b["dt"] = r[15]
|
|
1367
|
+
b["subject"] = decode(r[16])
|
|
1368
|
+
b["snippet"] = decode(r[17])
|
|
1369
|
+
b["attachment"] = []
|
|
1370
|
+
r[18].each {|bb|
|
|
1371
|
+
b["attachment"].push({"id"=>bb[0],"filename"=>bb[1],"type"=>bb[2],"size"=>bb[3]})
|
|
1372
|
+
}
|
|
1373
|
+
b["is_draft"] = true
|
|
1374
|
+
b["draft_parent"] = r[5]
|
|
1375
|
+
b["body"] = decode(r[20])
|
|
1376
|
+
end
|
|
1377
|
+
}
|
|
1378
|
+
@conv.push(b) unless b.empty?
|
|
1379
|
+
@message = Message.new(@conv_tile,@conv_total,@conv_id,@conv_labels,@conv_starred)
|
|
1380
|
+
@message.conv = @conv
|
|
1381
|
+
end
|
|
1382
|
+
elsif type == GM_CONTACT
|
|
1383
|
+
@contacts = []
|
|
1384
|
+
if raw["ce"]
|
|
1385
|
+
raw["ce"].each {|a|
|
|
1386
|
+
b = {
|
|
1387
|
+
"name"=>a[2],
|
|
1388
|
+
"email"=>a[4].gsub("\"",'')
|
|
1389
|
+
}
|
|
1390
|
+
if !a[5].empty?
|
|
1391
|
+
b["notes"] = a[5]
|
|
1392
|
+
end
|
|
1393
|
+
@contacts.push(b)
|
|
1394
|
+
}
|
|
1395
|
+
end
|
|
1396
|
+
@view = GM_CONTACT
|
|
1397
|
+
elsif type == GM_PREFERENCE
|
|
1398
|
+
prefs = {}
|
|
1399
|
+
raw["p"].each_with_index { |v,i|
|
|
1400
|
+
prefs[v[0]] = v[1] if i>0
|
|
1401
|
+
}
|
|
1402
|
+
@preference = {'max_page_size'=>'10',
|
|
1403
|
+
'keyboard_shortcuts'=>false,
|
|
1404
|
+
'indicators'=>false,
|
|
1405
|
+
'display_language'=>'en',
|
|
1406
|
+
'signature'=>'',
|
|
1407
|
+
'reply_to'=>'',
|
|
1408
|
+
'snippets'=>false,
|
|
1409
|
+
'display_name'=>'',
|
|
1410
|
+
}
|
|
1411
|
+
prefs.each do |k,v|
|
|
1412
|
+
case k
|
|
1413
|
+
when 'ix_nt'
|
|
1414
|
+
@preference['max_page_size'] = v
|
|
1415
|
+
when 'bx_hs'
|
|
1416
|
+
@preference['keyboard_shortcuts'] = (v == '1')
|
|
1417
|
+
when 'bx_sc'
|
|
1418
|
+
@preference['indicators'] = (v == '1')
|
|
1419
|
+
when 'sx_dl'
|
|
1420
|
+
@preference['display_language'] = v
|
|
1421
|
+
when 'sx_sg'
|
|
1422
|
+
@preference['signature'] = (v == '0') ? '' : v
|
|
1423
|
+
when 'sx_rt'
|
|
1424
|
+
@preference['reply_to'] = v
|
|
1425
|
+
when 'bx_ns'
|
|
1426
|
+
@preference['snippets'] = (v == '0')
|
|
1427
|
+
when 'sx_dn'
|
|
1428
|
+
@preference['display_name'] = v
|
|
1429
|
+
end
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
@label_list = []
|
|
1433
|
+
@label_total = []
|
|
1434
|
+
raw["cta"][1].each { |v|
|
|
1435
|
+
@label_list.push(v[0])
|
|
1436
|
+
@label_total.push(v[1])
|
|
1437
|
+
}
|
|
1438
|
+
@other_emails = []
|
|
1439
|
+
if raw["cfs"]
|
|
1440
|
+
raw["cfs"][1].each {|v|
|
|
1441
|
+
@other_emails.push({"name"=>decode(v[0]),"email"=>v[1],"default"=>(v[2]==1)})
|
|
1442
|
+
}
|
|
1443
|
+
end
|
|
1444
|
+
@filter = []
|
|
1445
|
+
@filter_rules = []
|
|
1446
|
+
raw["fi"][1].each { |fi|
|
|
1447
|
+
b = {
|
|
1448
|
+
"id" => fi[0],
|
|
1449
|
+
"query" => fi[1],
|
|
1450
|
+
"star" => fi[3],
|
|
1451
|
+
"label" => fi[4],
|
|
1452
|
+
"archive" => fi[5],
|
|
1453
|
+
"trash" => fi[6] #,"forward" => fi[7]
|
|
1454
|
+
}
|
|
1455
|
+
bb = {
|
|
1456
|
+
"from" => fi[2][0],
|
|
1457
|
+
"to" => fi[2][1],
|
|
1458
|
+
"subject" => fi[2][2],
|
|
1459
|
+
"has" => fi[2][3],
|
|
1460
|
+
"hasnot" => fi[2][4],
|
|
1461
|
+
"attach" => fi[2][5]
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
@filter.push(b)
|
|
1465
|
+
@filter_rules.push(bb)
|
|
1466
|
+
}
|
|
1467
|
+
@view = GM_PREFERENCE
|
|
1468
|
+
else
|
|
1469
|
+
@created = 0
|
|
1470
|
+
return nil
|
|
1471
|
+
end
|
|
1472
|
+
@message_list.box = @box if @message_list
|
|
1473
|
+
|
|
1474
|
+
@created = 1
|
|
1475
|
+
end
|
|
1476
|
+
|
|
1477
|
+
end
|
|
1478
|
+
|
|
1479
|
+
# a list of messages.
|
|
1480
|
+
class MessageList
|
|
1481
|
+
attr_reader :name, :total, :pos
|
|
1482
|
+
attr_accessor :box, :connection
|
|
1483
|
+
def initialize(name,total,pos)
|
|
1484
|
+
@name = name
|
|
1485
|
+
@total = total
|
|
1486
|
+
@pos = pos
|
|
1487
|
+
end
|
|
1488
|
+
|
|
1489
|
+
def each(&block)
|
|
1490
|
+
@box.each do |b|
|
|
1491
|
+
m = connection.fetch(:conversation=>b['id']).message
|
|
1492
|
+
m.connection = @connection
|
|
1493
|
+
block.call(m)
|
|
1494
|
+
end
|
|
1495
|
+
end
|
|
1496
|
+
|
|
1497
|
+
def map(&block)
|
|
1498
|
+
@box.map do |b|
|
|
1499
|
+
m = connection.fetch(:conversation=>b['id']).message
|
|
1500
|
+
m.connection = @connection
|
|
1501
|
+
block.call(m)
|
|
1502
|
+
end
|
|
1503
|
+
end
|
|
1504
|
+
|
|
1505
|
+
end
|
|
1506
|
+
|
|
1507
|
+
# a single message
|
|
1508
|
+
class Message
|
|
1509
|
+
attr_reader :title, :total, :id, :labels, :starred
|
|
1510
|
+
attr_accessor :conv, :connection
|
|
1511
|
+
def initialize(title,total,id,labels,starred)
|
|
1512
|
+
@title = title
|
|
1513
|
+
@total = total
|
|
1514
|
+
@id = id
|
|
1515
|
+
@labels = labels
|
|
1516
|
+
@starred = starred
|
|
1517
|
+
end
|
|
1518
|
+
|
|
1519
|
+
def method_missing(methId)
|
|
1520
|
+
str = methId.id2name
|
|
1521
|
+
@conv[0][str]
|
|
1522
|
+
end
|
|
1523
|
+
|
|
1524
|
+
#
|
|
1525
|
+
# return boolean
|
|
1526
|
+
# param string label
|
|
1527
|
+
# desc apply label to message
|
|
1528
|
+
#
|
|
1529
|
+
def apply_label(label)
|
|
1530
|
+
@connection.perform_action(GM_ACT_APPLYLABEL, @id, label)
|
|
1531
|
+
end
|
|
1532
|
+
|
|
1533
|
+
#
|
|
1534
|
+
# return boolean
|
|
1535
|
+
# param string label
|
|
1536
|
+
# desc remove label from message
|
|
1537
|
+
#
|
|
1538
|
+
def remove_label(label)
|
|
1539
|
+
@connection.perform_action(GM_ACT_REMOVELABEL, @id, label)
|
|
1540
|
+
end
|
|
1541
|
+
|
|
1542
|
+
#
|
|
1543
|
+
# return boolean
|
|
1544
|
+
# desc apply star to a message
|
|
1545
|
+
#
|
|
1546
|
+
def apply_star()
|
|
1547
|
+
@connection.perform_action(GM_ACT_STAR,@id, '')
|
|
1548
|
+
end
|
|
1549
|
+
|
|
1550
|
+
#
|
|
1551
|
+
# return boolean
|
|
1552
|
+
# param string msgid
|
|
1553
|
+
# desc remove star from a message
|
|
1554
|
+
#
|
|
1555
|
+
def remove_star()
|
|
1556
|
+
@connection.perform_action(GM_ACT_UNSTAR,@id, '')
|
|
1557
|
+
end
|
|
1558
|
+
|
|
1559
|
+
#
|
|
1560
|
+
# return boolean
|
|
1561
|
+
# desc archive a message
|
|
1562
|
+
#
|
|
1563
|
+
def archive()
|
|
1564
|
+
@connection.perform_action(GM_ACT_ARCHIVE,@id, '')
|
|
1565
|
+
end
|
|
1566
|
+
|
|
1567
|
+
#
|
|
1568
|
+
# return boolean
|
|
1569
|
+
# param string msgid
|
|
1570
|
+
# desc archive a message
|
|
1571
|
+
#
|
|
1572
|
+
def unarchive()
|
|
1573
|
+
@connection.perform_action(GM_ACT_INBOX,@id, '')
|
|
1574
|
+
end
|
|
1575
|
+
|
|
1576
|
+
def archived?()
|
|
1577
|
+
end
|
|
1578
|
+
|
|
1579
|
+
#
|
|
1580
|
+
# return boolean
|
|
1581
|
+
# param string msgid
|
|
1582
|
+
# desc mark a message as read
|
|
1583
|
+
#
|
|
1584
|
+
def mark_read()
|
|
1585
|
+
@connection.perform_action(GM_ACT_READ,@id, '')
|
|
1586
|
+
end
|
|
1587
|
+
|
|
1588
|
+
#
|
|
1589
|
+
# return boolean
|
|
1590
|
+
# param string msgid
|
|
1591
|
+
# desc mark a message as unread
|
|
1592
|
+
#
|
|
1593
|
+
def mark_unread()
|
|
1594
|
+
@connection.perform_action(GM_ACT_UNREAD,@id, '')
|
|
1595
|
+
end
|
|
1596
|
+
|
|
1597
|
+
def read?()
|
|
1598
|
+
@conv[0]['read?']
|
|
1599
|
+
end
|
|
1600
|
+
|
|
1601
|
+
#
|
|
1602
|
+
# return boolean
|
|
1603
|
+
# param string msgid
|
|
1604
|
+
# desc report a message as spam
|
|
1605
|
+
#
|
|
1606
|
+
def report_spam()
|
|
1607
|
+
@connection.perform_action(GM_ACT_SPAM,@id, '')
|
|
1608
|
+
end
|
|
1609
|
+
|
|
1610
|
+
#
|
|
1611
|
+
# return boolean
|
|
1612
|
+
# param string msgid
|
|
1613
|
+
# desc report a message as not spam
|
|
1614
|
+
#
|
|
1615
|
+
def report_not_spam()
|
|
1616
|
+
@connection.perform_action(GM_ACT_UNSPAM,@id, '')
|
|
1617
|
+
end
|
|
1618
|
+
|
|
1619
|
+
#
|
|
1620
|
+
# return boolean
|
|
1621
|
+
# desc move a message to trash
|
|
1622
|
+
#
|
|
1623
|
+
def trash()
|
|
1624
|
+
@connection.perform_action(GM_ACT_TRASH,@id, '')
|
|
1625
|
+
end
|
|
1626
|
+
|
|
1627
|
+
#
|
|
1628
|
+
# return boolean
|
|
1629
|
+
# desc move a message from trash to inbox
|
|
1630
|
+
#
|
|
1631
|
+
def untrash()
|
|
1632
|
+
@connection.perform_action(GM_ACT_UNTRASH,@id, '')
|
|
1633
|
+
end
|
|
1634
|
+
|
|
1635
|
+
#
|
|
1636
|
+
# return boolean
|
|
1637
|
+
# desc delete a message forever
|
|
1638
|
+
#
|
|
1639
|
+
def delete()
|
|
1640
|
+
if connected?
|
|
1641
|
+
@connection.perform_action(GM_ACT_DELFOREVER,@id, '')
|
|
1642
|
+
else
|
|
1643
|
+
false
|
|
1644
|
+
end
|
|
1645
|
+
end
|
|
1646
|
+
|
|
1647
|
+
def original()
|
|
1648
|
+
@connection.fetch(:show_original=>@id)
|
|
1649
|
+
end
|
|
1650
|
+
end
|
|
212
1651
|
|
|
213
1652
|
# Singleton method
|
|
214
1653
|
# return bool
|
|
@@ -216,8 +1655,8 @@ class GMailer
|
|
|
216
1655
|
#
|
|
217
1656
|
|
|
218
1657
|
def GMailer.connect(*param)
|
|
219
|
-
g =
|
|
220
|
-
g
|
|
1658
|
+
g = Connection.new(*param)
|
|
1659
|
+
@connection = g
|
|
221
1660
|
if block_given?
|
|
222
1661
|
yield(g)
|
|
223
1662
|
g.disconnect()
|
|
@@ -226,1225 +1665,5 @@ class GMailer
|
|
|
226
1665
|
end
|
|
227
1666
|
end
|
|
228
1667
|
|
|
229
|
-
|
|
230
|
-
#
|
|
231
|
-
# return bool
|
|
232
|
-
# desc See if it is connected to GMail.
|
|
233
|
-
#
|
|
234
|
-
def connected?
|
|
235
|
-
!@cookie_str.empty?
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
#
|
|
239
|
-
# return bool
|
|
240
|
-
# param string query
|
|
241
|
-
# desc Fetch contents by URL query.
|
|
242
|
-
#
|
|
243
|
-
def __fetch(query)
|
|
244
|
-
if connected?
|
|
245
|
-
Debugger::say("Start fetching query: " + query)
|
|
246
|
-
query += "&zv=" + (rand(2000)*2147483.648).to_i.to_s
|
|
247
|
-
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
248
|
-
# np.set_debug_output($stderr)
|
|
249
|
-
inbox = ''
|
|
250
|
-
np.start { |http|
|
|
251
|
-
response = http.get(GM_LNK_GMAIL + "?" + query,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT })
|
|
252
|
-
inbox = response.body
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
inbox = inbox.gsub("\n",'').gsub("D([","\nD([").gsub("])","])\n")
|
|
256
|
-
|
|
257
|
-
matches = inbox.scan(/D\((.*)\)/).flatten
|
|
258
|
-
packets = {}
|
|
259
|
-
matches.each {|x|
|
|
260
|
-
tmp = eval(x.gsub(",,",",'',").gsub(",,",",'',"))
|
|
261
|
-
if (packets[tmp[0]] || (tmp[0]=="mi"||tmp[0]=="mb"||tmp[0]=="di"))
|
|
262
|
-
if (tmp[0]=="t"||tmp[0]=="ts"||tmp[0]=="a"||tmp[0]=="cl")
|
|
263
|
-
packets[tmp[0]] += tmp[1..-1]
|
|
264
|
-
end
|
|
265
|
-
if (tmp[0]=="mi"||tmp[0]=="mb"||tmp[0]=="di")
|
|
266
|
-
if !packets["mg"].nil?
|
|
267
|
-
packets["mg"].push(tmp)
|
|
268
|
-
else
|
|
269
|
-
packets["mg"] = [tmp]
|
|
270
|
-
end
|
|
271
|
-
end
|
|
272
|
-
else
|
|
273
|
-
packets[tmp[0]] = tmp
|
|
274
|
-
end
|
|
275
|
-
}
|
|
276
|
-
if packets["cl"] && packets["cl"].length > 1
|
|
277
|
-
packets["ce"] = []
|
|
278
|
-
for i in 1 .. packets["cl"].length-1
|
|
279
|
-
packets["ce"].push(packets["cl"][i])
|
|
280
|
-
end
|
|
281
|
-
end
|
|
282
|
-
@raw = packets
|
|
283
|
-
|
|
284
|
-
Debugger::say("Fetch completed.")
|
|
285
|
-
true
|
|
286
|
-
else # not logged in yet
|
|
287
|
-
Debugger::say("Fetch failed: not connected.")
|
|
288
|
-
false
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
private :__fetch
|
|
292
|
-
|
|
293
|
-
#
|
|
294
|
-
# return bool
|
|
295
|
-
# param constant type
|
|
296
|
-
# param mixed box
|
|
297
|
-
# param int pos
|
|
298
|
-
# desc Fetch contents from GMail by type.
|
|
299
|
-
#
|
|
300
|
-
def fetch_box(type, box, pos)
|
|
301
|
-
|
|
302
|
-
if connected?
|
|
303
|
-
case type
|
|
304
|
-
when GM_STANDARD
|
|
305
|
-
q = "search=" + box.downcase + "&view=tl&start=" + pos.to_s
|
|
306
|
-
|
|
307
|
-
when GM_LABEL
|
|
308
|
-
q = "search=cat&cat=" + box.to_s + "&view=tl&start=" + pos.to_s
|
|
309
|
-
|
|
310
|
-
when GM_CONVERSATION
|
|
311
|
-
q = "search=inbox&ser=1&view=cv"
|
|
312
|
-
if (box.class==Array)
|
|
313
|
-
q += "&th=" + box[0].to_s
|
|
314
|
-
for i in 1 .. box.length
|
|
315
|
-
q += "&msgs=" + box[i].to_s
|
|
316
|
-
end
|
|
317
|
-
else
|
|
318
|
-
q += "&th=" + box.to_s
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
when GM_QUERY
|
|
322
|
-
q = "search=query&q=" + URI.escape(box.to_s) + "&view=tl&start=" + pos.to_s
|
|
323
|
-
|
|
324
|
-
when GM_PREFERENCE
|
|
325
|
-
q = "view=pr&pnl=g"
|
|
326
|
-
|
|
327
|
-
when GM_CONTACT
|
|
328
|
-
if box.downcase == "all"
|
|
329
|
-
q = "view=cl&search=contacts&pnl=a"
|
|
330
|
-
else
|
|
331
|
-
q = "view=cl&search=contacts&pnl=d"
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
else
|
|
335
|
-
q = "search=inbox&view=tl&start=0&init=1"
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
__fetch(q)
|
|
339
|
-
else
|
|
340
|
-
false
|
|
341
|
-
end
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
#
|
|
345
|
-
# return snapshot
|
|
346
|
-
# param constant type
|
|
347
|
-
# param mixed box
|
|
348
|
-
# param int pos
|
|
349
|
-
# desc Fetch contents from GMail by type.
|
|
350
|
-
#
|
|
351
|
-
def fetch(hash_param)
|
|
352
|
-
type = GM_STANDARD
|
|
353
|
-
box = "inbox"
|
|
354
|
-
pos = 0
|
|
355
|
-
hash_param.keys.each do |k|
|
|
356
|
-
case k
|
|
357
|
-
when :label
|
|
358
|
-
type = GM_LABEL
|
|
359
|
-
box = hash_param[k]
|
|
360
|
-
when :standard
|
|
361
|
-
type = GM_STANDARD
|
|
362
|
-
box = hash_param[k]
|
|
363
|
-
when :conversation
|
|
364
|
-
type = GM_CONVERSATION
|
|
365
|
-
box = hash_param[k]
|
|
366
|
-
when :preference
|
|
367
|
-
type = GM_PREFERENCE
|
|
368
|
-
box = hash_param[k]
|
|
369
|
-
when :contact
|
|
370
|
-
type = GM_CONTACT
|
|
371
|
-
box = hash_param[k]
|
|
372
|
-
when :query
|
|
373
|
-
type = GM_QUERY
|
|
374
|
-
box = hash_param[k]
|
|
375
|
-
when :pos
|
|
376
|
-
pos = hash_param[k].to_i
|
|
377
|
-
else
|
|
378
|
-
raise ArgumentError, 'Invalid hash argument'
|
|
379
|
-
end
|
|
380
|
-
end
|
|
381
|
-
box = "inbox" unless box
|
|
382
|
-
fetch_box(type,box,pos)
|
|
383
|
-
snapshot = snapshot(type)
|
|
384
|
-
if block_given?
|
|
385
|
-
yield(snapshot)
|
|
386
|
-
elsif type == GM_CONTACT
|
|
387
|
-
snapshot.contacts
|
|
388
|
-
else
|
|
389
|
-
snapshot
|
|
390
|
-
end
|
|
391
|
-
end
|
|
392
|
-
|
|
393
|
-
#
|
|
394
|
-
# return string[]
|
|
395
|
-
# param string[] convs
|
|
396
|
-
# param string path
|
|
397
|
-
# desc Save all attaching files of conversations to a path.
|
|
398
|
-
#
|
|
399
|
-
def attachments_of(convs, path)
|
|
400
|
-
|
|
401
|
-
if connected?
|
|
402
|
-
if (convs.class != Array)
|
|
403
|
-
convs = [convs] # array wrapper
|
|
404
|
-
end
|
|
405
|
-
final = []
|
|
406
|
-
convs.each { |v|
|
|
407
|
-
if v["attachment"]
|
|
408
|
-
v["attachment"].each { |vv|
|
|
409
|
-
f = path+"/"+vv["filename"]
|
|
410
|
-
f = path+"/"+vv["filename"]+"."+rand(2000).to_s while (FileTest.exist?(f))
|
|
411
|
-
if attachment(vv["id"],v["id"],f,false)
|
|
412
|
-
final.push(f)
|
|
413
|
-
end
|
|
414
|
-
}
|
|
415
|
-
end
|
|
416
|
-
}
|
|
417
|
-
final
|
|
418
|
-
else
|
|
419
|
-
nil
|
|
420
|
-
end
|
|
421
|
-
end
|
|
422
|
-
|
|
423
|
-
#
|
|
424
|
-
# return string[]
|
|
425
|
-
# param string[] convs
|
|
426
|
-
# param string path
|
|
427
|
-
# desc Save all attaching files of conversations to a path.
|
|
428
|
-
#
|
|
429
|
-
def zip_attachments_of(convs, path)
|
|
430
|
-
|
|
431
|
-
if connected?
|
|
432
|
-
if (convs.class != Array)
|
|
433
|
-
convs = [convs] # array wrapper
|
|
434
|
-
end
|
|
435
|
-
final = []
|
|
436
|
-
convs.each {|v|
|
|
437
|
-
if v["attachment"]
|
|
438
|
-
f = path+"/attachment.zip"
|
|
439
|
-
f = path+"/attachment."+rand(2000).to_s+".zip" while (FileTest.exist?(f))
|
|
440
|
-
if attachment(v["attachment"][0]["id"],v["id"],f,true)
|
|
441
|
-
final.push(f)
|
|
442
|
-
end
|
|
443
|
-
end
|
|
444
|
-
}
|
|
445
|
-
final
|
|
446
|
-
else
|
|
447
|
-
nil
|
|
448
|
-
end
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
#
|
|
452
|
-
# return bool
|
|
453
|
-
# param string attid
|
|
454
|
-
# param string msgid
|
|
455
|
-
# param string filename
|
|
456
|
-
# desc Save attachment with attachment ID attid and message ID msgid to file with name filename.
|
|
457
|
-
#
|
|
458
|
-
def attachment(attid, msgid, filename, zipped=false)
|
|
459
|
-
|
|
460
|
-
if connected?
|
|
461
|
-
Debugger::say("Start getting attachment...")
|
|
462
|
-
|
|
463
|
-
if !zipped
|
|
464
|
-
query = GM_LNK_ATTACHMENT + "&attid=" + URI.escape(attid) + "&th=" + URI.escape(msgid)
|
|
465
|
-
else
|
|
466
|
-
query = GM_LNK_ATTACHMENT_ZIPPED + "&th=" + URI.escape(msgid)
|
|
467
|
-
end
|
|
468
|
-
|
|
469
|
-
File.open(filename,"wb") { |f|
|
|
470
|
-
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
471
|
-
np.start { |http|
|
|
472
|
-
response = http.get(query,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT })
|
|
473
|
-
f.write(response.body)
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
Debugger::say("Completed getting attachment.")
|
|
477
|
-
true
|
|
478
|
-
else
|
|
479
|
-
Debugger::say("Failed to get attachment: not connected.")
|
|
480
|
-
false
|
|
481
|
-
end
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
#
|
|
485
|
-
# return array of labels
|
|
486
|
-
# desc get label lists
|
|
487
|
-
#
|
|
488
|
-
def labels()
|
|
489
|
-
if connected?
|
|
490
|
-
fetch(:standard=>"inbox") {|s| s.label_list }
|
|
491
|
-
else
|
|
492
|
-
nil
|
|
493
|
-
end
|
|
494
|
-
end
|
|
495
|
-
|
|
496
|
-
#
|
|
497
|
-
# return string
|
|
498
|
-
# param string label
|
|
499
|
-
# desc validate label
|
|
500
|
-
#
|
|
501
|
-
def validate_label(label)
|
|
502
|
-
label.strip!
|
|
503
|
-
if label==''
|
|
504
|
-
raise ArgumentError, 'Error: Labels cannot empty string'
|
|
505
|
-
end
|
|
506
|
-
if label.length > 40
|
|
507
|
-
raise ArgumentError, 'Error: Labels cannot contain more than 40 characters'
|
|
508
|
-
end
|
|
509
|
-
if label.include?('^')
|
|
510
|
-
raise ArgumentError, "Error: Labels cannot contain the character '^'"
|
|
511
|
-
end
|
|
512
|
-
label
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
#
|
|
516
|
-
# return boolean
|
|
517
|
-
# param string label
|
|
518
|
-
# desc create label
|
|
519
|
-
#
|
|
520
|
-
def create_label(label)
|
|
521
|
-
if connected?
|
|
522
|
-
perform_action(GM_ACT_CREATELABEL, '', validate_label(label))
|
|
523
|
-
else
|
|
524
|
-
false
|
|
525
|
-
end
|
|
526
|
-
end
|
|
527
|
-
|
|
528
|
-
#
|
|
529
|
-
# return boolean
|
|
530
|
-
# param string label
|
|
531
|
-
# desc create label
|
|
532
|
-
#
|
|
533
|
-
def delete_label(label)
|
|
534
|
-
if connected?
|
|
535
|
-
perform_action(GM_ACT_DELETELABEL, '', validate_label(label))
|
|
536
|
-
else
|
|
537
|
-
false
|
|
538
|
-
end
|
|
539
|
-
end
|
|
540
|
-
|
|
541
|
-
#
|
|
542
|
-
# return boolean
|
|
543
|
-
# param string old_label
|
|
544
|
-
# param string new_label
|
|
545
|
-
# desc create label
|
|
546
|
-
#
|
|
547
|
-
def rename_label(old_label,new_label)
|
|
548
|
-
if connected?
|
|
549
|
-
perform_action(GM_ACT_RENAMELABEL, '',
|
|
550
|
-
validate_label(old_label) +'^' + validate_label(new_label))
|
|
551
|
-
else
|
|
552
|
-
false
|
|
553
|
-
end
|
|
554
|
-
end
|
|
555
|
-
|
|
556
|
-
#
|
|
557
|
-
# return boolean
|
|
558
|
-
# param string msgid
|
|
559
|
-
# param string label
|
|
560
|
-
# desc apply label to message
|
|
561
|
-
#
|
|
562
|
-
def apply_label(id,label)
|
|
563
|
-
if connected?
|
|
564
|
-
perform_action(GM_ACT_APPLYLABEL, id, validate_label(label))
|
|
565
|
-
else
|
|
566
|
-
false
|
|
567
|
-
end
|
|
568
|
-
end
|
|
569
|
-
|
|
570
|
-
#
|
|
571
|
-
# return boolean
|
|
572
|
-
# param string msgid
|
|
573
|
-
# param string label
|
|
574
|
-
# desc remove label from message
|
|
575
|
-
#
|
|
576
|
-
def remove_label(id,label)
|
|
577
|
-
if connected?
|
|
578
|
-
perform_action(GM_ACT_REMOVELABEL, id, validate_label(label))
|
|
579
|
-
else
|
|
580
|
-
false
|
|
581
|
-
end
|
|
582
|
-
end
|
|
583
|
-
|
|
584
|
-
#
|
|
585
|
-
# return boolean
|
|
586
|
-
# param string hash_param
|
|
587
|
-
# desc remove label from message
|
|
588
|
-
#
|
|
589
|
-
def update_preference(hash_param)
|
|
590
|
-
if connected?
|
|
591
|
-
args = {}
|
|
592
|
-
hash_param.keys.each do |k|
|
|
593
|
-
case k
|
|
594
|
-
when :max_page_size
|
|
595
|
-
args['p_ix_nt'] = hash_param[k]
|
|
596
|
-
when :keyboard_shortcuts
|
|
597
|
-
args['p_bx_hs'] = hash_param[k] ? '1' : '0'
|
|
598
|
-
when :indicators
|
|
599
|
-
args['p_bx_sc'] = hash_param[k] ? '1' : '0'
|
|
600
|
-
when :display_language
|
|
601
|
-
args['p_sx_dl'] = hash_param[k]
|
|
602
|
-
when :signature
|
|
603
|
-
args['p_sx_sg'] = hash_param[k]
|
|
604
|
-
when :reply_to
|
|
605
|
-
args['p_sx_rt'] = hash_param[k]
|
|
606
|
-
when :snippets
|
|
607
|
-
args['p_bx_ns'] = hash_param[k] ? '0' : '1'
|
|
608
|
-
when :display_name
|
|
609
|
-
args['p_sx_dn'] = hash_param[k]
|
|
610
|
-
end
|
|
611
|
-
end
|
|
612
|
-
param = '&' + args.to_a.map {|x| x.join('=')}.join('&')
|
|
613
|
-
perform_action(GM_ACT_PREFERENCE,'', param)
|
|
614
|
-
else
|
|
615
|
-
false
|
|
616
|
-
end
|
|
617
|
-
end
|
|
618
|
-
|
|
619
|
-
#
|
|
620
|
-
# return boolean
|
|
621
|
-
# param string msgid
|
|
622
|
-
# desc apply star to a message
|
|
623
|
-
#
|
|
624
|
-
def apply_star(msgid)
|
|
625
|
-
if connected?
|
|
626
|
-
perform_action(GM_ACT_STAR,msgid, '')
|
|
627
|
-
else
|
|
628
|
-
false
|
|
629
|
-
end
|
|
630
|
-
end
|
|
631
|
-
|
|
632
|
-
#
|
|
633
|
-
# return boolean
|
|
634
|
-
# param string msgid
|
|
635
|
-
# desc remove star from a message
|
|
636
|
-
#
|
|
637
|
-
def remove_star(msgid)
|
|
638
|
-
if connected?
|
|
639
|
-
perform_action(GM_ACT_UNSTAR,msgid, '')
|
|
640
|
-
else
|
|
641
|
-
false
|
|
642
|
-
end
|
|
643
|
-
end
|
|
644
|
-
|
|
645
|
-
#
|
|
646
|
-
# return boolean
|
|
647
|
-
# param string msgid
|
|
648
|
-
# desc report a message as spam
|
|
649
|
-
#
|
|
650
|
-
def report_spam(msgid)
|
|
651
|
-
if connected?
|
|
652
|
-
perform_action(GM_ACT_SPAM,msgid, '')
|
|
653
|
-
else
|
|
654
|
-
false
|
|
655
|
-
end
|
|
656
|
-
end
|
|
657
|
-
|
|
658
|
-
#
|
|
659
|
-
# return boolean
|
|
660
|
-
# param string msgid
|
|
661
|
-
# desc report a message as not spam
|
|
662
|
-
#
|
|
663
|
-
def not_spam(msgid)
|
|
664
|
-
if connected?
|
|
665
|
-
perform_action(GM_ACT_UNSPAM,msgid, '')
|
|
666
|
-
else
|
|
667
|
-
false
|
|
668
|
-
end
|
|
669
|
-
end
|
|
670
|
-
|
|
671
|
-
#
|
|
672
|
-
# return boolean
|
|
673
|
-
# param string msgid
|
|
674
|
-
# desc delete a spam message forever
|
|
675
|
-
#
|
|
676
|
-
def delete_spam(msgid)
|
|
677
|
-
if connected?
|
|
678
|
-
perform_action(GM_ACT_DELSPAM,msgid, '')
|
|
679
|
-
else
|
|
680
|
-
false
|
|
681
|
-
end
|
|
682
|
-
end
|
|
683
|
-
|
|
684
|
-
#
|
|
685
|
-
# return boolean
|
|
686
|
-
# param string msgid
|
|
687
|
-
# desc mark a message as read
|
|
688
|
-
#
|
|
689
|
-
def mark_read(msgid)
|
|
690
|
-
if connected?
|
|
691
|
-
perform_action(GM_ACT_READ,msgid, '')
|
|
692
|
-
else
|
|
693
|
-
false
|
|
694
|
-
end
|
|
695
|
-
end
|
|
696
|
-
|
|
697
|
-
#
|
|
698
|
-
# return boolean
|
|
699
|
-
# param string msgid
|
|
700
|
-
# desc mark a message as unread
|
|
701
|
-
#
|
|
702
|
-
def mark_unread(msgid)
|
|
703
|
-
if connected?
|
|
704
|
-
perform_action(GM_ACT_UNREAD,msgid, '')
|
|
705
|
-
else
|
|
706
|
-
false
|
|
707
|
-
end
|
|
708
|
-
end
|
|
709
|
-
|
|
710
|
-
#
|
|
711
|
-
# return boolean
|
|
712
|
-
# param string msgid
|
|
713
|
-
# desc move a message to trash
|
|
714
|
-
#
|
|
715
|
-
def trash_in(msgid)
|
|
716
|
-
if connected?
|
|
717
|
-
perform_action(GM_ACT_TRASH,msgid, '')
|
|
718
|
-
else
|
|
719
|
-
false
|
|
720
|
-
end
|
|
721
|
-
end
|
|
722
|
-
|
|
723
|
-
#
|
|
724
|
-
# return boolean
|
|
725
|
-
# param string msgid
|
|
726
|
-
# desc move a message from trash to inbox
|
|
727
|
-
#
|
|
728
|
-
def trash_out(msgid)
|
|
729
|
-
if connected?
|
|
730
|
-
perform_action(GM_ACT_UNTRASH,msgid, '')
|
|
731
|
-
else
|
|
732
|
-
false
|
|
733
|
-
end
|
|
734
|
-
end
|
|
735
|
-
|
|
736
|
-
#
|
|
737
|
-
# return boolean
|
|
738
|
-
# param string msgid
|
|
739
|
-
# desc delete a trash message forever
|
|
740
|
-
#
|
|
741
|
-
def delete_trash(msgid)
|
|
742
|
-
if connected?
|
|
743
|
-
perform_action(GM_ACT_DELTRASH,msgid, '')
|
|
744
|
-
else
|
|
745
|
-
false
|
|
746
|
-
end
|
|
747
|
-
end
|
|
748
|
-
|
|
749
|
-
#
|
|
750
|
-
# return boolean
|
|
751
|
-
# param string msgid
|
|
752
|
-
# desc delete a message forever
|
|
753
|
-
#
|
|
754
|
-
def delete_message(msgid)
|
|
755
|
-
if connected?
|
|
756
|
-
perform_action(GM_ACT_DELFOREVER,msgid, '')
|
|
757
|
-
else
|
|
758
|
-
false
|
|
759
|
-
end
|
|
760
|
-
end
|
|
761
|
-
|
|
762
|
-
#
|
|
763
|
-
# return boolean
|
|
764
|
-
# param string msgid
|
|
765
|
-
# desc archive a message
|
|
766
|
-
#
|
|
767
|
-
def archive(msgid)
|
|
768
|
-
if connected?
|
|
769
|
-
perform_action(GM_ACT_ARCHIVE,msgid, '')
|
|
770
|
-
else
|
|
771
|
-
false
|
|
772
|
-
end
|
|
773
|
-
end
|
|
774
|
-
|
|
775
|
-
#
|
|
776
|
-
# return boolean
|
|
777
|
-
# param string msgid
|
|
778
|
-
# desc archive a message
|
|
779
|
-
#
|
|
780
|
-
def unarchive(msgid)
|
|
781
|
-
if connected?
|
|
782
|
-
perform_action(GM_ACT_INBOX,msgid, '')
|
|
783
|
-
else
|
|
784
|
-
false
|
|
785
|
-
end
|
|
786
|
-
end
|
|
787
|
-
|
|
788
|
-
#
|
|
789
|
-
# return hash of preference
|
|
790
|
-
# desc get preferences
|
|
791
|
-
#
|
|
792
|
-
def preference()
|
|
793
|
-
if connected?
|
|
794
|
-
fetch(:preference=>"all").preference
|
|
795
|
-
else
|
|
796
|
-
nil
|
|
797
|
-
end
|
|
798
|
-
end
|
|
799
|
-
|
|
800
|
-
#
|
|
801
|
-
# return array of messages
|
|
802
|
-
# desc get message lists
|
|
803
|
-
#
|
|
804
|
-
def messages(hash_param)
|
|
805
|
-
if connected?
|
|
806
|
-
fetch(hash_param) {|s| s.box }
|
|
807
|
-
else
|
|
808
|
-
nil
|
|
809
|
-
end
|
|
810
|
-
end
|
|
811
|
-
|
|
812
|
-
#
|
|
813
|
-
# return string
|
|
814
|
-
# param string query
|
|
815
|
-
# desc Dump everything to output.
|
|
816
|
-
#
|
|
817
|
-
def dump(query)
|
|
818
|
-
page = ''
|
|
819
|
-
if connected?
|
|
820
|
-
Debugger::say("Dumping...")
|
|
821
|
-
query += "&zv=" + (rand(2000)*2147483.648).to_i.to_s
|
|
822
|
-
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
823
|
-
np.start { |http|
|
|
824
|
-
response = http.get(GM_LNK_GMAIL + "?"+query,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT })
|
|
825
|
-
page = response.body
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
Debugger::say("Finished dumping " + page.length.to_s + " bytes.")
|
|
829
|
-
else # not logged in yet
|
|
830
|
-
Debugger::say("Failed to dump: not connected.")
|
|
831
|
-
end
|
|
832
|
-
page
|
|
833
|
-
end
|
|
834
|
-
|
|
835
|
-
def stripslashes(string)
|
|
836
|
-
encode(string.gsub("\\\"", "\"").gsub("\\'", "'").gsub("\\\\", "\\"))
|
|
837
|
-
end
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
#
|
|
841
|
-
# return bool
|
|
842
|
-
# param string to
|
|
843
|
-
# param string subject
|
|
844
|
-
# param string body
|
|
845
|
-
# param string cc
|
|
846
|
-
# param string bcc
|
|
847
|
-
# param string msg_id
|
|
848
|
-
# param string thread_id
|
|
849
|
-
# param string[] files
|
|
850
|
-
# desc Send GMail.
|
|
851
|
-
#
|
|
852
|
-
def send(*param)
|
|
853
|
-
if param.length==1 && param[0].class==Hash
|
|
854
|
-
param = param[0]
|
|
855
|
-
from = param[:from] || ''
|
|
856
|
-
to = param[:to] || ''
|
|
857
|
-
subject = param[:subject] || ''
|
|
858
|
-
body = param[:body] || ''
|
|
859
|
-
cc = param[:cc] || ''
|
|
860
|
-
bcc = param[:bcc] || ''
|
|
861
|
-
msg_id = param[:msg_id] || ''
|
|
862
|
-
thread_id = param[:msg_id] || ''
|
|
863
|
-
files = param[:files] || []
|
|
864
|
-
draft = param[:draft] || false
|
|
865
|
-
draft_id = param[:draft_id] || ''
|
|
866
|
-
elsif param.length==10
|
|
867
|
-
to, subject, body, cc, bcc, msg_id, thread_id, files, draft, draft_id = param
|
|
868
|
-
elsif param.length==11
|
|
869
|
-
from, to, subject, body, cc, bcc, msg_id, thread_id, files, draft, draft_id = param
|
|
870
|
-
else
|
|
871
|
-
raise ArgumentError, 'Invalid argument'
|
|
872
|
-
end
|
|
873
|
-
|
|
874
|
-
if connected?
|
|
875
|
-
Debugger::say("Starting to send mail...")
|
|
876
|
-
other_emails = fetch(:preference=>"all").other_emails
|
|
877
|
-
if other_emails.length>0
|
|
878
|
-
other_emails.each {|v|
|
|
879
|
-
from = v['email'] if from=='' && v['default']
|
|
880
|
-
}
|
|
881
|
-
from = @login + 'gmail.com' if from==''
|
|
882
|
-
else
|
|
883
|
-
from = nil
|
|
884
|
-
end
|
|
885
|
-
|
|
886
|
-
postdata = {}
|
|
887
|
-
if draft
|
|
888
|
-
postdata["view"] = "sd"
|
|
889
|
-
postdata["draft"] = draft_id
|
|
890
|
-
postdata["rm"] = msg_id
|
|
891
|
-
postdata["th"] = thread_id
|
|
892
|
-
else
|
|
893
|
-
postdata["view"] = "sm"
|
|
894
|
-
postdata["draft"] = draft_id
|
|
895
|
-
postdata["rm"] = msg_id
|
|
896
|
-
postdata["th"] = thread_id
|
|
897
|
-
end
|
|
898
|
-
postdata["msgbody"] = stripslashes(body)
|
|
899
|
-
postdata["from"] = stripslashes(from) if from
|
|
900
|
-
postdata["to"] = stripslashes(to)
|
|
901
|
-
postdata["subject"] = stripslashes(subject)
|
|
902
|
-
postdata["cc"] = stripslashes(cc)
|
|
903
|
-
postdata["bcc"] = stripslashes(bcc)
|
|
904
|
-
|
|
905
|
-
postdata["cmid"] = 1
|
|
906
|
-
postdata["ishtml"] = 0
|
|
907
|
-
|
|
908
|
-
cc = @cookie_str.split(';')
|
|
909
|
-
cc.each {|cc_part|
|
|
910
|
-
cc_parts = cc_part.split('=')
|
|
911
|
-
if(cc_parts[0]=='GMAIL_AT')
|
|
912
|
-
postdata["at"] = cc_parts[1]
|
|
913
|
-
break
|
|
914
|
-
end
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
boundary = "----#{Time.now.to_i}#{(rand(2000)*2147483.648).to_i}"
|
|
918
|
-
postdata2 = []
|
|
919
|
-
postdata.each {|k,v|
|
|
920
|
-
postdata2.push("Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n#{v}\r\n")
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
files.each_with_index {|f,i|
|
|
924
|
-
content = File.open(f,'rb') { |c| c.read }
|
|
925
|
-
postdata2.push("Content-Disposition: form-data; name=\"file#{i}\"; filename=\"#{File.basename(f)}\"\r\n" +
|
|
926
|
-
"Content-Transfer-Encoding: binary\r\n" +
|
|
927
|
-
"Content-Type: application/octet-stream\r\n\r\n" + content + "\r\n")
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
postdata = postdata2.collect { |p|
|
|
931
|
-
"--" + boundary + "\r\n" + p
|
|
932
|
-
}.join('') + "--" + boundary + "--\r\n"
|
|
933
|
-
|
|
934
|
-
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
935
|
-
response = nil
|
|
936
|
-
# np.set_debug_output($stderr)
|
|
937
|
-
np.start { |http|
|
|
938
|
-
response = http.post(GM_LNK_GMAIL, postdata,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT,'Content-type' => 'multipart/form-data; boundary=' + boundary } )
|
|
939
|
-
}
|
|
940
|
-
Debugger::say("Finished sending email.")
|
|
941
|
-
true
|
|
942
|
-
else
|
|
943
|
-
Debugger::say("Failed to send email: not connected.")
|
|
944
|
-
false
|
|
945
|
-
end
|
|
946
|
-
|
|
947
|
-
end
|
|
948
|
-
|
|
949
|
-
#
|
|
950
|
-
# return bool
|
|
951
|
-
# param constant act
|
|
952
|
-
# param string[] id
|
|
953
|
-
# param string para
|
|
954
|
-
# desc Perform action on messages.
|
|
955
|
-
#
|
|
956
|
-
def perform_action(act, id, para)
|
|
957
|
-
|
|
958
|
-
if connected?
|
|
959
|
-
Debugger::say("Start performing action...")
|
|
960
|
-
|
|
961
|
-
if (act == GM_ACT_DELFOREVER)
|
|
962
|
-
perform_action(GM_ACT_TRASH, id, 0) # trash it before
|
|
963
|
-
end
|
|
964
|
-
postdata = "act="
|
|
965
|
-
|
|
966
|
-
action_codes = ["ib", "cc_", "dc_", "nc_", "ac_", "rc_", "prefs", "st", "xst",
|
|
967
|
-
"sp", "us", "rd", "ur", "tr", "dl", "rc_^i", "ib", "ib", "dd", "dm", "dl", "dl"]
|
|
968
|
-
postdata += action_codes[act] ? action_codes[act] : action_codes[GM_ACT_INBOX]
|
|
969
|
-
if ([GM_ACT_APPLYLABEL,GM_ACT_REMOVELABEL,GM_ACT_CREATELABEL,
|
|
970
|
-
GM_ACT_DELETELABEL,GM_ACT_RENAMELABEL,GM_ACT_PREFERENCE].include?(act))
|
|
971
|
-
postdata += para.to_s
|
|
972
|
-
end
|
|
973
|
-
|
|
974
|
-
cc = @cookie_str.split(';')
|
|
975
|
-
cc.each {|cc_part|
|
|
976
|
-
cc_parts = cc_part.split('=')
|
|
977
|
-
if(cc_parts[0]=='GMAIL_AT')
|
|
978
|
-
postdata += "&at=" + cc_parts[1]
|
|
979
|
-
break
|
|
980
|
-
end
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
if (act == GM_ACT_TRASHMSG)
|
|
984
|
-
postdata += "&m=" + id.to_s
|
|
985
|
-
else
|
|
986
|
-
if id.class==Array
|
|
987
|
-
id.each {|t| postdata += "&t="+t.to_s }
|
|
988
|
-
else
|
|
989
|
-
postdata += "&t="+id.to_s
|
|
990
|
-
end
|
|
991
|
-
end
|
|
992
|
-
postdata += "&vp="
|
|
993
|
-
|
|
994
|
-
if [GM_ACT_UNTRASH,GM_ACT_DELFOREVER,GM_ACT_DELTRASH].include?(act)
|
|
995
|
-
link = GM_LNK_GMAIL+"?search=trash&view=tl&start=0"
|
|
996
|
-
elsif (act == GM_ACT_DELSPAM)
|
|
997
|
-
link = GM_LNK_GMAIL+"?search=spam&view=tl&start=0"
|
|
998
|
-
else
|
|
999
|
-
link = GM_LNK_GMAIL+"?search=query&q=&view=tl&start=0"
|
|
1000
|
-
end
|
|
1001
|
-
|
|
1002
|
-
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
1003
|
-
# np.set_debug_output($stderr)
|
|
1004
|
-
np.start { |http|
|
|
1005
|
-
response = http.post(link, postdata,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT} )
|
|
1006
|
-
result = response.body
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
Debugger::say("Finished performing action.")
|
|
1010
|
-
return true
|
|
1011
|
-
else
|
|
1012
|
-
Debugger::say("Failed to perform action: not connected.")
|
|
1013
|
-
return false
|
|
1014
|
-
end
|
|
1015
|
-
|
|
1016
|
-
end
|
|
1017
|
-
|
|
1018
|
-
#
|
|
1019
|
-
# return void
|
|
1020
|
-
# desc Disconnect from GMail.
|
|
1021
|
-
#
|
|
1022
|
-
def disconnect()
|
|
1023
|
-
Debugger::say("Start disconnecting...")
|
|
1024
|
-
|
|
1025
|
-
response = nil
|
|
1026
|
-
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
1027
|
-
# np.set_debug_output($stderr)
|
|
1028
|
-
np.start { |http|
|
|
1029
|
-
response = http.get(GM_LNK_LOGOUT,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT })
|
|
1030
|
-
}
|
|
1031
|
-
arr = URI::split(response["Location"])
|
|
1032
|
-
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(arr[2], 80)
|
|
1033
|
-
# np.set_debug_output($stderr)
|
|
1034
|
-
np.start { |http|
|
|
1035
|
-
response = http.get(arr[5]+'?'+arr[7], {'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT} )
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
Debugger::say("Logged-out from GMail.")
|
|
1039
|
-
@cookie_str = ''
|
|
1040
|
-
Debugger::say("Completed disconnecting.")
|
|
1041
|
-
end
|
|
1042
|
-
|
|
1043
|
-
#
|
|
1044
|
-
# return GMailSnapshot
|
|
1045
|
-
# param constant type
|
|
1046
|
-
# desc Get GMSnapshot by type.
|
|
1047
|
-
#
|
|
1048
|
-
def snapshot(type)
|
|
1049
|
-
if [GM_STANDARD,GM_LABEL,GM_CONVERSATION,GM_QUERY,GM_PREFERENCE,GM_CONTACT].include?(type)
|
|
1050
|
-
return GMailSnapshot.new(type, @raw, @charset)
|
|
1051
|
-
else
|
|
1052
|
-
return GMailSnapshot.new(GM_STANDARD, @raw, @charset) # assuming normal by default
|
|
1053
|
-
end
|
|
1054
|
-
end
|
|
1055
|
-
|
|
1056
|
-
def snap(type)
|
|
1057
|
-
action = GM_STANDARD
|
|
1058
|
-
case type
|
|
1059
|
-
when :standard
|
|
1060
|
-
action = GM_STANDARD
|
|
1061
|
-
when :label
|
|
1062
|
-
action = GM_LABEL
|
|
1063
|
-
when :conversation
|
|
1064
|
-
action = GM_CONVERSATION
|
|
1065
|
-
when :query
|
|
1066
|
-
action = GM_QUERY
|
|
1067
|
-
when :preference
|
|
1068
|
-
action = GM_PREFERENCE
|
|
1069
|
-
when :contact
|
|
1070
|
-
action = GM_CONTACT
|
|
1071
|
-
else
|
|
1072
|
-
raise ArgumentError, 'Invalid type'
|
|
1073
|
-
end
|
|
1074
|
-
snapshot(action)
|
|
1075
|
-
end
|
|
1076
|
-
|
|
1077
|
-
#
|
|
1078
|
-
# return bool
|
|
1079
|
-
# param string email
|
|
1080
|
-
# desc Send Gmail invite to email
|
|
1081
|
-
#
|
|
1082
|
-
def invite(email)
|
|
1083
|
-
|
|
1084
|
-
if connected?
|
|
1085
|
-
Debugger::say("Start sending invite...")
|
|
1086
|
-
|
|
1087
|
-
postdata = "act=ii&em=" + URI.escape(email)
|
|
1088
|
-
|
|
1089
|
-
cc = @cookie_str.split(';')
|
|
1090
|
-
cc.each {|cc_part|
|
|
1091
|
-
cc_parts = cc_part.split('=')
|
|
1092
|
-
if(cc_parts[0]=='GMAIL_AT')
|
|
1093
|
-
postdata += "&at=" + cc_parts[1]
|
|
1094
|
-
break
|
|
1095
|
-
end
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
link = GM_LNK_GMAIL + "?view=ii"
|
|
1099
|
-
|
|
1100
|
-
np = Net::HTTP::Proxy(@proxy_host,@proxy_port,@proxy_user,@proxy_pass).new(GM_LNK_HOST, 80)
|
|
1101
|
-
np.use_ssl = true
|
|
1102
|
-
np.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
1103
|
-
# np.set_debug_output($stderr)
|
|
1104
|
-
np.start { |http|
|
|
1105
|
-
response = http.post(link, postdata,{'Cookie' => @cookie_str,'User-agent' => GM_USER_AGENT} )
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
Debugger::say("Finished sending invite.")
|
|
1109
|
-
true
|
|
1110
|
-
else
|
|
1111
|
-
Debugger::say("Failed to send invite: not connected.")
|
|
1112
|
-
false
|
|
1113
|
-
end
|
|
1114
|
-
|
|
1115
|
-
end
|
|
1116
|
-
|
|
1117
|
-
#
|
|
1118
|
-
# return string[]
|
|
1119
|
-
# desc (Static) Get names of standard boxes.
|
|
1120
|
-
#
|
|
1121
|
-
def standard_box()
|
|
1122
|
-
["Inbox","Starred","Sent","Drafts","All","Spam","Trash"]
|
|
1123
|
-
end
|
|
1124
|
-
|
|
1125
|
-
#
|
|
1126
|
-
# return string
|
|
1127
|
-
# param string header
|
|
1128
|
-
# desc (Static Private) Extract cookies from header.
|
|
1129
|
-
#
|
|
1130
|
-
def __cookies(header)
|
|
1131
|
-
return '' unless header
|
|
1132
|
-
arr = []
|
|
1133
|
-
header.split(', ').each { |x|
|
|
1134
|
-
if x.include?('GMT')
|
|
1135
|
-
arr[-1] += ", " + x
|
|
1136
|
-
else
|
|
1137
|
-
arr.push x
|
|
1138
|
-
end
|
|
1139
|
-
}
|
|
1140
|
-
arr.delete_if {|x| x.include?('LSID=EXPIRED') }
|
|
1141
|
-
arr.map! {|x| x.split(';')[0]}
|
|
1142
|
-
arr.join(';')
|
|
1143
|
-
end
|
|
1144
|
-
|
|
1145
|
-
end
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
class GMailSnapshot
|
|
1149
|
-
|
|
1150
|
-
GM_STANDARD = 0x001
|
|
1151
|
-
GM_LABEL = 0x002
|
|
1152
|
-
GM_CONVERSATION = 0x004
|
|
1153
|
-
GM_QUERY = 0x008
|
|
1154
|
-
GM_CONTACT = 0x010
|
|
1155
|
-
GM_PREFERENCE = 0x020
|
|
1156
|
-
|
|
1157
|
-
def decode(str)
|
|
1158
|
-
return str if @charset.upcase == 'UTF-8'
|
|
1159
|
-
begin
|
|
1160
|
-
require 'Win32API'
|
|
1161
|
-
str = str.unpack("U*").pack("S*") + "\0"
|
|
1162
|
-
ostr = "\0" * 256
|
|
1163
|
-
wideCharToMultiByte = Win32API.new('kernel32','WideCharToMultiByte',['L','L','P','L','P','L','L','L'],'L')
|
|
1164
|
-
wideCharToMultiByte.Call(0,0,str,-1,ostr,256,0,0)
|
|
1165
|
-
ostr.strip
|
|
1166
|
-
rescue LoadError
|
|
1167
|
-
require 'iconv'
|
|
1168
|
-
Iconv::iconv(@charset,'UTF-8',str)[0]
|
|
1169
|
-
end
|
|
1170
|
-
end
|
|
1171
|
-
|
|
1172
|
-
def strip_tags(str,allowable_tags='')
|
|
1173
|
-
str.gsub(/<[^>]*>/, '')
|
|
1174
|
-
end
|
|
1175
|
-
|
|
1176
|
-
#
|
|
1177
|
-
# return GMailSnapshot
|
|
1178
|
-
# param constant type
|
|
1179
|
-
# param array raw
|
|
1180
|
-
# desc Constructor.
|
|
1181
|
-
#
|
|
1182
|
-
attr_reader :gmail_ver, :quota_mb, :quota_per, :preference
|
|
1183
|
-
attr_reader :std_box_new, :have_invit, :label_list, :label_new
|
|
1184
|
-
attr_reader :box_name, :box_total, :box_pos, :box
|
|
1185
|
-
attr_reader :conv_title, :conv_total, :conv_id, :conv_labels, :conv_starred, :conv
|
|
1186
|
-
attr_reader :contacts, :other_emails
|
|
1187
|
-
|
|
1188
|
-
def initialize(type, raw, charset='UTF-8')
|
|
1189
|
-
|
|
1190
|
-
@charset = charset
|
|
1191
|
-
if (raw.class!=Hash)
|
|
1192
|
-
@created = 0
|
|
1193
|
-
return nil
|
|
1194
|
-
elsif (raw.empty?)
|
|
1195
|
-
@created = 0
|
|
1196
|
-
return nil
|
|
1197
|
-
end
|
|
1198
|
-
if [GM_STANDARD,GM_LABEL,GM_CONVERSATION,GM_QUERY].include?(type)
|
|
1199
|
-
@gmail_ver = raw["v"][1]
|
|
1200
|
-
if raw["qu"]
|
|
1201
|
-
@quota_mb = raw["qu"][1]
|
|
1202
|
-
@quota_per = raw["qu"][3]
|
|
1203
|
-
end
|
|
1204
|
-
if (raw["ds"].class!=Array)
|
|
1205
|
-
@created = 0
|
|
1206
|
-
return nil
|
|
1207
|
-
end
|
|
1208
|
-
@std_box_new = raw["ds"][1..-1]
|
|
1209
|
-
#if (isset(raw["p"])) {
|
|
1210
|
-
# @owner = raw["p"][5][1]
|
|
1211
|
-
# @owner_email = raw["p"][6][1]
|
|
1212
|
-
#end
|
|
1213
|
-
@have_invit = raw["i"][1]
|
|
1214
|
-
@label_list = []
|
|
1215
|
-
@label_new = []
|
|
1216
|
-
raw["ct"][1].each {|v|
|
|
1217
|
-
@label_list.push(v[0])
|
|
1218
|
-
@label_new.push(v[1])
|
|
1219
|
-
}
|
|
1220
|
-
if raw["ts"]
|
|
1221
|
-
@view = (GM_STANDARD|GM_LABEL|GM_QUERY)
|
|
1222
|
-
@box_name = raw["ts"][5]
|
|
1223
|
-
@box_total = raw["ts"][3]
|
|
1224
|
-
@box_pos = raw["ts"][1]
|
|
1225
|
-
end
|
|
1226
|
-
@box = []
|
|
1227
|
-
if raw["t"]
|
|
1228
|
-
raw["t"].each {|t|
|
|
1229
|
-
if (t != "t")
|
|
1230
|
-
b = {
|
|
1231
|
-
"id"=>t[0],
|
|
1232
|
-
"is_read"=>(t[1] != 1 ? 1 : 0),
|
|
1233
|
-
"new?"=>(t[1] == 1),
|
|
1234
|
-
"is_starred"=>(t[2] == 1 ? 1 : 0),
|
|
1235
|
-
"star?"=>(t[2] == 1),
|
|
1236
|
-
"date"=>decode(strip_tags(t[3])),
|
|
1237
|
-
"sender"=>decode(strip_tags(t[4])),
|
|
1238
|
-
"flag"=>t[5],
|
|
1239
|
-
"subject"=>decode(strip_tags(t[6])),
|
|
1240
|
-
"snippet"=>decode(t[7].gsub('"','"').gsub('…','...')),
|
|
1241
|
-
"labels"=>t[8].empty? ? [] : t[8].map{|tt|decode(tt)},
|
|
1242
|
-
"attachment"=>t[9].empty? ? []: decode(t[9]).split(","),
|
|
1243
|
-
"msgid"=>t[10]
|
|
1244
|
-
}
|
|
1245
|
-
@box.push(b)
|
|
1246
|
-
end
|
|
1247
|
-
}
|
|
1248
|
-
end
|
|
1249
|
-
|
|
1250
|
-
if (!raw["cs"].nil?)
|
|
1251
|
-
@view = GM_CONVERSATION
|
|
1252
|
-
@conv_title = raw["cs"][2]
|
|
1253
|
-
@conv_total = raw["cs"][8]
|
|
1254
|
-
@conv_id = raw["cs"][1]
|
|
1255
|
-
@conv_labels = raw["cs"][5].empty? ? '' : raw["cs"][5]
|
|
1256
|
-
if !@conv_labels.empty?
|
|
1257
|
-
ij = @conv_labels.index("^i")
|
|
1258
|
-
if !ij.nil?
|
|
1259
|
-
@conv_labels[ij] = "Inbox"
|
|
1260
|
-
end
|
|
1261
|
-
ij = @conv_labels.index("^s")
|
|
1262
|
-
if !ij.nil?
|
|
1263
|
-
@conv_labels[ij] = "Spam"
|
|
1264
|
-
end
|
|
1265
|
-
ij = @conv_labels.index("^k")
|
|
1266
|
-
if !ij.nil?
|
|
1267
|
-
@conv_labels[ij] = "Trash"
|
|
1268
|
-
end
|
|
1269
|
-
ij = @conv_labels.index("^t")
|
|
1270
|
-
if !ij.nil?
|
|
1271
|
-
@conv_labels[ij] = '' # Starred
|
|
1272
|
-
end
|
|
1273
|
-
ij = @conv_labels.index("^r")
|
|
1274
|
-
if !ij.nil?
|
|
1275
|
-
@conv_labels[ij] = "Drafts"
|
|
1276
|
-
end
|
|
1277
|
-
end
|
|
1278
|
-
|
|
1279
|
-
@conv_starred = false
|
|
1280
|
-
|
|
1281
|
-
@conv = []
|
|
1282
|
-
b = {}
|
|
1283
|
-
raw["mg"].each {|r|
|
|
1284
|
-
if (r[0] == "mb" && !b.empty?)
|
|
1285
|
-
b["body"] += r[1]
|
|
1286
|
-
if (r[2] == 0)
|
|
1287
|
-
@conv.push(b)
|
|
1288
|
-
b = {}
|
|
1289
|
-
end
|
|
1290
|
-
elsif (r[0] == "mi")
|
|
1291
|
-
if !b.empty?
|
|
1292
|
-
@conv.push(b)
|
|
1293
|
-
b = {}
|
|
1294
|
-
end
|
|
1295
|
-
b = {}
|
|
1296
|
-
b["index"] = r[2]
|
|
1297
|
-
b["id"] = r[3]
|
|
1298
|
-
b["is_star"] = r[4]
|
|
1299
|
-
if (b["is_star"] == 1)
|
|
1300
|
-
@conv_starred = true
|
|
1301
|
-
end
|
|
1302
|
-
b["sender"] = r[6]
|
|
1303
|
-
b["sender_email"] = r[8].gsub("\"",'') # remove annoying d-quotes in address
|
|
1304
|
-
b["recv"] = r[9]
|
|
1305
|
-
b["recv_email"] = r[11].to_s.gsub("\"",'')
|
|
1306
|
-
b["reply_email"] = r[14].to_s.gsub("\"",'')
|
|
1307
|
-
b["dt_easy"] = r[10]
|
|
1308
|
-
b["dt"] = r[15]
|
|
1309
|
-
b["subject"] = r[16]
|
|
1310
|
-
b["snippet"] = r[17]
|
|
1311
|
-
b["attachment"] = []
|
|
1312
|
-
r[18].each {|bb|
|
|
1313
|
-
b["attachment"].push({"id"=>bb[0],"filename"=>bb[1],"type"=>bb[2],"size"=>bb[3]})
|
|
1314
|
-
}
|
|
1315
|
-
b["is_draft"] = false
|
|
1316
|
-
b["body"] = ''
|
|
1317
|
-
elsif (r[0] == "di")
|
|
1318
|
-
if !b.empty?
|
|
1319
|
-
@conv.push(b)
|
|
1320
|
-
b = {}
|
|
1321
|
-
end
|
|
1322
|
-
b = {}
|
|
1323
|
-
b["index"] = r[2]
|
|
1324
|
-
b["id"] = r[3]
|
|
1325
|
-
b["is_star"] = r[4]
|
|
1326
|
-
@conv_starred = (b["is_star"] == 1)
|
|
1327
|
-
b["sender"] = r[6]
|
|
1328
|
-
b["sender_email"] = r[8].gsub("\"",'') # remove annoying d-quotes in address
|
|
1329
|
-
b["recv"] = r[9]
|
|
1330
|
-
b["recv_email"] = r[11].gsub("\"",'')
|
|
1331
|
-
b["reply_email"] = r[14].gsub("\"",'')
|
|
1332
|
-
b["cc_email"] = r[12].gsub("\"",'')
|
|
1333
|
-
b["bcc_email"] = r[13].gsub("\"",'')
|
|
1334
|
-
b["dt_easy"] = r[10]
|
|
1335
|
-
b["dt"] = r[15]
|
|
1336
|
-
b["subject"] = r[16]
|
|
1337
|
-
b["snippet"] = r[17]
|
|
1338
|
-
b["attachment"] = []
|
|
1339
|
-
r[18].each {|bb|
|
|
1340
|
-
b["attachment"].push({"id"=>bb[0],"filename"=>bb[1],"type"=>bb[2],"size"=>bb[3]})
|
|
1341
|
-
}
|
|
1342
|
-
b["is_draft"] = true
|
|
1343
|
-
b["draft_parent"] = r[5]
|
|
1344
|
-
b["body"] = r[20]
|
|
1345
|
-
end
|
|
1346
|
-
}
|
|
1347
|
-
@conv.push(b) unless b.empty?
|
|
1348
|
-
end
|
|
1349
|
-
elsif type == GM_CONTACT
|
|
1350
|
-
@contacts = []
|
|
1351
|
-
if raw["ce"]
|
|
1352
|
-
raw["ce"].each {|a|
|
|
1353
|
-
b = {
|
|
1354
|
-
"name"=>a[2],
|
|
1355
|
-
"email"=>a[4].gsub("\"",'')
|
|
1356
|
-
}
|
|
1357
|
-
if !a[5].empty?
|
|
1358
|
-
b["notes"] = a[5]
|
|
1359
|
-
end
|
|
1360
|
-
@contacts.push(b)
|
|
1361
|
-
}
|
|
1362
|
-
end
|
|
1363
|
-
@view = GM_CONTACT
|
|
1364
|
-
elsif type == GM_PREFERENCE
|
|
1365
|
-
prefs = {}
|
|
1366
|
-
raw["p"].each_with_index { |v,i|
|
|
1367
|
-
prefs[v[0]] = v[1] if i>0
|
|
1368
|
-
}
|
|
1369
|
-
@preference = {'max_page_size'=>'10',
|
|
1370
|
-
'keyboard_shortcuts'=>false,
|
|
1371
|
-
'indicators'=>false,
|
|
1372
|
-
'display_language'=>'en',
|
|
1373
|
-
'signature'=>'',
|
|
1374
|
-
'reply_to'=>'',
|
|
1375
|
-
'snippets'=>false,
|
|
1376
|
-
'display_name'=>'',
|
|
1377
|
-
}
|
|
1378
|
-
prefs.each do |k,v|
|
|
1379
|
-
case k
|
|
1380
|
-
when 'ix_nt'
|
|
1381
|
-
@preference['max_page_size'] = v
|
|
1382
|
-
when 'bx_hs'
|
|
1383
|
-
@preference['keyboard_shortcuts'] = (v == '1')
|
|
1384
|
-
when 'bx_sc'
|
|
1385
|
-
@preference['indicators'] = (v == '1')
|
|
1386
|
-
when 'sx_dl'
|
|
1387
|
-
@preference['display_language'] = v
|
|
1388
|
-
when 'sx_sg'
|
|
1389
|
-
@preference['signature'] = (v == '0') ? '' : v
|
|
1390
|
-
when 'sx_rt'
|
|
1391
|
-
@preference['reply_to'] = v
|
|
1392
|
-
when 'bx_ns'
|
|
1393
|
-
@preference['snippets'] = (v == '0')
|
|
1394
|
-
when 'sx_dn'
|
|
1395
|
-
@preference['display_name'] = v
|
|
1396
|
-
end
|
|
1397
|
-
end
|
|
1398
|
-
|
|
1399
|
-
@label_list = []
|
|
1400
|
-
@label_total = []
|
|
1401
|
-
raw["cta"][1].each { |v|
|
|
1402
|
-
@label_list.push(v[0])
|
|
1403
|
-
@label_total.push(v[1])
|
|
1404
|
-
}
|
|
1405
|
-
@other_emails = []
|
|
1406
|
-
if raw["cfs"]
|
|
1407
|
-
raw["cfs"][1].each {|v|
|
|
1408
|
-
@other_emails.push({"name"=>decode(v[0]),"email"=>v[1],"default"=>(v[2]==1)})
|
|
1409
|
-
}
|
|
1410
|
-
end
|
|
1411
|
-
@filter = []
|
|
1412
|
-
@filter_rules = []
|
|
1413
|
-
raw["fi"][1].each { |fi|
|
|
1414
|
-
b = {
|
|
1415
|
-
"id" => fi[0],
|
|
1416
|
-
"query" => fi[1],
|
|
1417
|
-
"star" => fi[3],
|
|
1418
|
-
"label" => fi[4],
|
|
1419
|
-
"archive" => fi[5],
|
|
1420
|
-
"trash" => fi[6] #,"forward" => fi[7]
|
|
1421
|
-
}
|
|
1422
|
-
bb = {
|
|
1423
|
-
"from" => fi[2][0],
|
|
1424
|
-
"to" => fi[2][1],
|
|
1425
|
-
"subject" => fi[2][2],
|
|
1426
|
-
"has" => fi[2][3],
|
|
1427
|
-
"hasnot" => fi[2][4],
|
|
1428
|
-
"attach" => fi[2][5]
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
@filter.push(b)
|
|
1432
|
-
@filter_rules.push(bb)
|
|
1433
|
-
}
|
|
1434
|
-
@view = GM_PREFERENCE
|
|
1435
|
-
else
|
|
1436
|
-
@created = 0
|
|
1437
|
-
return nil
|
|
1438
|
-
end
|
|
1439
|
-
@created = 1
|
|
1440
|
-
end
|
|
1441
|
-
|
|
1442
|
-
end
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
class Debugger
|
|
1446
|
-
def Debugger.say(str)
|
|
1447
|
-
puts str if $D_ON
|
|
1448
|
-
end
|
|
1449
1668
|
end
|
|
1450
1669
|
|