gmail 0.5.0 → 0.6.0
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.
- 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
|