mlist 0.1.14 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ *0.1.16 [Bug Fix] (2010-04-13)
2
+
3
+ * Fixed bug where encoding was lost when adding footers. [aiwilliams]
4
+
5
+ *0.1.15 [Bug Fix] (2010-04-02)
6
+
7
+ * Fixed mistakes in lifecycle management of imap connection. [aiwilliams]
8
+
1
9
  *0.1.14 [Bug Fix] (2010-04-02)
2
10
 
3
11
  * Better to ask for not deleted messages, and expunging after processing. [aiwilliams]
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- :patch: 14
2
+ :patch: 16
3
3
  :major: 0
4
4
  :build:
5
5
  :minor: 1
@@ -6,11 +6,6 @@ module MList
6
6
  class Imap < Base
7
7
  def initialize(settings)
8
8
  super(settings)
9
- @imap = Net::IMAP.new(
10
- settings[:server],
11
- settings[:port],
12
- settings[:ssl]
13
- )
14
9
  end
15
10
 
16
11
  def deliver(tmail)
@@ -18,7 +13,12 @@ module MList
18
13
  end
19
14
 
20
15
  def execute
21
- connect { process_folders }
16
+ begin
17
+ connect
18
+ process_folders
19
+ ensure
20
+ disconnect
21
+ end
22
22
  end
23
23
 
24
24
  def archive_message_id(id)
@@ -27,12 +27,16 @@ module MList
27
27
  end
28
28
 
29
29
  def connect
30
+ @imap = Net::IMAP.new(
31
+ settings[:server],
32
+ settings[:port],
33
+ settings[:ssl]
34
+ )
30
35
  @imap.login(settings[:username], settings[:password])
31
- begin
32
- yield
33
- ensure
34
- @imap.close
35
- end
36
+ end
37
+
38
+ def disconnect
39
+ @imap.disconnect if @imap && !@imap.disconnected?
36
40
  end
37
41
 
38
42
  def process_folders
@@ -47,7 +51,7 @@ module MList
47
51
  process_message_id(message_id)
48
52
  archive_message_id(message_id)
49
53
  end
50
- @imap.expunge
54
+ @imap.close
51
55
  end
52
56
 
53
57
  def process_message_id(id)
@@ -1,5 +1,7 @@
1
1
  module MList
2
2
  class MailList < ActiveRecord::Base
3
+ include Util::Quoting
4
+
3
5
  set_table_name 'mlist_mail_lists'
4
6
 
5
7
  # Provides the MailList for a given implementation of MList::List,
@@ -237,24 +239,31 @@ module MList
237
239
 
238
240
  def prepare_html_footer(part, footer)
239
241
  return unless part
