gmail 0.4.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,164 +1,166 @@
1
- require 'mime/message'
2
-
3
- module Gmail
4
- class Message
5
- # Raised when given label doesn't exists.
6
- class NoLabelError < Exception; end
7
-
8
- attr_reader :uid
9
-
10
- def initialize(mailbox, uid)
11
- @uid = uid
12
- @mailbox = mailbox
13
- @gmail = mailbox.instance_variable_get("@gmail") if mailbox
14
- end
15
-
16
- def uid
17
- @uid ||= @gmail.conn.uid_search(['HEADER', 'Message-ID', message_id])[0]
18
- end
19
-
20
- # Mark message with given flag.
21
- def flag(name)
22
- !!@gmail.mailbox(@mailbox.name) { @gmail.conn.uid_store(uid, "+FLAGS", [name]) }
23
- end
24
-
25
- # Unmark message.
26
- def unflag(name)
27
- !!@gmail.mailbox(@mailbox.name) { @gmail.conn.uid_store(uid, "-FLAGS", [name]) }
28
- end
29
-
30
- # Do commonly used operations on message.
31
- def mark(flag)
32
- case flag
33
- when :read then read!
34
- when :unread then unread!
35
- when :deleted then delete!
36
- when :spam then spam!
37
- else
38
- flag(flag)
39
- end
40
- end
41
-
42
- # Mark this message as a spam.
43
- def spam!
44
- move_to('[Gmail]/Spam')
45
- end
46
-
47
- # Mark as read.
48
- def read!
49
- flag(:Seen)
50
- end
51
-
52
- # Mark as unread.
53
- def unread!
54
- unflag(:Seen)
55
- end
56
-
57
- # Mark message with star.
58
- def star!
59
- flag('[Gmail]/Starred')
60
- end
61
-
62
- # Remove message from list of starred.
63
- def unstar!
64
- unflag('[Gmail]/Starred')
65
- end
66
-
67
- # Move to trash / bin.
68
- def delete!
69
- @mailbox.messages.delete(uid)
70
- flag(:deleted)
71
-
72
- # For some, it's called "Trash", for others, it's called "Bin". Support both.
73
- trash = @gmail.labels.exist?('[Gmail]/Bin') ? '[Gmail]/Bin' : '[Gmail]/Trash'
74
- move_to(trash) unless %w[[Gmail]/Spam [Gmail]/Bin [Gmail]/Trash].include?(@mailbox.name)
75
- end
76
-
77
- # Archive this message.
78
- def archive!
79
- move_to('[Gmail]/All Mail')
80
- end
81
-
82
- # Move to given box and delete from others.
83
- def move_to(name, from=nil)
84
- label(name, from)
85
- delete! if !%w[[Gmail]/Bin [Gmail]/Trash].include?(name)
86
- end
87
- alias :move :move_to
88
-
89
- # Move message to given and delete from others. When given mailbox doesn't
90
- # exist then it will be automaticaly created.
91
- def move_to!(name, from=nil)
92
- label!(name, from) && delete!
93
- end
94
- alias :move! :move_to!
95
-
96
- # Mark this message with given label. When given label doesn't exist then
97
- # it will raise <tt>NoLabelError</tt>.
98
- #
99
- # See also <tt>Gmail::Message#label!</tt>.
100
- def label(name, from=nil)
101
- @gmail.mailbox(Net::IMAP.encode_utf7(from || @mailbox.external_name)) { @gmail.conn.uid_copy(uid, Net::IMAP.encode_utf7(name)) }
102
- rescue Net::IMAP::NoResponseError
103
- raise NoLabelError, "Label '#{name}' doesn't exist!"
104
- end
105
-
106
- # Mark this message with given label. When given label doesn't exist then
107
- # it will be automaticaly created.
108
- #
109
- # See also <tt>Gmail::Message#label</tt>.
110
- def label!(name, from=nil)
111
- label(name, from)
112
- rescue NoLabelError
113
- @gmail.labels.add(Net::IMAP.encode_utf7(name))
114
- label(name, from)
115
- end
116
- alias :add_label :label!
117
- alias :add_label! :label!
118
-
119
- # Remove given label from this message.
120
- def remove_label!(name)
121
- move_to('[Gmail]/All Mail', name)
122
- end
123
- alias :delete_label! :remove_label!
124
-
125
- def inspect
126
- "#<Gmail::Message#{'0x%04x' % (object_id << 1)} mailbox=#{@mailbox.external_name}#{' uid='+@uid.to_s if @uid}#{' message_id='+@message_id.to_s if @message_id}>"
127
- end
128
-
129
- def method_missing(meth, *args, &block)
130
- # Delegate rest directly to the message.
131
- if envelope.respond_to?(meth)
132
- envelope.send(meth, *args, &block)
133
- elsif message.respond_to?(meth)
134
- message.send(meth, *args, &block)
135
- else
136
- super(meth, *args, &block)
137
- end
138
- end
139
-
140
- def respond_to?(meth, *args, &block)
141
- if envelope.respond_to?(meth)
142
- return true
143
- elsif message.respond_to?(meth)
144
- return true
145
- else
146
- super(meth, *args, &block)
147
- end
148
- end
149
-
150
- def envelope
151
- @envelope ||= @gmail.mailbox(@mailbox.name) {
152
- @gmail.conn.uid_fetch(uid, "ENVELOPE")[0].attr["ENVELOPE"]
153
- }
154
- end
155
-
156
- def message
157
- @message ||= Mail.new(@gmail.mailbox(@mailbox.name) {
158
- @gmail.conn.uid_fetch(uid, "RFC822")[0].attr["RFC822"] # RFC822
159
- })
160
- end
161
- alias_method :raw_message, :message
162
-
163
- end # Message
164
- end # Gmail
1
+ module Gmail
2
+ class Message
3
+ # Raised when given label doesn't exists.
4
+ class NoLabelError < Exception; end
5
+
6
+ attr_reader :uid
7
+
8
+ def initialize(mailbox, uid)
9
+ @uid = uid
10
+ @mailbox = mailbox
11
+ @gmail = mailbox.instance_variable_get("@gmail") if mailbox
12
+ end
13
+
14
+ def labels
15
+ @gmail.conn.uid_fetch(uid, "X-GM-LABELS")[0].attr["X-GM-LABELS"]
16
+ end
17
+
18
+ def uid
19
+ @uid ||= @gmail.conn.uid_search(['HEADER', 'Message-ID', message_id])[0]
20
+ end
21
+
22
+ # Mark message with given flag.
23
+ def flag(name)
24
+ !!@gmail.mailbox(@mailbox.name) { @gmail.conn.uid_store(uid, "+FLAGS", [name]) }
25
+ end
26
+
27
+ # Unmark message.
28
+ def unflag(name)
29
+ !!@gmail.mailbox(@mailbox.name) { @gmail.conn.uid_store(uid, "-FLAGS", [name]) }
30
+ end
31
+
32
+ # Do commonly used operations on message.
33
+ def mark(flag)
34
+ case flag
35
+ when :read then read!
36
+ when :unread then unread!
37
+ when :deleted then delete!
38
+ when :spam then spam!
39
+ else
40
+ flag(flag)
41
+ end
42
+ end
43
+
44
+ # Mark this message as a spam.
45
+ def spam!
46
+ move_to('[Gmail]/Spam')
47
+ end
48
+
49
+ # Mark as read.
50
+ def read!
51
+ flag(:Seen)
52
+ end
53
+
54
+ # Mark as unread.
55
+ def unread!
56
+ unflag(:Seen)
57
+ end
58
+
59
+ # Mark message with star.
60
+ def star!
61
+ flag('[Gmail]/Starred')
62
+ end
63
+
64
+ # Remove message from list of starred.
65
+ def unstar!
66
+ unflag('[Gmail]/Starred')
67
+ end
68
+
69
+ # Move to trash / bin.
70
+ def delete!
71
+ @mailbox.messages.delete(uid)
72
+ flag(:deleted)
73
+
74
+ # For some, it's called "Trash", for others, it's called "Bin". Support both.
75
+ trash = @gmail.labels.exist?('[Gmail]/Bin') ? '[Gmail]/Bin' : '[Gmail]/Trash'
76
+ move_to(trash) unless %w[[Gmail]/Spam [Gmail]/Bin [Gmail]/Trash].include?(@mailbox.name)
77
+ end
78
+
79
+ # Archive this message.
80
+ def archive!
81
+ move_to('[Gmail]/All Mail')
82
+ end
83
+
84
+ # Move to given box and delete from others.
85
+ def move_to(name, from=nil)
86
+ label(name, from)
87
+ delete! if !%w[[Gmail]/Bin [Gmail]/Trash].include?(name)
88
+ end
89
+ alias :move :move_to
90
+
91
+ # Move message to given and delete from others. When given mailbox doesn't
92
+ # exist then it will be automaticaly created.
93
+ def move_to!(name, from=nil)
94
+ label!(name, from) && delete!
95
+ end
96
+ alias :move! :move_to!
97
+
98
+ # Mark this message with given label. When given label doesn't exist then
99
+ # it will raise <tt>NoLabelError</tt>.
100
+ #
101
+ # See also <tt>Gmail::Message#label!</tt>.
102
+ def label(name, from=nil)
103
+ @gmail.mailbox(Net::IMAP.encode_utf7(from || @mailbox.external_name)) { @gmail.conn.uid_copy(uid, Net::IMAP.encode_utf7(name)) }
104
+ rescue Net::IMAP::NoResponseError
105
+ raise NoLabelError, "Label '#{name}' doesn't exist!"
106
+ end
107
+
108
+ # Mark this message with given label. When given label doesn't exist then
109
+ # it will be automaticaly created.
110
+ #
111
+ # See also <tt>Gmail::Message#label</tt>.
112
+ def label!(name, from=nil)
113
+ label(name, from)
114
+ rescue NoLabelError
115
+ @gmail.labels.add(Net::IMAP.encode_utf7(name))
116
+ label(name, from)
117
+ end
118
+ alias :add_label :label!
119
+ alias :add_label! :label!
120
+
121
+ # Remove given label from this message.
122
+ def remove_label!(name)
123
+ move_to('[Gmail]/All Mail', name)
124
+ end
125
+ alias :delete_label! :remove_label!
126
+
127
+ def inspect
128
+ "#<Gmail::Message#{'0x%04x' % (object_id << 1)} mailbox=#{@mailbox.external_name}#{' uid='+@uid.to_s if @uid}#{' message_id='+@message_id.to_s if @message_id}>"
129
+ end
130
+
131
+ def method_missing(meth, *args, &block)
132
+ # Delegate rest directly to the message.
133
+ if envelope.respond_to?(meth)
134
+ envelope.send(meth, *args, &block)
135
+ elsif message.respond_to?(meth)
136
+ message.send(meth, *args, &block)
137
+ else
138
+ super(meth, *args, &block)
139
+ end
140
+ end
141
+
142
+ def respond_to?(meth, *args, &block)
143
+ if envelope.respond_to?(meth)
144
+ return true
145
+ elsif message.respond_to?(meth)
146
+ return true
147
+ else
148
+ super(meth, *args, &block)
149
+ end
150
+ end
151
+
152
+ def envelope
153
+ @envelope ||= @gmail.mailbox(@mailbox.name) {
154
+ @gmail.conn.uid_fetch(uid, "ENVELOPE")[0].attr["ENVELOPE"]
155
+ }
156
+ end
157
+
158
+ def message
159
+ @message ||= Mail.new(@gmail.mailbox(@mailbox.name) {
160
+ @gmail.conn.uid_fetch(uid, "RFC822")[0].attr["RFC822"] # RFC822
161
+ })
162
+ end
163
+ alias_method :raw_message, :message
164
+
165
+ end # Message
166
+ end # Gmail
@@ -1,12 +1,3 @@
1
- module Gmail
2
- class Version #:nodoc:
3
- MAJOR = 0
4
- MINOR = 4
5
- PATCH = 0
6
- STRING = [MAJOR, MINOR, PATCH].join('.')
7
- end # Version
8
-
9
- def self.version # :nodoc:
10
- Version::STRING
11
- end
12
- end # Gmail
1
+ module Gmail
2
+ VERSION = "0.4.2"
3
+ end # Gmail
@@ -1,2 +1,2 @@
1
- - "test@gmail.com"
1
+ - "test@gmail.com"
2
2
  - "test"
