ruby-gmail 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|