ruby-gmail 0.0.1 → 0.0.2
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.
- data.tar.gz.sig +0 -0
- data/History.txt +5 -0
- data/README.txt +1 -1
- data/lib/gmail.rb +6 -6
- data/lib/gmail/mailbox.rb +5 -6
- data/lib/gmail/message.rb +7 -7
- data/lib/ietf/rfc2045.rb +3 -1
- data/lib/mime/entity.rb +5 -6
- metadata +1 -1
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
data/README.txt
CHANGED
@@ -18,7 +18,7 @@ A Rubyesque interface to Gmail. Connect to Gmail via IMAP and manipulate emails
|
|
18
18
|
== SYNOPSIS:
|
19
19
|
|
20
20
|
gmail = Gmail.new(username, password)
|
21
|
-
gmail.inbox.count # => {:
|
21
|
+
gmail.inbox.count # => {:read => 41, :unread => 2}
|
22
22
|
unread = gmail.inbox.emails(:unread)
|
23
23
|
unread[0].archive!
|
24
24
|
unread[1].delete!
|
data/lib/gmail.rb
CHANGED
@@ -3,7 +3,7 @@ require 'net/smtp'
|
|
3
3
|
require 'smtp_tls'
|
4
4
|
|
5
5
|
class Gmail
|
6
|
-
VERSION = '0.0.
|
6
|
+
VERSION = '0.0.2'
|
7
7
|
|
8
8
|
attr_reader :imap
|
9
9
|
|
@@ -15,7 +15,7 @@ class Gmail
|
|
15
15
|
end
|
16
16
|
self
|
17
17
|
end
|
18
|
-
meta.username = username
|
18
|
+
meta.username = username =~ /@/ ? username : username + '@gmail.com'
|
19
19
|
meta.password = password
|
20
20
|
@imap = Net::IMAP.new('imap.gmail.com',993,true)
|
21
21
|
@connected = true if @imap.login(username, password)
|
@@ -40,14 +40,14 @@ class Gmail
|
|
40
40
|
raise ArgumentError, "Must provide a code block" unless block_given?
|
41
41
|
mailbox_stack << mailbox
|
42
42
|
unless @selected == mailbox.name
|
43
|
-
@
|
43
|
+
@imap.select(mailbox.name)
|
44
44
|
@selected = mailbox.name
|
45
45
|
end
|
46
46
|
value = block.arity == 1 ? block.call(mailbox) : block.call
|
47
47
|
mailbox_stack.pop
|
48
48
|
# Select previously selected mailbox if there is one
|
49
49
|
if mailbox_stack.last
|
50
|
-
@
|
50
|
+
@imap.select(mailbox_stack.last.name)
|
51
51
|
@selected = mailbox.name
|
52
52
|
end
|
53
53
|
return value
|
@@ -60,7 +60,7 @@ class Gmail
|
|
60
60
|
Net::SMTP.start('smtp.gmail.com', 587, 'localhost.localdomain', meta.username, meta.password, 'plain', true) do |smtp|
|
61
61
|
puts "SMTP open."
|
62
62
|
block.call(lambda {|to, body|
|
63
|
-
from = meta.username
|
63
|
+
from = meta.username
|
64
64
|
puts "Sending from #{from} to #{to}:\n#{body}"
|
65
65
|
smtp.send_message(body, from, to)
|
66
66
|
})
|
@@ -72,7 +72,7 @@ class Gmail
|
|
72
72
|
def send_email(to, body=nil)
|
73
73
|
meta = class << self; self end
|
74
74
|
if to.is_a?(MIME::Message)
|
75
|
-
to.headers['from'] = meta.username
|
75
|
+
to.headers['from'] = meta.username
|
76
76
|
body = to.to_s
|
77
77
|
to = to.to
|
78
78
|
end
|
data/lib/gmail/mailbox.rb
CHANGED
@@ -4,7 +4,7 @@ class Gmail
|
|
4
4
|
|
5
5
|
def initialize(gmail, name)
|
6
6
|
@gmail = gmail
|
7
|
-
@name = name
|
7
|
+
@name = name
|
8
8
|
end
|
9
9
|
|
10
10
|
def inspect
|
@@ -24,14 +24,13 @@ class Gmail
|
|
24
24
|
:read => ['SEEN']
|
25
25
|
}
|
26
26
|
# puts "Gathering #{(aliases[key] || key).inspect} messages for mailbox '#{name}'..."
|
27
|
-
@gmail.in_mailbox(
|
27
|
+
@gmail.in_mailbox(self) do
|
28
28
|
@gmail.imap.uid_search(aliases[key] || key).collect { |uid| messages[uid] ||= Message.new(@gmail, self, uid) }
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
32
|
+
def messages
|
33
|
+
@messages ||= {}
|
34
|
+
end
|
36
35
|
end
|
37
36
|
end
|
data/lib/gmail/message.rb
CHANGED
@@ -7,7 +7,7 @@ class Gmail
|
|
7
7
|
@uid = uid
|
8
8
|
end
|
9
9
|
def inspect
|
10
|
-
"<#Message:#{object_id} mailbox=#{mailbox.name}#{' uid='+@uid if @uid}#{' message_id='+@message_id if @message_id}>"
|
10
|
+
"<#Message:#{object_id} mailbox=#{@mailbox.name}#{' uid='+@uid.to_s if @uid}#{' message_id='+@message_id.to_s if @message_id}>"
|
11
11
|
end
|
12
12
|
|
13
13
|
# Auto IMAP info
|
@@ -16,14 +16,14 @@ class Gmail
|
|
16
16
|
end
|
17
17
|
def message_id
|
18
18
|
@message_id || begin
|
19
|
-
@gmail.in_mailbox(@mailbox
|
19
|
+
@gmail.in_mailbox(@mailbox) do
|
20
20
|
@message_id = @gmail.imap.uid_fetch(@uid, ['ENVELOPE'])[0].attr['ENVELOPE'].message_id
|
21
21
|
end
|
22
22
|
end
|
23
23
|
@message_id
|
24
24
|
end
|
25
25
|
def body
|
26
|
-
@body ||= @gmail.in_mailbox(@mailbox
|
26
|
+
@body ||= @gmail.in_mailbox(@mailbox) do
|
27
27
|
@gmail.imap.uid_fetch(uid, "RFC822")[0].attr["RFC822"]
|
28
28
|
end
|
29
29
|
end
|
@@ -35,12 +35,12 @@ class Gmail
|
|
35
35
|
|
36
36
|
# IMAP Operations
|
37
37
|
def flag(flg)
|
38
|
-
@gmail.in_mailbox(@mailbox
|
38
|
+
@gmail.in_mailbox(@mailbox) do
|
39
39
|
@gmail.imap.uid_store(uid, "+FLAGS", [flg])
|
40
40
|
end
|
41
41
|
end
|
42
42
|
def unflag(flg)
|
43
|
-
@gmail.in_mailbox(@mailbox
|
43
|
+
@gmail.in_mailbox(@mailbox) do
|
44
44
|
@gmail.imap.uid_store(uid, "-FLAGS", [flg])
|
45
45
|
end
|
46
46
|
end
|
@@ -63,8 +63,8 @@ class Gmail
|
|
63
63
|
flag(:Deleted)
|
64
64
|
end
|
65
65
|
def label(name)
|
66
|
-
@gmail.in_mailbox(@mailbox
|
67
|
-
|
66
|
+
@gmail.in_mailbox(@mailbox) do
|
67
|
+
@gmail.imap.uid_copy(uid, name)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
# We're not sure of any 'labels' except the 'mailbox' we're in at the moment.
|
data/lib/ietf/rfc2045.rb
CHANGED
@@ -17,7 +17,9 @@ module IETF
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.parse_rfc2045_content_from(raw, boundary)
|
20
|
-
raw.split(/#{CRLF.source}--#{boundary}(?:--)?(?:#{CRLF.source}|$)/)
|
20
|
+
parts = raw.split(/#{CRLF.source}--#{boundary}(?:--)?(?:#{CRLF.source}|$)/)
|
21
|
+
parts.reject! {|p| p.gsub(/^[ \r\n#{HTAB}]?$/,'') == ''} # Remove any parts that are blank
|
22
|
+
parts.collect {|part|
|
21
23
|
IETF::RFC2045.parse_rfc2045_from(part)
|
22
24
|
}
|
23
25
|
end
|
data/lib/mime/entity.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ietf/rfc2045'
|
1
2
|
String::ALPHANUMERIC_CHARACTERS = ('a'..'z').to_a + ('A'..'Z').to_a unless defined? String::ALPHANUMERIC_CHARACTERS
|
2
3
|
def String.random(size)
|
3
4
|
length = String::ALPHANUMERIC_CHARACTERS.length
|
@@ -32,7 +33,6 @@ module MIME
|
|
32
33
|
def from_parsed(parsed)
|
33
34
|
case parsed
|
34
35
|
when Array
|
35
|
-
puts "Parsed: #{parsed[0].class.name}, #{parsed[1].class.name}"
|
36
36
|
if parsed[0].is_a?(Hash) && (parsed[1].is_a?(Hash) || parsed[1].is_a?(String))
|
37
37
|
@headers = parsed[0]
|
38
38
|
@content = parsed[1].is_a?(Hash) ? parsed[1][:content].collect {|p| Entity.new.from_parsed(p)} : parsed[1]
|
@@ -41,15 +41,14 @@ module MIME
|
|
41
41
|
@multipart_boundary = parsed[1][:boundary]
|
42
42
|
end
|
43
43
|
else
|
44
|
-
|
44
|
+
raise "IETF PARSING FAIL!"
|
45
45
|
end
|
46
46
|
return self
|
47
47
|
when Hash
|
48
|
-
puts "Parsed: #{parsed.keys.sort.inspect}"
|
49
48
|
if parsed.has_key?(:type) && parsed.has_key?(:boundary) && parsed.has_key?(:content)
|
50
49
|
@content = parsed[:content].is_a?(Array) ? parsed[:content].collect {|p| Entity.new.from_parsed(p)} : parsed[:content]
|
51
50
|
else
|
52
|
-
|
51
|
+
raise "IETF PARSING FAIL!"
|
53
52
|
end
|
54
53
|
return self
|
55
54
|
end
|
@@ -153,7 +152,7 @@ module MIME
|
|
153
152
|
# Converts this data structure into a string, but decoded if necessary
|
154
153
|
def decoded_content
|
155
154
|
return nil if @content.is_a?(Array)
|
156
|
-
case encoding
|
155
|
+
case encoding.downcase
|
157
156
|
when 'quoted-printable'
|
158
157
|
@content.unpack('M')[0]
|
159
158
|
when 'base64'
|
@@ -166,7 +165,7 @@ module MIME
|
|
166
165
|
# You can set new content, and it will be saved in encoded form.
|
167
166
|
def content=(raw)
|
168
167
|
@content = raw.is_a?(Array) ? raw :
|
169
|
-
case encoding
|
168
|
+
case encoding.downcase
|
170
169
|
when 'quoted-printable'
|
171
170
|
[raw].pack('M')
|
172
171
|
when 'base64'
|
metadata
CHANGED
metadata.gz.sig
CHANGED
Binary file
|