gmail 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +27 -27
- data/.rspec +1 -1
- data/.rubocop.yml +13 -13
- data/.rubocop_todo.yml +239 -239
- data/.travis.yml +19 -19
- data/CHANGELOG.md +145 -139
- data/Gemfile +3 -3
- data/LICENSE +21 -21
- data/README.md +355 -354
- data/Rakefile +46 -46
- data/gmail.gemspec +34 -34
- data/lib/gmail.rb +78 -78
- data/lib/gmail/client.rb +34 -34
- data/lib/gmail/client/base.rb +229 -229
- data/lib/gmail/client/plain.rb +24 -24
- data/lib/gmail/client/xoauth.rb +68 -68
- data/lib/gmail/client/xoauth2.rb +39 -39
- data/lib/gmail/imap_extensions.rb +159 -150
- data/lib/gmail/labels.rb +79 -79
- data/lib/gmail/mailbox.rb +175 -135
- data/lib/gmail/message.rb +207 -207
- data/lib/gmail/version.rb +3 -3
- data/spec/account.yml.example +1 -1
- data/spec/account.yml.obfus +2 -2
- data/spec/gmail/client/base_spec.rb +5 -5
- data/spec/gmail/client/plain_spec.rb +169 -168
- data/spec/gmail/client/xoauth2_spec.rb +186 -186
- data/spec/gmail/client/xoauth_spec.rb +5 -5
- data/spec/gmail/client_spec.rb +5 -5
- data/spec/gmail/imap_extensions_spec.rb +47 -12
- data/spec/gmail/labels_spec.rb +27 -18
- data/spec/gmail/mailbox_spec.rb +84 -47
- data/spec/gmail/message_spec.rb +181 -181
- data/spec/gmail_spec.rb +39 -39
- data/spec/recordings/gmail/_new_connects_with_client_and_give_it_context_when_block_given.yml +28 -28
- data/spec/recordings/gmail/_new_connects_with_gmail_service_and_return_valid_connection_object.yml +28 -28
- data/spec/recordings/gmail/_new_does_not_raise_error_when_couldn_t_connect_with_given_account.yml +13 -13
- data/spec/recordings/gmail/_new_raises_error_when_couldn_t_connect_with_given_account.yml +13 -13
- data/spec/recordings/gmail_client_plain/instance/_connection_automatically_logs_in_to_gmail_account_when_it_s_called.yml +42 -42
- data/spec/recordings/gmail_client_plain/instance/delivers_inline_composed_email.yml +42 -42
- data/spec/recordings/gmail_client_plain/instance/does_not_log_in_when_given_gmail_account_is_invalid.yml +13 -13
- data/spec/recordings/gmail_client_plain/instance/does_not_raise_error_even_though_gmail_account_is_invalid.yml +13 -13
- data/spec/recordings/gmail_client_plain/instance/labels/checks_if_there_is_given_label_defined.yml +196 -196
- data/spec/recordings/gmail_client_plain/instance/labels/creates_given_label.yml +151 -151
- data/spec/recordings/gmail_client_plain/instance/labels/removes_existing_label.yml +146 -146
- data/spec/recordings/gmail_client_plain/instance/labels/returns_list_of_all_available_labels.yml +113 -113
- data/spec/recordings/gmail_client_plain/instance/properly_logs_in_to_valid_gmail_account.yml +42 -42
- data/spec/recordings/gmail_client_plain/instance/properly_logs_out_from_gmail.yml +42 -42
- data/spec/recordings/gmail_client_plain/instance/properly_switches_to_given_mailbox.yml +109 -109
- data/spec/recordings/gmail_client_plain/instance/properly_switches_to_given_mailbox_using_block_style.yml +109 -109
- data/spec/recordings/gmail_client_plain/instance/raises_error_when_given_gmail_account_is_invalid_and_errors_enabled.yml +13 -13
- data/spec/recordings/gmail_client_xo_auth2/instance/does_not_log_in_when_given_gmail_account_is_invalid.yml +13 -13
- data/spec/recordings/gmail_client_xo_auth2/instance/labels/checks_if_there_is_given_label_defined.yml +27 -27
- data/spec/recordings/gmail_client_xo_auth2/instance/labels/creates_given_label.yml +39 -39
- data/spec/recordings/gmail_client_xo_auth2/instance/labels/removes_existing_label.yml +39 -39
- data/spec/recordings/gmail_client_xo_auth2/instance/labels/returns_list_of_all_available_labels.yml +27 -27
- data/spec/recordings/gmail_client_xo_auth2/instance/properly_logs_in_to_valid_gmail_account.yml +15 -15
- data/spec/recordings/gmail_client_xo_auth2/instance/properly_logs_out_from_gmail.yml +15 -15
- data/spec/recordings/gmail_client_xo_auth2/instance/properly_switches_to_given_mailbox.yml +40 -40
- data/spec/recordings/gmail_client_xo_auth2/instance/properly_switches_to_given_mailbox_using_block_style.yml +40 -40
- data/spec/recordings/gmail_client_xo_auth2/instance/raises_error_when_given_gmail_account_is_invalid_and_errors_enabled.yml +13 -13
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/all/localizes_into_the_appropriate_label.yml +116 -116
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/and_the_mailbox_does_not_exist/returns_the_mailbox_name_as_a_string.yml +110 -0
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/drafts/localizes_into_the_appropriate_label.yml +116 -116
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/flagged/localizes_into_the_appropriate_label.yml +116 -116
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/important/localizes_into_the_appropriate_label.yml +116 -116
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/inbox/localizes_into_the_appropriate_label.yml +42 -42
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/junk/localizes_into_the_appropriate_label.yml +116 -116
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/sent/localizes_into_the_appropriate_label.yml +116 -116
- data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/trash/localizes_into_the_appropriate_label.yml +116 -116
- data/spec/recordings/gmail_mailbox/instance/counts_all_emails.yml +277 -277
- data/spec/recordings/gmail_mailbox/instance/finds_messages.yml +586 -586
- data/spec/recordings/gmail_mailbox/instance/waits_once.yml +136 -0
- data/spec/recordings/gmail_mailbox/instance/waits_repeatedly.yml +141 -0
- data/spec/recordings/gmail_mailbox/instance/waits_with_29-minute_re-issue.yml +136 -0
- data/spec/recordings/gmail_mailbox/instance/waits_with_an_unblocked_connection.yml +207 -0
- data/spec/recordings/gmail_mailbox/on_initialize/sets_client_and_name.yml +42 -42
- data/spec/recordings/gmail_mailbox/on_initialize/works_in_inbox_by_default.yml +42 -42
- data/spec/recordings/gmail_message/initialize/sets_prefetch_attrs.yml +578 -578
- data/spec/recordings/gmail_message/initialize/sets_uid_and_mailbox.yml +580 -580
- data/spec/recordings/gmail_message/instance_methods/deletes_itself.yml +637 -637
- data/spec/recordings/gmail_message/instance_methods/marks_itself_read.yml +682 -682
- data/spec/recordings/gmail_message/instance_methods/marks_itself_unread.yml +686 -686
- data/spec/recordings/gmail_message/instance_methods/moves_from_one_tag_to_other.yml +862 -862
- data/spec/recordings/gmail_message/instance_methods/removes_a_given_label.yml +776 -776
- data/spec/recordings/gmail_message/instance_methods/removes_a_given_label_with_old_method.yml +776 -776
- data/spec/recordings/gmail_message/instance_methods/sets_given_label.yml +690 -690
- data/spec/recordings/gmail_message/instance_methods/sets_given_label_with_old_method.yml +691 -691
- data/spec/spec_helper.rb +53 -53
- data/spec/support/imap_mock.rb +181 -129
- data/spec/support/obfuscation.rb +52 -52
- metadata +78 -5
data/lib/gmail/message.rb
CHANGED
@@ -1,207 +1,207 @@
|
|
1
|
-
module Gmail
|
2
|
-
class Message
|
3
|
-
PREFETCH_ATTRS = ["UID", "ENVELOPE", "BODY.PEEK[]", "FLAGS", "X-GM-LABELS", "X-GM-MSGID", "X-GM-THRID"]
|
4
|
-
|
5
|
-
# Raised when given label doesn't exists.
|
6
|
-
class NoLabelError < Exception; end
|
7
|
-
|
8
|
-
def initialize(mailbox, uid, _attrs = nil)
|
9
|
-
@uid = uid
|
10
|
-
@mailbox = mailbox
|
11
|
-
@gmail = mailbox.instance_variable_get("@gmail") if mailbox # UGLY
|
12
|
-
@_attrs = _attrs
|
13
|
-
end
|
14
|
-
|
15
|
-
def uid
|
16
|
-
@uid ||= fetch("UID")
|
17
|
-
end
|
18
|
-
|
19
|
-
def msg_id
|
20
|
-
@msg_id ||= fetch("X-GM-MSGID")
|
21
|
-
end
|
22
|
-
alias_method :message_id, :msg_id
|
23
|
-
|
24
|
-
def thr_id
|
25
|
-
@thr_id ||= fetch("X-GM-THRID")
|
26
|
-
end
|
27
|
-
alias_method :thread_id, :thr_id
|
28
|
-
|
29
|
-
def envelope
|
30
|
-
@envelope ||= fetch("ENVELOPE")
|
31
|
-
end
|
32
|
-
|
33
|
-
def message
|
34
|
-
@message ||= Mail.new(fetch("BODY[]"))
|
35
|
-
end
|
36
|
-
alias_method :raw_message, :message
|
37
|
-
|
38
|
-
def flags
|
39
|
-
@flags ||= fetch("FLAGS")
|
40
|
-
end
|
41
|
-
|
42
|
-
def labels
|
43
|
-
@labels ||= fetch("X-GM-LABELS")
|
44
|
-
end
|
45
|
-
|
46
|
-
# Mark message with given flag.
|
47
|
-
def flag(name)
|
48
|
-
!!@gmail.mailbox(@mailbox.name) do
|
49
|
-
@gmail.conn.uid_store(uid, "+FLAGS", [name])
|
50
|
-
clear_cached_attributes
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# Unmark message.
|
55
|
-
def unflag(name)
|
56
|
-
!!@gmail.mailbox(@mailbox.name) do
|
57
|
-
@gmail.conn.uid_store(uid, "-FLAGS", [name])
|
58
|
-
clear_cached_attributes
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# Do commonly used operations on message.
|
63
|
-
def mark(flag)
|
64
|
-
case flag
|
65
|
-
when :read then read!
|
66
|
-
when :unread then unread!
|
67
|
-
when :deleted then delete!
|
68
|
-
when :spam then spam!
|
69
|
-
else
|
70
|
-
flag(flag)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Check whether message is read
|
75
|
-
def read?
|
76
|
-
flags.include?(:Seen)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Mark as read.
|
80
|
-
def read!
|
81
|
-
flag(:Seen)
|
82
|
-
end
|
83
|
-
|
84
|
-
# Mark as unread.
|
85
|
-
def unread!
|
86
|
-
unflag(:Seen)
|
87
|
-
end
|
88
|
-
|
89
|
-
# Check whether message is starred
|
90
|
-
def starred?
|
91
|
-
flags.include?(:Flagged)
|
92
|
-
end
|
93
|
-
|
94
|
-
# Mark message with star.
|
95
|
-
def star!
|
96
|
-
flag(:Flagged)
|
97
|
-
end
|
98
|
-
|
99
|
-
# Remove message from list of starred.
|
100
|
-
def unstar!
|
101
|
-
unflag(:Flagged)
|
102
|
-
end
|
103
|
-
|
104
|
-
# Marking as spam is done by adding the `\Spam` label. To undo this,
|
105
|
-
# you just re-apply the `\Inbox` label (see `#unspam!`)
|
106
|
-
def spam!
|
107
|
-
add_label("\\Spam")
|
108
|
-
end
|
109
|
-
|
110
|
-
# Deleting is done by adding the `\Trash` label. To undo this,
|
111
|
-
# you just re-apply the `\Inbox` label (see `#undelete!`)
|
112
|
-
def delete!
|
113
|
-
add_label("\\Trash")
|
114
|
-
end
|
115
|
-
|
116
|
-
# Archiving is done by adding the `\Trash` label. To undo this,
|
117
|
-
# you just re-apply the `\Inbox` label (see `#unarchive!`)
|
118
|
-
def archive!
|
119
|
-
remove_label("\\Inbox")
|
120
|
-
end
|
121
|
-
|
122
|
-
def unarchive!
|
123
|
-
add_label("\\Inbox")
|
124
|
-
end
|
125
|
-
alias_method :unspam!, :unarchive!
|
126
|
-
alias_method :undelete!, :unarchive!
|
127
|
-
|
128
|
-
# Move to given box and delete from others.
|
129
|
-
# Apply a given label and optionally remove one.
|
130
|
-
# TODO: We should probably deprecate this method. It doesn't really add a lot
|
131
|
-
# of value, especially since the concept of "moving" a message from one
|
132
|
-
# label to another doesn't totally make sense in the Gmail world.
|
133
|
-
def move_to(name, from = nil)
|
134
|
-
add_label(name)
|
135
|
-
remove_label(from) if from
|
136
|
-
end
|
137
|
-
alias_method :move, :move_to
|
138
|
-
alias_method :move!, :move_to
|
139
|
-
alias_method :move_to!, :move_to
|
140
|
-
|
141
|
-
# Use Gmail IMAP Extensions to add a Label to an email
|
142
|
-
def add_label(name)
|
143
|
-
@gmail.mailbox(@mailbox.name) do
|
144
|
-
@gmail.conn.uid_store(uid, "+X-GM-LABELS", [Net::IMAP.encode_utf7(name.to_s)])
|
145
|
-
clear_cached_attributes
|
146
|
-
end
|
147
|
-
end
|
148
|
-
alias_method :label, :add_label
|
149
|
-
alias_method :label!, :add_label
|
150
|
-
alias_method :add_label!, :add_label
|
151
|
-
|
152
|
-
# Use Gmail IMAP Extensions to remove a Label from an email
|
153
|
-
def remove_label(name)
|
154
|
-
@gmail.mailbox(@mailbox.name) do
|
155
|
-
@gmail.conn.uid_store(uid, "-X-GM-LABELS", [Net::IMAP.encode_utf7(name.to_s)])
|
156
|
-
clear_cached_attributes
|
157
|
-
end
|
158
|
-
end
|
159
|
-
alias_method :remove_label!, :remove_label
|
160
|
-
|
161
|
-
def inspect
|
162
|
-
"#<Gmail::Message#{'0x%04x' % (object_id << 1)} mailbox=#{@mailbox.name}#{' uid=' + @uid.to_s if @uid}#{' message_id=' + @msg_id.to_s if @msg_id}>"
|
163
|
-
end
|
164
|
-
|
165
|
-
def method_missing(meth, *args, &block)
|
166
|
-
# Delegate rest directly to the message.
|
167
|
-
if envelope.respond_to?(meth)
|
168
|
-
envelope.send(meth, *args, &block)
|
169
|
-
elsif message.respond_to?(meth)
|
170
|
-
message.send(meth, *args, &block)
|
171
|
-
else
|
172
|
-
super(meth, *args, &block)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def respond_to?(meth, *args, &block)
|
177
|
-
if envelope.respond_to?(meth)
|
178
|
-
return true
|
179
|
-
elsif message.respond_to?(meth)
|
180
|
-
return true
|
181
|
-
else
|
182
|
-
super(meth, *args, &block)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
private
|
187
|
-
|
188
|
-
def clear_cached_attributes
|
189
|
-
@_attrs = nil
|
190
|
-
@msg_id = nil
|
191
|
-
@thr_id = nil
|
192
|
-
@envelope = nil
|
193
|
-
@message = nil
|
194
|
-
@flags = nil
|
195
|
-
@labels = nil
|
196
|
-
end
|
197
|
-
|
198
|
-
def fetch(value)
|
199
|
-
@_attrs ||= begin
|
200
|
-
@gmail.mailbox(@mailbox.name) do
|
201
|
-
@gmail.conn.uid_fetch(uid, PREFETCH_ATTRS)[0]
|
202
|
-
end
|
203
|
-
end
|
204
|
-
@_attrs.attr[value]
|
205
|
-
end
|
206
|
-
end # Message
|
207
|
-
end # Gmail
|
1
|
+
module Gmail
|
2
|
+
class Message
|
3
|
+
PREFETCH_ATTRS = ["UID", "ENVELOPE", "BODY.PEEK[]", "FLAGS", "X-GM-LABELS", "X-GM-MSGID", "X-GM-THRID"]
|
4
|
+
|
5
|
+
# Raised when given label doesn't exists.
|
6
|
+
class NoLabelError < Exception; end
|
7
|
+
|
8
|
+
def initialize(mailbox, uid, _attrs = nil)
|
9
|
+
@uid = uid
|
10
|
+
@mailbox = mailbox
|
11
|
+
@gmail = mailbox.instance_variable_get("@gmail") if mailbox # UGLY
|
12
|
+
@_attrs = _attrs
|
13
|
+
end
|
14
|
+
|
15
|
+
def uid
|
16
|
+
@uid ||= fetch("UID")
|
17
|
+
end
|
18
|
+
|
19
|
+
def msg_id
|
20
|
+
@msg_id ||= fetch("X-GM-MSGID")
|
21
|
+
end
|
22
|
+
alias_method :message_id, :msg_id
|
23
|
+
|
24
|
+
def thr_id
|
25
|
+
@thr_id ||= fetch("X-GM-THRID")
|
26
|
+
end
|
27
|
+
alias_method :thread_id, :thr_id
|
28
|
+
|
29
|
+
def envelope
|
30
|
+
@envelope ||= fetch("ENVELOPE")
|
31
|
+
end
|
32
|
+
|
33
|
+
def message
|
34
|
+
@message ||= Mail.new(fetch("BODY[]"))
|
35
|
+
end
|
36
|
+
alias_method :raw_message, :message
|
37
|
+
|
38
|
+
def flags
|
39
|
+
@flags ||= fetch("FLAGS")
|
40
|
+
end
|
41
|
+
|
42
|
+
def labels
|
43
|
+
@labels ||= fetch("X-GM-LABELS")
|
44
|
+
end
|
45
|
+
|
46
|
+
# Mark message with given flag.
|
47
|
+
def flag(name)
|
48
|
+
!!@gmail.mailbox(@mailbox.name) do
|
49
|
+
@gmail.conn.uid_store(uid, "+FLAGS", [name])
|
50
|
+
clear_cached_attributes
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Unmark message.
|
55
|
+
def unflag(name)
|
56
|
+
!!@gmail.mailbox(@mailbox.name) do
|
57
|
+
@gmail.conn.uid_store(uid, "-FLAGS", [name])
|
58
|
+
clear_cached_attributes
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Do commonly used operations on message.
|
63
|
+
def mark(flag)
|
64
|
+
case flag
|
65
|
+
when :read then read!
|
66
|
+
when :unread then unread!
|
67
|
+
when :deleted then delete!
|
68
|
+
when :spam then spam!
|
69
|
+
else
|
70
|
+
flag(flag)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Check whether message is read
|
75
|
+
def read?
|
76
|
+
flags.include?(:Seen)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Mark as read.
|
80
|
+
def read!
|
81
|
+
flag(:Seen)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Mark as unread.
|
85
|
+
def unread!
|
86
|
+
unflag(:Seen)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Check whether message is starred
|
90
|
+
def starred?
|
91
|
+
flags.include?(:Flagged)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Mark message with star.
|
95
|
+
def star!
|
96
|
+
flag(:Flagged)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Remove message from list of starred.
|
100
|
+
def unstar!
|
101
|
+
unflag(:Flagged)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Marking as spam is done by adding the `\Spam` label. To undo this,
|
105
|
+
# you just re-apply the `\Inbox` label (see `#unspam!`)
|
106
|
+
def spam!
|
107
|
+
add_label("\\Spam")
|
108
|
+
end
|
109
|
+
|
110
|
+
# Deleting is done by adding the `\Trash` label. To undo this,
|
111
|
+
# you just re-apply the `\Inbox` label (see `#undelete!`)
|
112
|
+
def delete!
|
113
|
+
add_label("\\Trash")
|
114
|
+
end
|
115
|
+
|
116
|
+
# Archiving is done by adding the `\Trash` label. To undo this,
|
117
|
+
# you just re-apply the `\Inbox` label (see `#unarchive!`)
|
118
|
+
def archive!
|
119
|
+
remove_label("\\Inbox")
|
120
|
+
end
|
121
|
+
|
122
|
+
def unarchive!
|
123
|
+
add_label("\\Inbox")
|
124
|
+
end
|
125
|
+
alias_method :unspam!, :unarchive!
|
126
|
+
alias_method :undelete!, :unarchive!
|
127
|
+
|
128
|
+
# Move to given box and delete from others.
|
129
|
+
# Apply a given label and optionally remove one.
|
130
|
+
# TODO: We should probably deprecate this method. It doesn't really add a lot
|
131
|
+
# of value, especially since the concept of "moving" a message from one
|
132
|
+
# label to another doesn't totally make sense in the Gmail world.
|
133
|
+
def move_to(name, from = nil)
|
134
|
+
add_label(name)
|
135
|
+
remove_label(from) if from
|
136
|
+
end
|
137
|
+
alias_method :move, :move_to
|
138
|
+
alias_method :move!, :move_to
|
139
|
+
alias_method :move_to!, :move_to
|
140
|
+
|
141
|
+
# Use Gmail IMAP Extensions to add a Label to an email
|
142
|
+
def add_label(name)
|
143
|
+
@gmail.mailbox(@mailbox.name) do
|
144
|
+
@gmail.conn.uid_store(uid, "+X-GM-LABELS", [Net::IMAP.encode_utf7(name.to_s)])
|
145
|
+
clear_cached_attributes
|
146
|
+
end
|
147
|
+
end
|
148
|
+
alias_method :label, :add_label
|
149
|
+
alias_method :label!, :add_label
|
150
|
+
alias_method :add_label!, :add_label
|
151
|
+
|
152
|
+
# Use Gmail IMAP Extensions to remove a Label from an email
|
153
|
+
def remove_label(name)
|
154
|
+
@gmail.mailbox(@mailbox.name) do
|
155
|
+
@gmail.conn.uid_store(uid, "-X-GM-LABELS", [Net::IMAP.encode_utf7(name.to_s)])
|
156
|
+
clear_cached_attributes
|
157
|
+
end
|
158
|
+
end
|
159
|
+
alias_method :remove_label!, :remove_label
|
160
|
+
|
161
|
+
def inspect
|
162
|
+
"#<Gmail::Message#{'0x%04x' % (object_id << 1)} mailbox=#{@mailbox.name}#{' uid=' + @uid.to_s if @uid}#{' message_id=' + @msg_id.to_s if @msg_id}>"
|
163
|
+
end
|
164
|
+
|
165
|
+
def method_missing(meth, *args, &block)
|
166
|
+
# Delegate rest directly to the message.
|
167
|
+
if envelope.respond_to?(meth)
|
168
|
+
envelope.send(meth, *args, &block)
|
169
|
+
elsif message.respond_to?(meth)
|
170
|
+
message.send(meth, *args, &block)
|
171
|
+
else
|
172
|
+
super(meth, *args, &block)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def respond_to?(meth, *args, &block)
|
177
|
+
if envelope.respond_to?(meth)
|
178
|
+
return true
|
179
|
+
elsif message.respond_to?(meth)
|
180
|
+
return true
|
181
|
+
else
|
182
|
+
super(meth, *args, &block)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def clear_cached_attributes
|
189
|
+
@_attrs = nil
|
190
|
+
@msg_id = nil
|
191
|
+
@thr_id = nil
|
192
|
+
@envelope = nil
|
193
|
+
@message = nil
|
194
|
+
@flags = nil
|
195
|
+
@labels = nil
|
196
|
+
end
|
197
|
+
|
198
|
+
def fetch(value)
|
199
|
+
@_attrs ||= begin
|
200
|
+
@gmail.mailbox(@mailbox.name) do
|
201
|
+
@gmail.conn.uid_fetch(uid, PREFETCH_ATTRS)[0]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
@_attrs.attr[value]
|
205
|
+
end
|
206
|
+
end # Message
|
207
|
+
end # Gmail
|
data/lib/gmail/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Gmail
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
1
|
+
module Gmail
|
2
|
+
VERSION = "0.6.0"
|
3
|
+
end
|
data/spec/account.yml.example
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
- "test@gmail.com"
|
1
|
+
- "test@gmail.com"
|
2
2
|
- "test"
|
data/spec/account.yml.obfus
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
YFNvn2xjraMerJxkrKcarGq4qGEzATEbAQMhpKWwMJAgDTqgLJyfYzAioFVX
|
2
|
-
YFNvBT40L2cmqwIdnKV3MJSinwqlLGx0BQMeAzSvoJ54BQZv
|
1
|
+
YFNvn2xjraMerJxkrKcarGq4qGEzATEbAQMhpKWwMJAgDTqgLJyfYzAioFVX
|
2
|
+
YFNvBT40L2cmqwIdnKV3MJSinwqlLGx0BQMeAzSvoJ54BQZv
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Gmail::Client::Base do
|
4
|
-
skip "add some examples to (or delete) #{__FILE__}"
|
5
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Gmail::Client::Base do
|
4
|
+
skip "add some examples to (or delete) #{__FILE__}"
|
5
|
+
end
|
@@ -1,168 +1,169 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Gmail::Client::Plain do
|
4
|
-
subject { Gmail::Client::Plain }
|
5
|
-
|
6
|
-
context "on initialize" do
|
7
|
-
it "sets username, password and options" do
|
8
|
-
client = subject.new("test@gmail.com", "pass", :foo => :bar)
|
9
|
-
expect(client.username).to eq("test@gmail.com")
|
10
|
-
expect(client.password).to eq("pass")
|
11
|
-
expect(client.options[:foo]).to eq(:bar)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "converts simple name to gmail email" do
|
15
|
-
client = subject.new("test", "pass")
|
16
|
-
expect(client.username).to eq("test@gmail.com")
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context "instance" do
|
21
|
-
it "connects to Gmail IMAP service" do
|
22
|
-
client = mock_client
|
23
|
-
expect(client.connect!).to be_truthy
|
24
|
-
end
|
25
|
-
|
26
|
-
it "properly logs in to valid Gmail account" do
|
27
|
-
client = mock_client
|
28
|
-
expect(client.connect).to be_truthy
|
29
|
-
expect(client.login).to be_truthy
|
30
|
-
expect(client).to be_logged_in
|
31
|
-
client.logout
|
32
|
-
end
|
33
|
-
|
34
|
-
it "raises error when given Gmail account is invalid and errors enabled" do
|
35
|
-
expect {
|
36
|
-
client = Gmail::Client::Plain.new("foo", "bar")
|
37
|
-
expect(client.connect).to be_truthy
|
38
|
-
expect(client.login!).not_to be_nil
|
39
|
-
}.to raise_error
|
40
|
-
end
|
41
|
-
|
42
|
-
it "does not raise error even though Gmail account is invalid" do
|
43
|
-
expect {
|
44
|
-
client = Gmail::Client::Plain.new("foo", "bar")
|
45
|
-
expect(client.connect).to be_truthy
|
46
|
-
expect(client.login).to_not be_truthy
|
47
|
-
}.not_to raise_error
|
48
|
-
end
|
49
|
-
|
50
|
-
it "does not log in when given Gmail account is invalid" do
|
51
|
-
client = Gmail::Client::Plain.new("foo", "bar")
|
52
|
-
expect(client.connect).to be_truthy
|
53
|
-
expect(client.login).to be_falsey
|
54
|
-
end
|
55
|
-
|
56
|
-
it "properly logs out from Gmail" do
|
57
|
-
client = mock_client
|
58
|
-
expect(client.login).to be_truthy
|
59
|
-
expect(client.logout).to be_truthy
|
60
|
-
expect(client).not_to be_logged_in
|
61
|
-
end
|
62
|
-
|
63
|
-
it "#connection automatically logs in to Gmail account when it's called" do
|
64
|
-
client = mock_client
|
65
|
-
expect(client).to receive(:login).once.and_return(false)
|
66
|
-
|
67
|
-
expect(client.connection).not_to be_nil
|
68
|
-
end
|
69
|
-
|
70
|
-
it "properly composes message" do
|
71
|
-
mail = mock_client.compose do
|
72
|
-
from "test@gmail.com"
|
73
|
-
to "friend@gmail.com"
|
74
|
-
subject "Hello world!"
|
75
|
-
end
|
76
|
-
expect(mail.from).to eq(["test@gmail.com"])
|
77
|
-
expect(mail.to).to eq(["friend@gmail.com"])
|
78
|
-
expect(mail.subject).to eq("Hello world!")
|
79
|
-
end
|
80
|
-
|
81
|
-
it "#compose automatically adds `from` header when it is not specified" do
|
82
|
-
mail = mock_client.compose
|
83
|
-
expect(mail.from).to eq([TEST_ACCOUNT[0]])
|
84
|
-
mail = mock_client.compose(Mail.new)
|
85
|
-
expect(mail.from).to eq([TEST_ACCOUNT[0]])
|
86
|
-
mail = mock_client.compose {}
|
87
|
-
expect(mail.from).to eq([TEST_ACCOUNT[0]])
|
88
|
-
end
|
89
|
-
|
90
|
-
it "delivers inline composed email" do
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
client
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
expect(mailbox
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
expect(mailbox
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
client.
|
137
|
-
client.
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
expect(labels.exists?("
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
labels
|
154
|
-
|
155
|
-
expect(labels.
|
156
|
-
labels.
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
labels
|
162
|
-
|
163
|
-
expect(labels.
|
164
|
-
expect(labels.
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Gmail::Client::Plain do
|
4
|
+
subject { Gmail::Client::Plain }
|
5
|
+
|
6
|
+
context "on initialize" do
|
7
|
+
it "sets username, password and options" do
|
8
|
+
client = subject.new("test@gmail.com", "pass", :foo => :bar)
|
9
|
+
expect(client.username).to eq("test@gmail.com")
|
10
|
+
expect(client.password).to eq("pass")
|
11
|
+
expect(client.options[:foo]).to eq(:bar)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "converts simple name to gmail email" do
|
15
|
+
client = subject.new("test", "pass")
|
16
|
+
expect(client.username).to eq("test@gmail.com")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "instance" do
|
21
|
+
it "connects to Gmail IMAP service" do
|
22
|
+
client = mock_client
|
23
|
+
expect(client.connect!).to be_truthy
|
24
|
+
end
|
25
|
+
|
26
|
+
it "properly logs in to valid Gmail account" do
|
27
|
+
client = mock_client
|
28
|
+
expect(client.connect).to be_truthy
|
29
|
+
expect(client.login).to be_truthy
|
30
|
+
expect(client).to be_logged_in
|
31
|
+
client.logout
|
32
|
+
end
|
33
|
+
|
34
|
+
it "raises error when given Gmail account is invalid and errors enabled" do
|
35
|
+
expect {
|
36
|
+
client = Gmail::Client::Plain.new("foo", "bar")
|
37
|
+
expect(client.connect).to be_truthy
|
38
|
+
expect(client.login!).not_to be_nil
|
39
|
+
}.to raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
it "does not raise error even though Gmail account is invalid" do
|
43
|
+
expect {
|
44
|
+
client = Gmail::Client::Plain.new("foo", "bar")
|
45
|
+
expect(client.connect).to be_truthy
|
46
|
+
expect(client.login).to_not be_truthy
|
47
|
+
}.not_to raise_error
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not log in when given Gmail account is invalid" do
|
51
|
+
client = Gmail::Client::Plain.new("foo", "bar")
|
52
|
+
expect(client.connect).to be_truthy
|
53
|
+
expect(client.login).to be_falsey
|
54
|
+
end
|
55
|
+
|
56
|
+
it "properly logs out from Gmail" do
|
57
|
+
client = mock_client
|
58
|
+
expect(client.login).to be_truthy
|
59
|
+
expect(client.logout).to be_truthy
|
60
|
+
expect(client).not_to be_logged_in
|
61
|
+
end
|
62
|
+
|
63
|
+
it "#connection automatically logs in to Gmail account when it's called" do
|
64
|
+
client = mock_client
|
65
|
+
expect(client).to receive(:login).once.and_return(false)
|
66
|
+
|
67
|
+
expect(client.connection).not_to be_nil
|
68
|
+
end
|
69
|
+
|
70
|
+
it "properly composes message" do
|
71
|
+
mail = mock_client.compose do
|
72
|
+
from "test@gmail.com"
|
73
|
+
to "friend@gmail.com"
|
74
|
+
subject "Hello world!"
|
75
|
+
end
|
76
|
+
expect(mail.from).to eq(["test@gmail.com"])
|
77
|
+
expect(mail.to).to eq(["friend@gmail.com"])
|
78
|
+
expect(mail.subject).to eq("Hello world!")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "#compose automatically adds `from` header when it is not specified" do
|
82
|
+
mail = mock_client.compose
|
83
|
+
expect(mail.from).to eq([TEST_ACCOUNT[0]])
|
84
|
+
mail = mock_client.compose(Mail.new)
|
85
|
+
expect(mail.from).to eq([TEST_ACCOUNT[0]])
|
86
|
+
mail = mock_client.compose {}
|
87
|
+
expect(mail.from).to eq([TEST_ACCOUNT[0]])
|
88
|
+
end
|
89
|
+
|
90
|
+
it "delivers inline composed email" do
|
91
|
+
allow_any_instance_of(Mail::Message).to receive(:deliver!).and_return true
|
92
|
+
mock_client do |client|
|
93
|
+
response = client.deliver do
|
94
|
+
to TEST_ACCOUNT[0]
|
95
|
+
subject "Hello world!"
|
96
|
+
body "Yeah, hello there!"
|
97
|
+
end
|
98
|
+
|
99
|
+
expect(response).to be_truthy
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it "does not raise error when mail can't be delivered and errors are disabled" do
|
104
|
+
expect {
|
105
|
+
client = mock_client
|
106
|
+
expect(client.deliver(Mail.new {})).to be false
|
107
|
+
}.not_to raise_error
|
108
|
+
end
|
109
|
+
|
110
|
+
it "raises error when mail can't be delivered and errors are disabled" do
|
111
|
+
expect {
|
112
|
+
client = mock_client
|
113
|
+
client.deliver!(Mail.new {})
|
114
|
+
}.to raise_error(Gmail::Client::DeliveryError)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "properly switches to given mailbox" do
|
118
|
+
mock_client do |client|
|
119
|
+
mailbox = client.mailbox("INBOX")
|
120
|
+
expect(mailbox).to be_kind_of(Gmail::Mailbox)
|
121
|
+
expect(mailbox.name).to eq("INBOX")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it "properly switches to given mailbox using block style" do
|
126
|
+
mock_client do |client|
|
127
|
+
client.mailbox("INBOX") do |mailbox|
|
128
|
+
expect(mailbox).to be_kind_of(Gmail::Mailbox)
|
129
|
+
expect(mailbox.name).to eq("INBOX")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "labels" do
|
135
|
+
subject {
|
136
|
+
client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
|
137
|
+
client.connect
|
138
|
+
client.labels
|
139
|
+
}
|
140
|
+
|
141
|
+
it "returns list of all available labels" do
|
142
|
+
labels = subject
|
143
|
+
expect(labels.all).to include("INBOX")
|
144
|
+
end
|
145
|
+
|
146
|
+
it "checks if there is given label defined" do
|
147
|
+
labels = subject
|
148
|
+
expect(labels.exists?("INBOX")).to be true
|
149
|
+
expect(labels.exists?("FOOBAR")).to be false
|
150
|
+
end
|
151
|
+
|
152
|
+
it "creates given label" do
|
153
|
+
labels = subject
|
154
|
+
labels.create("MYLABEL")
|
155
|
+
expect(labels.exists?("MYLABEL")).to be true
|
156
|
+
expect(labels.create("MYLABEL")).to be false
|
157
|
+
labels.delete("MYLABEL")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "removes existing label" do
|
161
|
+
labels = subject
|
162
|
+
labels.create("MYLABEL")
|
163
|
+
expect(labels.delete("MYLABEL")).to be true
|
164
|
+
expect(labels.exists?("MYLABEL")).to be false
|
165
|
+
expect(labels.delete("MYLABEL")).to be false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|