240
- content = part.body
242
+
243
+ content = part.body('utf-8')
241
244
  content.gsub!(%r(<p>\s*#{FOOTER_BLOCK_START_RE}.*?#{FOOTER_BLOCK_END_RE}\s*<\/p>)im, '')
242
245
  content.strip!
246
+
243
247
  html_footer = "<p>#{auto_link_urls(text_to_html(footer))}</p>"
244
248
 
245
249
  unless content.sub!(/<\/body>/, "#{html_footer}</body>")
246
250
  # no body was there, substitution failed
247
251
  content << html_footer
248
252
  end
249
- part.body = content
253
+
254
+ part.charset = 'utf-8'
255
+ part.content_transfer_encoding = 'quoted-printable'
256
+ part.body = [normalize_new_lines(content)].pack("M*")
250
257
  end
251
258
 
252
259
  def prepare_text_footer(part, footer)
253
260
  return unless part
254
- content = strip_list_footers(part.body)
261
+ content = strip_list_footers(part.body('utf-8'))
255
262
  content << "\n\n" unless content.end_with?("\n\n")
256
263
  content << footer
257
- part.body = content
264
+ part.charset = 'utf-8'
265
+ part.content_transfer_encoding = 'quoted-printable'
266
+ part.body = [normalize_new_lines(content)].pack("M*")
258
267
  end
259
268
 
260
269
  def list_footer(message)
@@ -1,50 +1,47 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
  require 'mlist/email_server/imap'
3
3
 
4
- describe MList::EmailServer::Imap, 'settings' do
5
- it 'should use the provided credentials' do
6
- mock(Net::IMAP).new('host', 993, true) { mock('imap') }
7
- MList::EmailServer::Imap.new(:server => 'host', :port => 993, :ssl => true)
8
- end
9
-
10
- it 'should login with the provided credentials, process the folders, close on completion' do
11
- imap_server = Object.new
12
- stub(Net::IMAP).new { imap_server }
13
-
4
+ describe MList::EmailServer::Imap, 'execute' do
5
+ it 'should use the provided credentials when connecting' do
6
+ imap_server = 'mock_imap_server'
7
+ mock(Net::IMAP).new('host', 993, true) { imap_server }
14
8
  mock(imap_server).login('aahh', 'eeya')
15
- mock(imap_server).close
16
9
 
17
10
  imap = MList::EmailServer::Imap.new(
11
+ :server => 'host', :port => 993, :ssl => true,
18
12
  :username => 'aahh', :password => 'eeya'
19
13
  )
20
- mock(imap).process_folders
21
- imap.execute
14
+ imap.connect
22
15
  end
23
16
 
24
- it 'should process the provided folders' do
25
- imap_server = Object.new
26
- stub(Net::IMAP).new { imap_server }
27
- imap = MList::EmailServer::Imap.new(
28
- :source_folders => ['Inbox', 'Spam']
29
- )
30
- mock(imap).process_folder('Inbox')
31
- mock(imap).process_folder('Spam')
32
- imap.process_folders
17
+ it 'should connect, process the folders, disconnect on execution' do
18
+ imap = MList::EmailServer::Imap.new({})
19
+ mock(imap).connect
20
+ mock(imap).process_folders
21
+ mock(imap).disconnect
22
+ imap.execute
33
23
  end
34
24
  end
35
25
 
36
26
  describe MList::EmailServer::Imap, 'processing' do
37
27
  before do
38
28
  @imap_server = 'mock_imap_server'
39
- stub(Net::IMAP).new { @imap_server }
40
29
  @imap = MList::EmailServer::Imap.new({:archive_folder => 'Archive'})
30
+ @imap.instance_variable_set('@imap', @imap_server)
31
+ end
32
+
33
+ it 'should process the provided folders' do
34
+ imap = MList::EmailServer::Imap.new(:source_folders => ['Inbox', 'Spam'])
35
+ mock(imap).process_folder('Inbox')
36
+ mock(imap).process_folder('Spam')
37
+ imap.process_folders
41
38
  end
42
39
 
43
- it 'should examine the specified folder and process all the messages' do
40
+ it 'should select the folder, process each message, close the folder' do
44
41
  message_ids = [1,2]
45
42
  mock(@imap_server).select('folder')
46
43
  mock(@imap_server).search(['NOT','DELETED']) { message_ids }
47
- mock(@imap_server).expunge
44
+ mock(@imap_server).close
48
45
  mock(@imap).process_message_id(1)
49
46
  mock(@imap).archive_message_id(1)
50
47
  mock(@imap).process_message_id(2)
@@ -396,7 +396,7 @@ describe MList::MailList do
396
396
  it 'should append the list footer to text/plain emails' do
397
397
  @post_tmail.body = "My Email\n\n\n\n\n"
398
398
  mock(@manager_list).footer_content(is_a(MList::Message)) { 'my footer' }
399
- process_post.body.should == "My Email\n\n\n\n\n#{MList::MailList::FOOTER_BLOCK_START}\nmy footer\n#{MList::MailList::FOOTER_BLOCK_END}"
399
+ process_post.body.should == "My Email\n\n\n\n\n#{MList::MailList::FOOTER_BLOCK_START}\nmy footer\n#{MList::MailList::FOOTER_BLOCK_END}=\n"
400
400
  end
401
401
 
402
402
  it 'should append the list footer to multipart/alternative, text/plain part of emails' do
@@ -414,7 +414,7 @@ describe MList::MailList do
414
414
  it 'should handle whitespace well when appending footer' do
415
415
  @post_tmail.body = "My Email"
416
416
  mock(@manager_list).footer_content(is_a(MList::Message)) { 'my footer' }
417
- process_post.body.should == "My Email\n\n#{MList::MailList::FOOTER_BLOCK_START}\nmy footer\n#{MList::MailList::FOOTER_BLOCK_END}"
417
+ process_post.body.should == "My Email\n\n#{MList::MailList::FOOTER_BLOCK_START}\nmy footer\n#{MList::MailList::FOOTER_BLOCK_END}=\n"
418
418
  end
419
419
 
420
420
  it 'should strip out any existing text footers from the list' do
@@ -433,7 +433,7 @@ describe MList::MailList do
433
433
  this is without any in front
434
434
  #{MList::MailList::FOOTER_BLOCK_END}
435
435
  }
436
- process_post.body.should == "My Email\n\n#{MList::MailList::FOOTER_BLOCK_START}\nmy footer\n#{MList::MailList::FOOTER_BLOCK_END}"
436
+ process_post.body.should == "My Email\n\n#{MList::MailList::FOOTER_BLOCK_START}\nmy footer\n#{MList::MailList::FOOTER_BLOCK_END}=\n"
437
437
  end
438
438
 
439
439
  it 'should strip out any existing html footers from the list' do
@@ -457,6 +457,19 @@ this is without any in front
457
457
  process_post.parts[1].body.should == "<p>My Email</p>\n<blockquote>\n <p> Stuff in my email</p>\n\n>> not in our p!<p>#{MList::MailList::FOOTER_BLOCK_START}<br />\nmy footer<br />\n#{MList::MailList::FOOTER_BLOCK_END}</p>"
458
458
  end
459
459
 
460
+ it 'should properly reflect the new encoding when adding footers' do
461
+ @post_tmail = tmail_fixture('content_types/multipart_alternative_encoded')
462
+ stub(@manager_list).footer_content { 'my footer' }
463
+
464
+ part = process_post.parts[0]
465
+ part.charset.should == 'utf-8'
466
+ part.body.should == "Hi Friends and Neighbors:\n\nLike you, we have many concerns about what is going on in our country. This\nyear in our homeschool, we've spent a lot more time learning about the\nhistory of our country, and the mindset of the founders that caused them to\nbreak away from the British empire and put together our great founding\ndocuments of the Declaration of Independence and U.S. Constitution. How far\nwe have fallen!\n\n-- \nBob Bold\nThe Edge of Your Seat Experience Compny™\n\n\n#{MList::MailList::FOOTER_BLOCK_START}\nmy footer\n#{MList::MailList::FOOTER_BLOCK_END}"
467
+
468
+ part = process_post.parts[1]
469
+ part.charset.should == 'utf-8'
470
+ part.body.should == "<div class=\"gmail_quote\"><br><div class=\"gmail_quote\"><div><span style=\"font-family:arial, sans-serif;font-size:13px;border-collapse:collapse\"><div>\nHi Friends and Neighbors:</div><div><br></div><div>Like you, we have many concerns about what is going on in our country.  This year in our homeschool, we&#39;ve spent a lot more time learning about the history of our country, and the mindset of the founders that caused them to break away from the British empire and put together our great founding documents of the Declaration of Independence and U.S. Constitution.  How far we have fallen!</div>\n\n<div><span style=\"font-size:small\"><br></span></div></span></div></div>-- <br>Bob Bold<br>The Edge of Your Seat Experience Compny™ <br>Beaverton Heights              919-555-5555 (v)<br>1234 Checkstone St            919-555-5555 (f)<br><p>#{MList::MailList::FOOTER_BLOCK_START}<br />\nmy footer<br />\n#{MList::MailList::FOOTER_BLOCK_END}</p>"
471
+ end
472
+
460
473
  describe 'time' do
461
474
  include TMail::TextUtils
462
475
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 14
9
- version: 0.1.14
8
+ - 16
9
+ version: 0.1.16
10
10
  platform: ruby
11
11
  authors:
12
12
  - Adam Williams
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-02 00:00:00 -04:00
17
+ date: 2010-04-13 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies: []
20
20