google-gmail-api 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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