google-gmail-api 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ module Gmail
2
+ module Base
3
+ module Update
4
+ def update!(body)
5
+ if id.nil?
6
+ d = self.class.create(body)
7
+ else
8
+ response = Gmail.request(self.class.base_method.send("update"),{id: id}, body)
9
+ d = Util.convert_to_gmail_object(response, self.class.class_name.downcase)
10
+ end
11
+ @values = d.values
12
+ self
13
+ end
14
+
15
+ def update(body)
16
+ if id.nil?
17
+ d = self.class.create(body)
18
+ else
19
+ response = Gmail.request(self.class.base_method.send("update"),{id: id}, body)
20
+ d = Util.convert_to_gmail_object(response, self.class.class_name.downcase)
21
+ end
22
+ d
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,54 @@
1
+ module Gmail
2
+ class Draft < APIResource
3
+ include Base::List
4
+ include Base::Create
5
+ include Base::Delete
6
+ include Base::Get
7
+ include Base::Update
8
+
9
+ def message
10
+ if @values.message.is_a?(Message)
11
+ @values.message
12
+ else
13
+ @values.message = Util.convert_to_gmail_object(to_hash[:message], key="message")
14
+ if @values.message.payload.nil?
15
+ self.detailed!
16
+ message
17
+ end
18
+ @values.message
19
+ end
20
+ end
21
+
22
+ def save(opts={})
23
+ msg = {raw: message.raw}
24
+ if message.threadId
25
+ msg[:threadId] = message.threadId
26
+ end
27
+ if message.labelIds
28
+ msg[:labelIds] = message.labelIds
29
+ end
30
+ body = {message: msg}
31
+ update(body)
32
+ end
33
+
34
+ def save!(opts={})
35
+ msg = {raw: message.raw}
36
+ if message.threadId
37
+ msg[:threadId] = message.threadId
38
+ end
39
+ if message.labelIds
40
+ msg[:labelIds] = message.labelIds
41
+ end
42
+ body = {message: msg}
43
+ update!(body)
44
+ end
45
+
46
+ def deliver
47
+ response = Gmail.request(self.class.base_method.to_h['gmail.users.drafts.send'],{},{id: id})
48
+ Message.get(response[:id])
49
+ end
50
+
51
+
52
+
53
+ end
54
+ end
@@ -0,0 +1,147 @@
1
+ module Gmail
2
+ class GmailObject
3
+ include Enumerable
4
+ include Hooks
5
+ define_hooks :after_initialize
6
+
7
+ # The default :id method is deprecated and isn't useful to us
8
+ if method_defined?(:id)
9
+ undef :id
10
+ end
11
+
12
+ def initialize(hash={})
13
+ @values = Hashie::Mash.new hash
14
+ run_hook :after_initialize
15
+ end
16
+
17
+
18
+ def to_s(*args)
19
+ JSON.pretty_generate(@values.to_hash)
20
+ end
21
+
22
+ def inspect
23
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}> " + to_s
24
+ end
25
+
26
+ def [](k)
27
+ @values[k.to_sym]
28
+ end
29
+
30
+ def []=(k, v)
31
+ @values.send("#{k}=", v)
32
+ end
33
+
34
+ def to_json(*a)
35
+ JSON.generate(@values)
36
+ end
37
+
38
+ def as_json(*a)
39
+ @values.as_json(*a)
40
+ end
41
+
42
+ def detailed
43
+ if self.class == GmailObject
44
+ raise "Can't detail a generic GmailObject. It needs to be a Thread, Message, Draft or Label"
45
+ end
46
+
47
+ self.class.get(id)
48
+ end
49
+
50
+ def refresh
51
+ if self.class == GmailObject
52
+ raise "Can't refresh a generic GmailObject. It needs to be a Thread, Message, Draft or Label"
53
+ end
54
+ @values = self.class.get(id).values
55
+ self
56
+ end
57
+
58
+ alias_method :detailed!, :refresh
59
+ #
60
+ def to_hash
61
+ Util.symbolize_names(@values.to_hash)
62
+ end
63
+
64
+ def values
65
+ @values
66
+ end
67
+ #
68
+ # def each(&blk)
69
+ # @values.each(&blk)
70
+ # end
71
+ #
72
+ # def _dump(level)
73
+ # Marshal.dump([@values, @api_key])
74
+ # end
75
+ #
76
+ # def self._load(args)
77
+ # values, api_key = Marshal.load(args)
78
+ # construct_from(values)
79
+ # end
80
+ #
81
+ # if RUBY_VERSION < '1.9.2'
82
+ # def respond_to?(symbol)
83
+ # @values.has_key?(symbol) || super
84
+ # end
85
+ # end
86
+ #
87
+ protected
88
+
89
+ def metaclass
90
+ class << self; self; end
91
+ end
92
+ #
93
+ # def remove_accessors(keys)
94
+ # metaclass.instance_eval do
95
+ # keys.each do |k|
96
+ # next if @@permanent_attributes.include?(k)
97
+ # k_eq = :"#{k}="
98
+ # remove_method(k) if method_defined?(k)
99
+ # remove_method(k_eq) if method_defined?(k_eq)
100
+ # end
101
+ # end
102
+ # end
103
+ #
104
+ # def add_accessors(keys)
105
+ # metaclass.instance_eval do
106
+ # keys.each do |k|
107
+ # next if @@permanent_attributes.include?(k)
108
+ # k_eq = :"#{k}="
109
+ # define_method(k) { @values[k] }
110
+ # define_method(k_eq) do |v|
111
+ # if v == ""
112
+ # raise ArgumentError.new(
113
+ # "You cannot set #{k} to an empty string." +
114
+ # "We interpret empty strings as nil in requests." +
115
+ # "You may set #{self}.#{k} = nil to delete the property.")
116
+ # end
117
+ # @values[k] = v
118
+ # @unsaved_values.add(k)
119
+ # end
120
+ # end
121
+ # end
122
+ # end
123
+ #
124
+ def method_missing(name, *args)
125
+
126
+ if @values.send(name.to_s + "?")
127
+ @values.send(name)
128
+ else
129
+ begin
130
+ @values.send(name.to_s, args[0])
131
+ rescue
132
+ begin
133
+ super.send(name)
134
+ rescue
135
+ nil
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+
142
+ #
143
+ # def respond_to_missing?(symbol, include_private = false)
144
+ # super
145
+ # end
146
+ end
147
+ end
@@ -0,0 +1,52 @@
1
+ module Gmail
2
+ class Label < APIResource
3
+ include Base::List
4
+ include Base::Create
5
+ include Base::Delete
6
+ include Base::Get
7
+ include Base::Update
8
+
9
+ def save
10
+ update(to_hash)
11
+ end
12
+
13
+ def save!
14
+ update!(to_hash)
15
+ end
16
+
17
+ def self.boxes
18
+ @boxes ||= [:inbox, :sent, :trash, :important, :starred, :draft, :spam, :unread, :category_updates, :category_promotions, :category_social, :category_personal, :category_forums ]
19
+ end
20
+
21
+ boxes.each do |method|
22
+ define_singleton_method method do
23
+ Label.get(method.to_s.upcase)
24
+ end
25
+ end
26
+
27
+ def messages filters={}
28
+ filters = {labelIds: [id]}.merge(filters)
29
+ filters[:labelIds] = filters[:labelIds] | [id]
30
+ Message.all(filters)
31
+ end
32
+
33
+ def unread_messages
34
+ if messagesUnread == 0
35
+ []
36
+ else
37
+ Message.all({labelIds: [id, "UNREAD"]})
38
+ end
39
+ end
40
+
41
+ def threads filters={}
42
+ filters = {labelIds: [id]}.merge(filters)
43
+ filters[:labelIds] = filters[:labelIds] | [id]
44
+ Thread.all(filters)
45
+ end
46
+
47
+ def unread_threads
48
+ Thread.all({labelIds: [id, "UNREAD"]})
49
+ end
50
+
51
+ end
52
+ end # Gmail
@@ -0,0 +1,242 @@
1
+ # encoding: utf-8
2
+ module Gmail
3
+ class Message < APIResource
4
+ include Base::List
5
+ include Base::Delete
6
+ include Base::Get
7
+ include Base::Modify
8
+ include Base::Trash
9
+
10
+ require "stringex"
11
+
12
+ after_initialize :set_basics
13
+
14
+ def thread
15
+ Thread.get(threadId)
16
+ end
17
+
18
+ def create_draft
19
+ Draft.create(message: msg_parameters)
20
+ end
21
+
22
+ def deliver!
23
+ response = Gmail.request(self.class.base_method.to_h['gmail.users.messages.send'],{}, msg_parameters)
24
+ @values = Message.get(response[:id]).values
25
+ self
26
+ end
27
+
28
+ def deliver
29
+ response = Gmail.request(self.class.base_method.to_h['gmail.users.messages.send'],{}, msg_parameters)
30
+ Message.get(response[:id])
31
+ end
32
+
33
+ def insert
34
+ response = Gmail.request(self.class.base_method.insert,{}, msg_parameters)
35
+ Message.get(response[:id])
36
+ end
37
+
38
+ def insert!
39
+ response = Gmail.request(self.class.base_method.insert,{}, msg_parameters)
40
+ @values = Message.get(response[:id]).values
41
+ self
42
+ end
43
+
44
+ def reply_all_with msg
45
+ msg = set_headers_for_reply msg
46
+ msg = quote_in msg
47
+ msg
48
+ end
49
+
50
+ def reply_sender_with msg
51
+ msg = set_headers_for_reply msg
52
+ msg = quote_in msg
53
+ msg.cc = nil
54
+ msg
55
+ end
56
+
57
+ def forward_with msg
58
+ # save headers that need to be override by users compared to a classic reply
59
+ x_cc = msg.cc
60
+ x_to = msg.to
61
+ x_bcc = msg.bcc
62
+ x_subject = msg.subject || subject #if user doesn't override keep classic behavior
63
+ # set headers as for reply
64
+ msg = set_headers_for_reply msg
65
+ # quote message
66
+ msg = quote_in msg
67
+ # reset saved overridden headers
68
+ msg.cc = x_cc
69
+ msg.to = x_to
70
+ msg.bcc = x_bcc
71
+ msg.subject = x_subject
72
+ msg
73
+ end
74
+
75
+
76
+ def thread_id
77
+ threadId
78
+ end
79
+
80
+
81
+ def unread?
82
+ (labelIds||[]).include?("UNREAD")
83
+ end
84
+
85
+ def sent?
86
+ (labelIds||[]).include?("SENT")
87
+ end
88
+
89
+ def inbox?
90
+ (labelIds||[]).include?("INBOX")
91
+ end
92
+
93
+
94
+
95
+ def raw # is not in private because the method is used in Draft
96
+ if super #check if raw is set to allow fully custom message to be sent
97
+ super
98
+ else
99
+ s = self
100
+ msg = Mail.new
101
+ msg.subject = subject
102
+ if body
103
+ msg.body = body
104
+ end
105
+ msg.from = from
106
+ msg.to = to
107
+ msg.cc = cc
108
+ msg.header['X-Bcc'] = bcc unless bcc.nil?#because Mail gem doesn't allow bcc headers...
109
+ msg.in_reply_to = in_reply_to unless in_reply_to.nil?
110
+ msg.references = references unless references.nil?
111
+ if text || html
112
+ bodypart = Mail::Part.new
113
+ if text
114
+ bodypart.text_part = Mail::Part.new do |p|
115
+ content_type 'text/plain; charset=UTF-8'
116
+ p.body s.text
117
+ end
118
+ end
119
+ if html
120
+ bodypart.html_part = Mail::Part.new do |p|
121
+ content_type 'text/html; charset=UTF-8'
122
+ p.body s.html
123
+ end
124
+ end
125
+ msg.add_part bodypart
126
+ end
127
+ if attachments
128
+ if attachments.is_a?(Hash)
129
+ attachments.each do |name, attachment|
130
+ msg.add_file filename: name, content: attachment
131
+ end
132
+ elsif attachments.is_a?(Array)
133
+ attachments.each do |attachment|
134
+ msg.add_file(attachment)
135
+ end
136
+ end
137
+ end
138
+ Base64.urlsafe_encode64 msg.to_s.sub("X-Bcc", "Bcc") #because Mail gem doesn't allow bcc headers...
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+ def msg_parameters
145
+ msg = {raw: raw}
146
+ if threadId
147
+ msg[:threadId] = threadId
148
+ end
149
+ if labelIds
150
+ msg[:labelIds] = labelIds
151
+ end
152
+ msg
153
+ end
154
+
155
+ def self.find_addresses str
156
+ Mail::AddressList.new("#{str}".to_ascii.gsub(/<(<(.)*@(.)*>)(.)*>/, '\1'))
157
+ end
158
+
159
+ def set_headers_for_reply msg
160
+ #to_ar = []
161
+ #split_regexp = Regexp.new("\s*,\s*")
162
+ own_email = delivered_to || Gmail.mailbox_email
163
+
164
+
165
+ to_ar = (Message.find_addresses(to).addresses + Message.find_addresses(cc).addresses).map(&:to_s)
166
+ #to_ar = (to || "").split(split_regexp) + (cc || "").split(split_regexp)
167
+ result = to_ar.grep(Regexp.new(own_email, "i"))
168
+ to_ar = to_ar - result
169
+
170
+ msg.subject = subject
171
+ if from.match(Regexp.new(own_email, "i"))
172
+ msg.to = to_ar.first
173
+ to_ar = to_ar.drop(1)
174
+ else
175
+ msg.to = from
176
+ end
177
+ msg.cc = to_ar.join(", ")
178
+ msg.bcc = nil
179
+ msg.threadId = thread_id
180
+ msg.references = ((references || "").split(Regexp.new "\s+") << message_id).join(" ")
181
+ msg.in_reply_to = ((in_reply_to || "").split(Regexp.new "\s+") << message_id).join(" ")
182
+ msg
183
+ end
184
+
185
+ def quote_in reply_msg
186
+ text_to_append = "\r\n\r\n#{date} #{from}:\r\n\r\n>" + (body || text).gsub("\n", "\n>") unless body.nil? && text.nil?
187
+ html_to_append = "\r\n<br><br><div class=\"gmail_quote\"> #{date} #{CGI.escapeHTML(from)}:<br><blockquote class=\"gmail_quote\" style=\"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex\">" + html + "</blockquote></div><br>" unless html.nil?
188
+ reply_msg.html = "<div>" + reply_msg.html + "</div>" + html_to_append unless reply_msg.html.nil?
189
+ reply_msg.text = reply_msg.text + text_to_append unless reply_msg.text.nil?
190
+ reply_msg.body = reply_msg.body + text_to_append unless reply_msg.body.nil?
191
+ reply_msg
192
+ end
193
+
194
+ def urlsafe_decode64 code
195
+ Base64.urlsafe_decode64(code).force_encoding('UTF-8').encode
196
+ end
197
+
198
+
199
+ def set_basics
200
+ if @values.payload
201
+ ["From", "To", "Cc", "Subject", "Bcc", "Date", "Message-ID", "References", "In-Reply-To", "Delivered-To"].each do |n|
202
+ if payload_n = @values.payload.headers.select{|h| h.name.downcase == n.downcase}.first
203
+ @values.send(n.downcase.tr("-", "_") + "=", payload_n.value)
204
+ end
205
+ end
206
+
207
+ if payload.parts
208
+ content_payload = @values.payload.find_all_object_containing("mimeType", "multipart/alternative").first
209
+ content_payload ||= @values.payload
210
+ text_part=content_payload.find_all_object_containing("mimeType", "text/plain").first
211
+ if text_part && text_part.body.data
212
+ @values.text = urlsafe_decode64(text_part.body.data)
213
+ end
214
+ html_part=content_payload.find_all_object_containing("mimeType", "text/html").first
215
+ if html_part && html_part.body.data
216
+ @values.html = urlsafe_decode64(html_part.body.data)
217
+ end
218
+ end
219
+ if payload.body.data
220
+ @values.body = urlsafe_decode64(@values.payload.body.data)
221
+ end
222
+ end
223
+ end
224
+
225
+ class Hashie::Mash
226
+ def find_all_object_containing(key, value )
227
+ result=[]
228
+ if self.send(key) == value
229
+ result << self
230
+ end
231
+ self.values.each do |vs|
232
+ vs = [vs] unless vs.is_a? Array
233
+ vs.each do |v|
234
+ result += v.find_all_object_containing(key,value) if v.is_a? Hashie::Mash
235
+ end
236
+ end
237
+ result
238
+ end
239
+ end
240
+
241
+ end
242
+ end