mlist 0.1.9

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.
Files changed (50) hide show
  1. data/CHANGELOG +59 -0
  2. data/README +204 -0
  3. data/Rakefile +27 -0
  4. data/TODO +36 -0
  5. data/VERSION.yml +4 -0
  6. data/lib/mlist/email.rb +69 -0
  7. data/lib/mlist/email_post.rb +126 -0
  8. data/lib/mlist/email_server/base.rb +33 -0
  9. data/lib/mlist/email_server/default.rb +31 -0
  10. data/lib/mlist/email_server/fake.rb +16 -0
  11. data/lib/mlist/email_server/pop.rb +28 -0
  12. data/lib/mlist/email_server/smtp.rb +24 -0
  13. data/lib/mlist/email_server.rb +2 -0
  14. data/lib/mlist/email_subscriber.rb +6 -0
  15. data/lib/mlist/list.rb +183 -0
  16. data/lib/mlist/mail_list.rb +277 -0
  17. data/lib/mlist/manager/database.rb +48 -0
  18. data/lib/mlist/manager/notifier.rb +31 -0
  19. data/lib/mlist/manager.rb +30 -0
  20. data/lib/mlist/message.rb +150 -0
  21. data/lib/mlist/server.rb +62 -0
  22. data/lib/mlist/thread.rb +98 -0
  23. data/lib/mlist/util/email_helpers.rb +155 -0
  24. data/lib/mlist/util/header_sanitizer.rb +71 -0
  25. data/lib/mlist/util/quoting.rb +70 -0
  26. data/lib/mlist/util/tmail_builder.rb +42 -0
  27. data/lib/mlist/util/tmail_methods.rb +138 -0
  28. data/lib/mlist/util.rb +12 -0
  29. data/lib/mlist.rb +46 -0
  30. data/lib/pop_ssl.rb +999 -0
  31. data/rails/init.rb +22 -0
  32. data/spec/fixtures/schema.rb +94 -0
  33. data/spec/integration/date_formats_spec.rb +12 -0
  34. data/spec/integration/mlist_spec.rb +232 -0
  35. data/spec/integration/pop_email_server_spec.rb +22 -0
  36. data/spec/integration/proof_spec.rb +74 -0
  37. data/spec/matchers/equal_tmail.rb +53 -0
  38. data/spec/matchers/have_address.rb +48 -0
  39. data/spec/matchers/have_header.rb +104 -0
  40. data/spec/models/email_post_spec.rb +100 -0
  41. data/spec/models/email_server/base_spec.rb +11 -0
  42. data/spec/models/email_spec.rb +54 -0
  43. data/spec/models/mail_list_spec.rb +469 -0
  44. data/spec/models/message_spec.rb +109 -0
  45. data/spec/models/thread_spec.rb +83 -0
  46. data/spec/models/util/email_helpers_spec.rb +47 -0
  47. data/spec/models/util/header_sanitizer_spec.rb +19 -0
  48. data/spec/models/util/quoting_spec.rb +96 -0
  49. data/spec/spec_helper.rb +76 -0
  50. metadata +103 -0
