mlist 0.1.9

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