imap_to_rss 1.0.1 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+