@@ -0,0 +1,138 @@
1
+ module MList
2
+ module Util
3
+
4
+ module TMailReaders
5
+ def date
6
+ if date = tmail.header_string('date')
7
+ Time.parse(date)
8
+ end
9
+ end
10
+
11
+ def from_address
12
+ tmail.from.first.downcase
13
+ end
14
+
15
+ def html
16
+ case tmail.content_type
17
+ when 'text/html'
18
+ tmail.body.strip
19
+ when 'multipart/alternative'
20
+ html_part = tmail.parts.detect {|part| part.content_type == 'text/html'}
21
+ html_part.body.strip if html_part
22
+ end
23
+ end
24
+
25
+ def identifier
26
+ remove_brackets(tmail.header_string('message-id'))
27
+ end
28
+
29
+ def mailer
30
+ tmail.header_string('x-mailer')
31
+ end
32
+
33
+ def text
34
+ text_content = ''
35
+ extract_text_content(tmail, text_content)
36
+ return text_content unless text_content.blank?
37
+
38
+ html_content = ''
39
+ extract_html_content(tmail, html_content)
40
+ return html_to_text(html_content) unless html_content.blank?
41
+
42
+ return nil
43
+ end
44
+
45
+ # Answers the first text/plain part it can find, the tmail itself if
46
+ # it's content type is text/plain.
47
+ #
48
+ def text_plain_part(part = tmail)
49
+ case part.content_type
50
+ when 'text/plain'
51
+ part
52
+ when 'multipart/alternative'
53
+ part.parts.detect {|part| text_plain_part(part)}
54
+ end
55
+ end
56
+
57
+ private
58
+ def extract_html_content(part, collector)
59
+ case part.content_type
60
+ when 'text/html'
61
+ collector << part.body.strip
62
+ when 'multipart/alternative', 'multipart/mixed', 'multipart/related'
63
+ part.parts.each {|part| extract_html_content(part, collector)}
64
+ end
65
+ end
66
+
67
+ def extract_text_content(part, collector)
68
+ case part.content_type
69
+ when 'text/plain'
70
+ collector << part.body.strip
71
+ when 'multipart/alternative', 'multipart/mixed', 'multipart/related'
72
+ part.parts.each {|part| extract_text_content(part, collector)}
73
+ end
74
+ end
75
+ end
76
+
77
+ module TMailWriters
78
+ def charset
79
+ 'utf-8'
80
+ end
81
+
82
+ def delete_header(name)
83
+ tmail[name] = nil
84
+ end
85
+
86
+ def headers=(updates)
87
+ updates.each do |k,v|
88
+ if TMail::Mail::ALLOW_MULTIPLE.include?(k.downcase)
89
+ prepend_header(k,v)
90
+ else
91
+ write_header(k,v)
92
+ end
93
+ end
94
+ end
95
+
96
+ # Add another value for the named header, it's position being earlier in
97
+ # the email than those that are already present. This will raise an error
98
+ # if the header does not allow multiple values according to
99
+ # TMail::Mail::ALLOW_MULTIPLE.
100
+ #
101
+ def prepend_header(name, value)
102
+ original = tmail[name] || []
103
+ tmail[name] = nil
104
+ tmail[name] = sanitize_header(charset, name, value)
105
+ tmail[name] = tmail[name] + original
106
+ end
107
+
108
+ def write_header(name, value)
109
+ tmail[name] = sanitize_header(charset, name, value)
110
+ end
111
+
112
+ def to=(recipient_addresses)
113
+ tmail.to = sanitize_header(charset, 'to', recipient_addresses)
114
+ end
115
+
116
+ def bcc=(recipient_addresses)
117
+ tmail.bcc = sanitize_header(charset, 'bcc', recipient_addresses)
118
+ end
119
+
120
+ def from=(from_address)
121
+ tmail.from = sanitize_header(charset, 'from', from_address)
122
+ end
123
+
124
+ def in_reply_to=(*values)
125
+ tmail.in_reply_to = sanitize_header(charset, 'in-reply-to', *values)
126
+ end
127
+
128
+ def mailer=(value)
129
+ write_header('x-mailer', value)
130
+ end
131
+
132
+ def message_id=(value)
133
+ tmail.message_id = sanitize_header(charset, 'message-id', value)
134
+ end
135
+ end
136
+
137
+ end
138
+ end
data/lib/mlist/util.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'mlist/util/quoting'
2
+ require 'mlist/util/header_sanitizer'
3
+ require 'mlist/util/email_helpers'
4
+ require 'mlist/util/tmail_methods'
5
+ require 'mlist/util/tmail_builder'
6
+
7
+ module MList
8
+ module Util
9
+ mattr_accessor :default_header_sanitizers
10
+ self.default_header_sanitizers = HeaderSanitizerHash.new
11
+ end
12
+ end
data/lib/mlist.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'delegate'
2
+
3
+ require 'uuid'
4
+ require 'tmail'
5
+ require 'hpricot'
6
+ require 'active_support'
7
+ require 'active_record'
8
+
9
+ require 'mlist/util'
10
+ require 'mlist/email'
11
+ require 'mlist/message'
12
+ require 'mlist/list'
13
+ require 'mlist/mail_list'
14
+ require 'mlist/email_post'
15
+ require 'mlist/email_server'
16
+ require 'mlist/email_subscriber'
17
+ require 'mlist/server'
18
+ require 'mlist/thread'
19
+
20
+ require 'mlist/manager'
21
+
22
+ module MList
23
+ mattr_reader :version
24
+ @@version = YAML.load_file(File.join(File.dirname(__FILE__), '..', "VERSION.yml"))
25
+ class << @@version
26
+ def to_s
27
+ @to_s ||= [self[:major], self[:minor], self[:patch]].join('.')
28
+ end
29
+ end
30
+
31
+ class DoubleDeliveryError < StandardError
32
+ def initialize(message)
33
+ super("A message should never be delivered more than once. An attempt was made to deliver this message:\n#{message.inspect}")
34
+ end
35
+ end
36
+ end
37
+
38
+ Time::DATE_FORMATS[:mlist_reply_timestamp] = Date::DATE_FORMATS[:mlist_reply_timestamp] = lambda do |time|
39
+ time.strftime('%a, %b %d, %Y at %I:%M %p').sub(/0(\d,)/, '\1').sub(/0(\d:)/, '\1')
40
+ end
41
+
42
+ # In order to keep the inline images in email intact. Certainly a scary bit of
43
+ # hacking, but this is the solution out there on the internet.
44
+ TMail::HeaderField::FNAME_TO_CLASS.delete 'content-id'
45
+
46
+ TMail::Mail::ALLOW_MULTIPLE['x-beenthere'] = true