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 CHANGED
Binary file
data/.autotest CHANGED
@@ -2,22 +2,18 @@
2
2
 
3
3
  require 'autotest/restart'
4
4
 
5
- # Autotest.add_hook :initialize do |at|
6
- # at.extra_files << "../some/external/dependency.rb"
7
- #
8
- # at.libs << ":../some/external"
9
- #
10
- # at.add_exception 'vendor'
11
- #
12
- # at.add_mapping(/dependency.rb/) do |f, _|
13
- # at.files_matching(/test_.*rb$/)
14
- # end
15
- #
16
- # %w(TestA TestB).each do |klass|
17
- # at.extra_class_map[klass] = "test/test_misc.rb"
18
- # end
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
@@ -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
@@ -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.new 'imap_to_rss', IMAPToRSS::VERSION do |itor|
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
- itor.extra_deps << ['imap_processor', '~> 1.1']
13
- itor.extra_deps << ['nokogiri', '~> 1.2']
14
- itor.extra_deps << ['tmail', '~> 1.2']
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
@@ -14,7 +14,7 @@ class IMAPToRSS < IMAPProcessor
14
14
  ##
15
15
  # The version of IMAPToRSS you are using
16
16
 
17
- VERSION = '1.0.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 then
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} send you a #{amount} gift card!</strong>\n\n"
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 cancelation #{order_number}"
134
- description = "<p>You canceled your order:\n\n"
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 @mail.body =~ /Shipping Carrier: (.*)/
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 @mail.body =~ /Carrier Tracking ID: (.*)/
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
- "http://trkcnfrm1.smi.usps.com/PTSInternetWeb/InterLabelInquiry.do?strOrigTrackNum=#{tracking_number}"
165
+ "http://trkcnfrm1.smi.usps.com/PTSInternetWeb/InterLabelInquiry.do?strOrigTrackNum=#{tracking_number}"
163
166
  when 'FedEx' then
164
- "http://fedex.com/Tracking?tracknumbers=#{tracking_number}"
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
- nil
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
- url = nil
22
- description = nil
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
- mail.body =~ /^Dear.*?[,:]
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
- mail.body =~ /^(http:.*)/
50
- next false unless $1
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
+