@@ -1,173 +1,178 @@
1
- require 'spec_helper'
2
-
3
- describe "Gmail client (Plain)" do
4
- subject { Gmail::Client::Plain }
5
-
6
- context "on initialize" do
7
- it "should set username, password and options" do
8
- client = subject.new("test@gmail.com", "pass", :foo => :bar)
9
- client.username.should == "test@gmail.com"
10
- client.password.should == "pass"
11
- client.options[:foo].should == :bar
12
- end
13
-
14
- it "should convert simple name to gmail email" do
15
- client = subject.new("test", "pass")
16
- client.username.should == "test@gmail.com"
17
- end
18
- end
19
-
20
- context "instance" do
21
- def mock_client(&block)
22
- client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
23
- if block_given?
24
- client.connect
25
- yield client
26
- client.logout
27
- end
28
- client
29
- end
30
-
31
- it "should connect to GMail IMAP service" do
32
- lambda {
33
- client = mock_client
34
- client.connect!.should be_true
35
- }.should_not raise_error(Gmail::Client::ConnectionError)
36
- end
37
-
38
- it "should properly login to valid GMail account" do
39
- client = mock_client
40
- client.connect.should be_true
41
- client.login.should be_true
42
- client.should be_logged_in
43
- client.logout
44
- end
45
-
46
- it "should raise error when given GMail account is invalid and errors enabled" do
47
- lambda {
48
- client = Gmail::Client::Plain.new("foo", "bar")
49
- client.connect.should be_true
50
- client.login!.should_not be_true
51
- }.should raise_error(Gmail::Client::AuthorizationError)
52
- end
53
-
54
- it "shouldn't login when given GMail account is invalid" do
55
- lambda {
56
- client = Gmail::Client::Plain.new("foo", "bar")
57
- client.connect.should be_true
58
- client.login.should_not be_true
59
- }.should_not raise_error(Gmail::Client::AuthorizationError)
60
- end
61
-
62
- it "should properly logout from GMail" do
63
- client = mock_client
64
- client.connect
65
- client.login.should be_true
66
- client.logout.should be_true
67
- client.should_not be_logged_in
68
- end
69
-
70
- it "#connection should automatically log in to GMail account when it's called" do
71
- mock_client do |client|
72
- client.expects(:login).once.returns(false)
73
- client.connection.should_not be_nil
74
- end
75
- end
76
-
77
- it "should properly compose message" do
78
- mail = mock_client.compose do
79
- from "test@gmail.com"
80
- to "friend@gmail.com"
81
- subject "Hello world!"
82
- end
83
- mail.from.should == ["test@gmail.com"]
84
- mail.to.should == ["friend@gmail.com"]
85
- mail.subject.should == "Hello world!"
86
- end
87
-
88
- it "#compose should automatically add `from` header when it is not specified" do
89
- mail = mock_client.compose
90
- mail.from.should == [TEST_ACCOUNT[0]]
91
- mail = mock_client.compose(Mail.new)
92
- mail.from.should == [TEST_ACCOUNT[0]]
93
- mail = mock_client.compose {}
94
- mail.from.should == [TEST_ACCOUNT[0]]
95
- end
96
-
97
- it "should deliver inline composed email" do
98
- mock_client do |client|
99
- client.deliver do
100
- to TEST_ACCOUNT[0]
101
- subject "Hello world!"
102
- body "Yeah, hello there!"
103
- end.should be_true
104
- end
105
- end
106
-
107
- it "should not raise error when mail can't be delivered and errors are disabled" do
108
- lambda {
109
- client = mock_client
110
- client.deliver(Mail.new {}).should be_false
111
- }.should_not raise_error(Gmail::Client::DeliveryError)
112
- end
113
-
114
- it "should raise error when mail can't be delivered and errors are disabled" do
115
- lambda {
116
- client = mock_client
117
- client.deliver!(Mail.new {})
118
- }.should raise_error(Gmail::Client::DeliveryError)
119
- end
120
-
121
- it "should properly switch to given mailbox" do
122
- mock_client do |client|
123
- mailbox = client.mailbox("TEST")
124
- mailbox.should be_kind_of(Gmail::Mailbox)
125
- mailbox.name.should == "TEST"
126
- end
127
- end
128
-
129
- it "should properly switch to given mailbox using block style" do
130
- mock_client do |client|
131
- client.mailbox("TEST") do |mailbox|
132
- mailbox.should be_kind_of(Gmail::Mailbox)
133
- mailbox.name.should == "TEST"
134
- end
135
- end
136
- end
137
-
138
- context "labels" do
139
- subject {
140
- client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
141
- client.connect
142
- client.labels
143
- }
144
-
145
- it "should get list of all available labels" do
146
- labels = subject
147
- labels.all.should include("TEST", "INBOX")
148
- end
149
-
150
- it "should be able to check if there is given label defined" do
151
- labels = subject
152
- labels.exists?("TEST").should be_true
153
- labels.exists?("FOOBAR").should be_false
154
- end
155
-
156
- it "should be able to create given label" do
157
- labels = subject
158
- labels.create("MYLABEL")
159
- labels.exists?("MYLABEL").should be_true
160
- labels.create("MYLABEL").should be_false
161
- labels.delete("MYLABEL")
162
- end
163
-
164
- it "should be able to remove existing label" do
165
- labels = subject
166
- labels.create("MYLABEL")
167
- labels.delete("MYLABEL").should be_true
168
- labels.exists?("MYLABEL").should be_false
169
- labels.delete("MYLABEL").should be_false
170
- end
171
- end
172
- end
173
- 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 "should set username, password and options" do
8
+ client = subject.new("test@gmail.com", "pass", :foo => :bar)
9
+ client.username.should == "test@gmail.com"
10
+ client.password.should == "pass"
11
+ client.options[:foo].should == :bar
12
+ end
13
+
14
+ it "should convert simple name to gmail email" do
15
+ client = subject.new("test", "pass")
16
+ client.username.should == "test@gmail.com"
17
+ end
18
+ end
19
+
20
+ context "instance" do
21
+ def mock_client(&block)
22
+ client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
23
+ if block_given?
24
+ client.connect
25
+ yield client
26
+ client.logout
27
+ end
28
+ client
29
+ end
30
+
31
+ it "should connect to GMail IMAP service" do
32
+ client = mock_client
33
+ client.connect!.should be_true
34
+ end
35
+
36
+ it "should properly login to valid GMail account" do
37
+ client = mock_client
38
+ client.connect.should be_true
39
+ client.login.should be_true
40
+ client.should be_logged_in
41
+ client.logout
42
+ end
43
+
44
+ it "should raise error when given GMail account is invalid and errors enabled" do
45
+ lambda {
46
+ client = Gmail::Client::Plain.new("foo", "bar")
47
+ client.connect.should be_true
48
+ client.login!.should_not be_nil
49
+ }.should raise_error
50
+ ### FIX: can someone dig to the bottom of this? We are getting NoMethodError instead of Gmail::Client::AuthorizationError in 1.9
51
+ end
52
+
53
+ it "shouldn't raise error even though GMail account is invalid" do
54
+ lambda {
55
+ client = Gmail::Client::Plain.new("foo", "bar")
56
+ client.connect.should be_true
57
+ expect(client.login).to_not be_true
58
+ }.should_not raise_error
59
+ end
60
+
61
+ it "shouldn't login when given GMail account is invalid" do
62
+ client = Gmail::Client::Plain.new("foo", "bar")
63
+ client.connect.should be_true
64
+ client.login.should be_false
65
+ end
66
+
67
+ it "should properly logout from GMail" do
68
+ client = mock_client
69
+ client.connect
70
+ client.login.should be_true
71
+ client.logout.should be_true
72
+ client.should_not be_logged_in
73
+ end
74
+
75
+ it "#connection should automatically log in to GMail account when it's called" do
76
+ mock_client do |client|
77
+ client.expects(:login).once.returns(false)
78
+ client.connection.should_not be_nil
79
+ end
80
+ end
81
+
82
+ it "should properly compose message" do
83
+ mail = mock_client.compose do
84
+ from "test@gmail.com"
85
+ to "friend@gmail.com"
86
+ subject "Hello world!"
87
+ end
88
+ mail.from.should == ["test@gmail.com"]
89
+ mail.to.should == ["friend@gmail.com"]
90
+ mail.subject.should == "Hello world!"
91
+ end
92
+
93
+ it "#compose should automatically add `from` header when it is not specified" do
94
+ mail = mock_client.compose
95
+ mail.from.should == [TEST_ACCOUNT[0]]
96
+ mail = mock_client.compose(Mail.new)
97
+ mail.from.should == [TEST_ACCOUNT[0]]
98
+ mail = mock_client.compose {}
99
+ mail.from.should == [TEST_ACCOUNT[0]]
100
+ end
101
+
102
+ it "should deliver inline composed email" do
103
+ mock_client do |client|
104
+ client.deliver do
105
+ to TEST_ACCOUNT[0]
106
+ subject "Hello world!"
107
+ body "Yeah, hello there!"
108
+ end.should be_true
109
+ end
110
+ end
111
+
112
+ it "should not raise error when mail can't be delivered and errors are disabled" do
113
+ lambda {
114
+ client = mock_client
115
+ client.deliver(Mail.new {}).should be_false
116
+ }.should_not raise_error
117
+ end
118
+
119
+ it "should raise error when mail can't be delivered and errors are disabled" do
120
+ lambda {
121
+ client = mock_client
122
+ client.deliver!(Mail.new {})
123
+ }.should raise_error(Gmail::Client::DeliveryError)
124
+ end
125
+
126
+ it "should properly switch to given mailbox" do
127
+ mock_client do |client|
128
+ mailbox = client.mailbox("INBOX")
129
+ mailbox.should be_kind_of(Gmail::Mailbox)
130
+ mailbox.name.should == "INBOX"
131
+ end
132
+ end
133
+
134
+ it "should properly switch to given mailbox using block style" do
135
+ mock_client do |client|
136
+ client.mailbox("INBOX") do |mailbox|
137
+ mailbox.should be_kind_of(Gmail::Mailbox)
138
+ mailbox.name.should == "INBOX"
139
+ end
140
+ end
141
+ end
142
+
143
+ context "labels" do
144
+ subject {
145
+ client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
146
+ client.connect
147
+ client.labels
148
+ }
149
+
150
+ it "should get list of all available labels" do
151
+ labels = subject
152
+ labels.all.should include("INBOX")
153
+ end
154
+
155
+ it "should be able to check if there is given label defined" do
156
+ labels = subject
157
+ labels.exists?("INBOX").should be_true
158
+ labels.exists?("FOOBAR").should be_false
159
+ end
160
+
161
+ it "should be able to create given label" do
162
+ labels = subject
163
+ labels.create("MYLABEL")
164
+ labels.exists?("MYLABEL").should be_true
165
+ labels.create("MYLABEL").should be_false
166
+ labels.delete("MYLABEL")
167
+ end
168
+
169
+ it "should be able to remove existing label" do
170
+ labels = subject
171
+ labels.create("MYLABEL")
172
+ labels.delete("MYLABEL").should be_true
173
+ labels.exists?("MYLABEL").should be_false
174
+ labels.delete("MYLABEL").should be_false
175
+ end
176
+ end
177
+ end
178
+ end