imap_to_rss 1.0.1 → 1.1
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/.autotest +14 -18
- data/History.txt +13 -0
- data/Manifest.txt +6 -0
- data/Rakefile +12 -8
- data/lib/imap_to_rss.rb +7 -7
- data/lib/imap_to_rss/handler/amazon.rb +20 -15
- data/lib/imap_to_rss/handler/hsbc.rb +58 -29
- data/lib/imap_to_rss/handler/itunes.rb +49 -0
- data/lib/imap_to_rss/test_case.rb +66 -0
- data/test/test_imap_to_rss_handler_amazon.rb +737 -0
- data/test/test_imap_to_rss_handler_hsbc.rb +134 -0
- data/test/test_imap_to_rss_handler_itunes.rb +104 -0
- data/test/test_imap_to_rss_handler_ups.rb +72 -0
- metadata +15 -6
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/.autotest
CHANGED
@@ -2,22 +2,18 @@
|
|
2
2
|
|
3
3
|
require 'autotest/restart'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# end
|
5
|
+
Autotest.add_hook :initialize do |at|
|
6
|
+
|
7
|
+
at.testlib = 'minitest/unit'
|
8
|
+
|
9
|
+
def at.path_to_classname(s)
|
10
|
+
sep = File::SEPARATOR
|
11
|
+
f = s.sub(/^test#{sep}/, '').sub(/\.rb$/, '').split(sep)
|
12
|
+
f = f.map { |path| path.split(/_|(\d+)/).map { |seg| seg.capitalize }.join }
|
13
|
+
f = f.map { |path| path =~ /^Test/ ? path : "Test#{path}" }
|
14
|
+
name = f.join('::').sub 'ImapToRss', 'IMAPToRSS'
|
15
|
+
name.sub 'Hsbc', 'HSBC'
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
20
19
|
|
21
|
-
# Autotest.add_hook :run_command do |at|
|
22
|
-
# system "rake build"
|
23
|
-
# end
|
data/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
=== 1.1 / 2009-09-01
|
2
|
+
|
3
|
+
* 1 major enhancement
|
4
|
+
* Added iTunes handler
|
5
|
+
|
6
|
+
* 1 bug fix
|
7
|
+
* Fixed various bugs in the Amazon handler
|
8
|
+
|
9
|
+
=== 1.0.2 / 2009-05-21
|
10
|
+
|
11
|
+
* 1 bug fix
|
12
|
+
* Don't crash when found messages weren't handled
|
13
|
+
|
1
14
|
=== 1.0.1 / 2009-05-18
|
2
15
|
|
3
16
|
* 1 bug fix
|
data/Manifest.txt
CHANGED
@@ -8,4 +8,10 @@ lib/imap_to_rss.rb
|
|
8
8
|
lib/imap_to_rss/handler.rb
|
9
9
|
lib/imap_to_rss/handler/amazon.rb
|
10
10
|
lib/imap_to_rss/handler/hsbc.rb
|
11
|
+
lib/imap_to_rss/handler/itunes.rb
|
11
12
|
lib/imap_to_rss/handler/ups.rb
|
13
|
+
lib/imap_to_rss/test_case.rb
|
14
|
+
test/test_imap_to_rss_handler_amazon.rb
|
15
|
+
test/test_imap_to_rss_handler_hsbc.rb
|
16
|
+
test/test_imap_to_rss_handler_itunes.rb
|
17
|
+
test/test_imap_to_rss_handler_ups.rb
|
data/Rakefile
CHANGED
@@ -2,16 +2,20 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
|
-
$:.unshift 'lib'
|
6
|
-
require 'imap_to_rss'
|
7
5
|
|
8
|
-
Hoe.
|
9
|
-
itor.rubyforge_name = 'seattlerb'
|
10
|
-
itor.developer 'Eric Hodel', 'drbrain@example.com'
|
6
|
+
Hoe.add_include_dirs "../../imap_processor/dev/lib"
|
11
7
|
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
Hoe.plugin :seattlerb
|
9
|
+
|
10
|
+
Hoe.spec 'imap_to_rss' do
|
11
|
+
developer 'Eric Hodel', 'drbrain@example.com'
|
12
|
+
|
13
|
+
self.rubyforge_name = 'seattlerb'
|
14
|
+
self.testlib = :minitest
|
15
|
+
|
16
|
+
extra_deps << ['imap_processor', '~> 1.1']
|
17
|
+
extra_deps << ['nokogiri', '~> 1.2']
|
18
|
+
extra_deps << ['tmail', '~> 1.2']
|
15
19
|
end
|
16
20
|
|
17
21
|
# vim: syntax=Ruby
|
data/lib/imap_to_rss.rb
CHANGED
@@ -14,7 +14,7 @@ class IMAPToRSS < IMAPProcessor
|
|
14
14
|
##
|
15
15
|
# The version of IMAPToRSS you are using
|
16
16
|
|
17
|
-
VERSION = '1.
|
17
|
+
VERSION = '1.1'
|
18
18
|
|
19
19
|
##
|
20
20
|
# A Struct representing an RSS item for the RSS feed. Contains fields
|
@@ -70,7 +70,7 @@ class IMAPToRSS < IMAPProcessor
|
|
70
70
|
##
|
71
71
|
# Creates a new IMAPToRSS and connects to the selected server.
|
72
72
|
|
73
|
-
def initialize(options)
|
73
|
+
def initialize(options = {})
|
74
74
|
super
|
75
75
|
|
76
76
|
@handlers = []
|
@@ -177,13 +177,13 @@ class IMAPToRSS < IMAPProcessor
|
|
177
177
|
|
178
178
|
handled = handler.handle messages
|
179
179
|
|
180
|
+
# only tag handled messages, examined messages may be handled in the
|
181
|
+
# future
|
182
|
+
next if handled.empty?
|
183
|
+
|
180
184
|
@imap.store handled, '+FLAGS', %w[IMAP_TO_RSS]
|
181
185
|
|
182
|
-
if dest_mailbox
|
183
|
-
@imap.copy handled, dest_mailbox
|
184
|
-
@imap.store handled, '+FLAGS', [:Deleted]
|
185
|
-
@imap.expunge
|
186
|
-
end
|
186
|
+
move_messages handled, dest_mailbox if dest_mailbox
|
187
187
|
end
|
188
188
|
|
189
189
|
build_rss
|
@@ -86,11 +86,11 @@ class IMAPToRSS::Handler::Amazon < IMAPToRSS::Handler
|
|
86
86
|
|
87
87
|
def aws_bill
|
88
88
|
@mail.body =~ /^Total: (.*)/
|
89
|
-
total = $1
|
89
|
+
total = $1.strip
|
90
90
|
|
91
91
|
@mail.body =~ /^(http.*)/
|
92
92
|
|
93
|
-
add_item "Amazon Web Services Bill: #{total}", '', $1
|
93
|
+
add_item "Amazon Web Services Bill: #{total}", '', $1.strip
|
94
94
|
end
|
95
95
|
|
96
96
|
##
|
@@ -99,20 +99,20 @@ class IMAPToRSS::Handler::Amazon < IMAPToRSS::Handler
|
|
99
99
|
def gift_card
|
100
100
|
url = "https://www.amazon.com/gp/css/account/payment/view-gc-balance.html"
|
101
101
|
@mail.body =~ /^Amount: (.*)/
|
102
|
-
amount = $1
|
102
|
+
amount = $1.strip
|
103
103
|
|
104
104
|
@mail.body =~ /^From: (.*)/
|
105
|
-
from = $1
|
105
|
+
from = $1.strip
|
106
106
|
|
107
107
|
@mail.body =~ /^Gift Message: (.*)/
|
108
|
-
message = $1
|
108
|
+
message = $1.strip
|
109
109
|
|
110
110
|
@mail.body =~ /^Claim code (.*)/
|
111
|
-
claim_code = $1
|
111
|
+
claim_code = $1.strip
|
112
112
|
|
113
113
|
subject = "Amazon Gift Card from #{from} - #{amount}!"
|
114
114
|
|
115
|
-
description = "<p><strong>#{from}
|
115
|
+
description = "<p><strong>#{from} sent you a #{amount} gift card!</strong>\n\n"
|
116
116
|
description << "<p>#{message}\n\n"
|
117
117
|
description << "<h2>#{claim_code}</h2>\n\n"
|
118
118
|
description << "<p><a href=\"#{url}\">Claim your gift card</a>"
|
@@ -130,8 +130,8 @@ class IMAPToRSS::Handler::Amazon < IMAPToRSS::Handler
|
|
130
130
|
items = @mail.body.scan(/(\d?) of (.*)/)
|
131
131
|
|
132
132
|
url = order_url order_number
|
133
|
-
subject = "Amazon order
|
134
|
-
description = "<p>You
|
133
|
+
subject = "Amazon order cancellation #{order_number}"
|
134
|
+
description = "<p>You cancelled your order:\n\n"
|
135
135
|
|
136
136
|
description << order_table(items)
|
137
137
|
|
@@ -143,28 +143,33 @@ class IMAPToRSS::Handler::Amazon < IMAPToRSS::Handler
|
|
143
143
|
|
144
144
|
def order_shipped
|
145
145
|
@mail.body =~ /^(The following items .*?:\r\n.*?)(Shipping Carrier|Item Subtotal)/m
|
146
|
+
|
146
147
|
items = $1.map do |item|
|
147
148
|
next unless item =~ /\d+\s(.*?)\$[\d.]+\s+(\d+)/
|
148
149
|
[$2, $1.strip]
|
149
150
|
end.compact
|
150
151
|
|
151
|
-
carrier = $1.strip if
|
152
|
+
carrier = $1.strip if
|
153
|
+
@mail.body =~ /(?:Shipping Carrier:|Shipped via) (.*)/
|
152
154
|
date = $1.strip if @mail.body =~ /Ship Date: (.*)/
|
153
155
|
speed = $1.strip if @mail.body =~ /Shipping Speed: (.*)/
|
154
|
-
tracking_number = $1.strip if
|
156
|
+
tracking_number = $1.strip if
|
157
|
+
@mail.body =~ /(?:Carrier Tracking ID|Tracking number): (.*)/
|
155
158
|
|
156
|
-
@mail.body =~ /Your shipping address:\r\n\r\n(.*?)\r\n\r\n/m
|
159
|
+
@mail.body =~ /(?:Your shipping address|This shipment was sent to):\r\n\r\n(.*?)\r\n\r\n/m
|
157
160
|
address = $1.split("\n").map { |line| line.strip }.join "<br />\n" if $1
|
158
161
|
|
159
162
|
if tracking_number then
|
160
163
|
url = case carrier
|
161
164
|
when 'USPS' then
|
162
|
-
|
165
|
+
"http://trkcnfrm1.smi.usps.com/PTSInternetWeb/InterLabelInquiry.do?strOrigTrackNum=#{tracking_number}"
|
163
166
|
when 'FedEx' then
|
164
|
-
|
167
|
+
"http://fedex.com/Tracking?tracknumbers=#{tracking_number}"
|
168
|
+
when 'UPS' then
|
169
|
+
"http://wwwapps.ups.com/WebTracking/processInputRequest?InquiryNumber1=#{tracking_number}"
|
165
170
|
else
|
166
171
|
log "Unknown carrier: %p" % carrier
|
167
|
-
|
172
|
+
"http://www.google.com/search?q=#{tracking_number}"
|
168
173
|
end
|
169
174
|
end
|
170
175
|
|
@@ -18,47 +18,76 @@ class IMAPToRSS::Handler::HSBC < IMAPToRSS::Handler
|
|
18
18
|
|
19
19
|
def handle(uids)
|
20
20
|
each_message uids, 'text/plain' do |uid, mail|
|
21
|
-
|
22
|
-
|
21
|
+
@mail = mail
|
22
|
+
@url = nil
|
23
|
+
@description = nil
|
23
24
|
|
24
25
|
case mail.from.first
|
25
|
-
when 'HSBC@email.hsbcusa.com' then
|
26
|
-
mail.body =~ /^Dear.*?,
|
27
|
-
([ \t]*\r?\n){2,}
|
28
|
-
(.*?)
|
29
|
-
([ \t]*\r?\n){2,}/mx
|
30
|
-
next false unless $2
|
31
|
-
|
32
|
-
description = $2
|
33
26
|
when 'A2ATransfer@us.hsbc.com' then
|
34
|
-
|
35
|
-
([ \t]*\r?\n){2,}
|
36
|
-
(.*?)
|
37
|
-
([ \t]*\r?\n){2,}
|
38
|
-
Sincerely,/mx
|
39
|
-
next false unless $2
|
40
|
-
|
41
|
-
body = $2
|
42
|
-
|
43
|
-
body.gsub!(/[*\r]/, '')
|
44
|
-
body.gsub!(/[ \t]*\n/, "\n")
|
45
|
-
body = body.split(/\n\n+/).map { |para| "<p>#{para}</p>" }
|
46
|
-
|
47
|
-
description = body.join "\n\n"
|
27
|
+
next false unless handle_a2atransfer
|
48
28
|
when 'alerts@email.hsbcusa.com' then
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
url = $1
|
29
|
+
next false unless handle_alert
|
30
|
+
when 'HSBC@email.hsbcusa.com' then
|
31
|
+
next false unless handle_hsbc
|
53
32
|
else
|
54
33
|
log "Unknown From: #{mail.from.join ', '}"
|
55
34
|
next false
|
56
35
|
end
|
57
36
|
|
58
|
-
add_item mail.subject, description, mail.from, mail.date, url,
|
37
|
+
add_item mail.subject, @description, mail.from, mail.date, @url,
|
59
38
|
mail.message_id, 'HSBC'
|
60
39
|
end
|
61
40
|
end
|
62
41
|
|
42
|
+
def handle_a2atransfer
|
43
|
+
@mail.body =~ /^Dear.*?[,:]
|
44
|
+
([ \t]*\r?\n){2,}
|
45
|
+
(.*?)
|
46
|
+
([ \t]*\r?\n){2,}
|
47
|
+
Sincerely,/mx
|
48
|
+
|
49
|
+
return false unless $2
|
50
|
+
|
51
|
+
body = $2
|
52
|
+
|
53
|
+
body.gsub!(/[*\r]/, '')
|
54
|
+
body.gsub!(/[ \t]*\n/, "\n")
|
55
|
+
body = body.split(/\n\n+/).map { |para| "<p>#{para}</p>" }
|
56
|
+
|
57
|
+
@description = body.join "\n\n"
|
58
|
+
end
|
59
|
+
|
60
|
+
def handle_alert
|
61
|
+
@mail.body =~ /^Dear.*?,
|
62
|
+
([ \t]*\r?\n){2,}
|
63
|
+
(.*?)
|
64
|
+
([ \t]*\r?\n){2,}/mx
|
65
|
+
return false unless $2
|
66
|
+
|
67
|
+
@description = $2
|
68
|
+
end
|
69
|
+
|
70
|
+
def handle_hsbc
|
71
|
+
case @mail.body
|
72
|
+
when /purchase exceeding/ then
|
73
|
+
@mail.body =~ /Description: (.*)/
|
74
|
+
purchase = $1.strip
|
75
|
+
@mail.body =~ /^Amount: \$\s+([\d.]+)/
|
76
|
+
amount = $1
|
77
|
+
|
78
|
+
@description = <<-DESC
|
79
|
+
<p>Your purchase of #{purchase} was for $#{amount} which exceeds your
|
80
|
+
notification limit
|
81
|
+
DESC
|
82
|
+
when /^Dear.*?,
|
83
|
+
([ \t]*\r?\n){2,}
|
84
|
+
(.*?)
|
85
|
+
([ \t]*\r?\n){2,}/mx
|
86
|
+
@description = $2
|
87
|
+
end
|
88
|
+
|
89
|
+
return false unless @description
|
90
|
+
end
|
91
|
+
|
63
92
|
end
|
64
93
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'imap_to_rss/handler'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Processes iTunes receipts
|
5
|
+
|
6
|
+
class IMAPToRSS::Handler::Itunes < IMAPToRSS::Handler
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@search = 'FROM', 'itunes'
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle(uids)
|
13
|
+
each_message uids, 'text/plain' do |uid, mail|
|
14
|
+
body = ''
|
15
|
+
mail.body =~ /Order Number: ([^\s]*)/
|
16
|
+
order_number = $1
|
17
|
+
|
18
|
+
next false unless order_number
|
19
|
+
|
20
|
+
mail.body =~ /Order Total: (\$[\d.]+)/
|
21
|
+
total = $1
|
22
|
+
|
23
|
+
mail.body =~ /Purchase History:.*?(https:.*?)\r/m
|
24
|
+
url = $1
|
25
|
+
|
26
|
+
mail.body =~ /^Item\sNumber.*?
|
27
|
+
(^-+\r?\n)
|
28
|
+
(.*?)
|
29
|
+
\1/mx
|
30
|
+
|
31
|
+
body << "<table>\n<tr><th>Item<th>Price\n"
|
32
|
+
|
33
|
+
$2.scan(/^([^\s]+)\s+(.*?)\s+(Free|\$[\d.]+)/) do |item, name, price|
|
34
|
+
body << "<tr><td>#{name}<td>#{price}\n"
|
35
|
+
end
|
36
|
+
|
37
|
+
body << "</table>\n"
|
38
|
+
|
39
|
+
body << "<p>Total: #{total}"
|
40
|
+
|
41
|
+
subject = "iTunes Receipt ##{order_number}, #{total}"
|
42
|
+
|
43
|
+
add_item subject, body, mail.from, mail.date, url,
|
44
|
+
mail.message_id, 'iTunes'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'imap_to_rss'
|
3
|
+
|
4
|
+
# :stopdoc:
|
5
|
+
class IMAPToRSS
|
6
|
+
def connect(*args)
|
7
|
+
o = Object.new
|
8
|
+
def o.imap() end
|
9
|
+
o
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class IMAPToRSS::Handler
|
14
|
+
attr_accessor :mail
|
15
|
+
end
|
16
|
+
# :startdoc:
|
17
|
+
|
18
|
+
##
|
19
|
+
# Test case for IMAPToRSS handlers
|
20
|
+
|
21
|
+
class IMAPToRSS::TestCase < MiniTest::Unit::TestCase
|
22
|
+
|
23
|
+
##
|
24
|
+
# Sets this test case up with +handler+. Provides instance variables
|
25
|
+
# <tt>@itor</tt> and <tt>@handler</tt>
|
26
|
+
|
27
|
+
def setup(handler)
|
28
|
+
@itor = IMAPToRSS.new
|
29
|
+
@handler = handler
|
30
|
+
@handler.setup @itor
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns a new TMail::Mail from +options+. Defaults are:
|
35
|
+
#
|
36
|
+
# from:: from@example.com
|
37
|
+
# date:: Time.at 0
|
38
|
+
# to:: to@example.com
|
39
|
+
# subject:: subject for this mail
|
40
|
+
# body:: Hi! I'm a body!
|
41
|
+
#
|
42
|
+
# The mail body will be normalized to \r\n line breaks.
|
43
|
+
|
44
|
+
def util_mail(options = {})
|
45
|
+
options = {
|
46
|
+
:from => 'from@example.com',
|
47
|
+
:date => Time.at(0),
|
48
|
+
:to => 'to@example.com',
|
49
|
+
:subject => 'subject for this mail',
|
50
|
+
:body => 'Hi! I\'m a body!'
|
51
|
+
}.merge options
|
52
|
+
|
53
|
+
body = options[:body].split(/\r?\n/).join "\r\n"
|
54
|
+
|
55
|
+
TMail::Mail.parse <<-MAIL
|
56
|
+
From: #{options[:from]}\r
|
57
|
+
Date: #{options[:date].rfc2822}\r
|
58
|
+
To: #{options[:to]}\r
|
59
|
+
Subject: #{options[:subject]}\r
|
60
|
+
\r
|
61
|
+
#{body}
|
62
|
+
MAIL
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|