aiwilliams-mlist 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +98 -37
- data/VERSION.yml +1 -1
- data/lib/mlist/email_server/smtp.rb +1 -2
- data/lib/mlist/manager/database.rb +4 -0
- data/lib/mlist/server.rb +3 -1
- data/lib/mlist/util/header_sanitizer.rb +9 -6
- metadata +1 -1
data/README
CHANGED
@@ -1,21 +1,34 @@
|
|
1
|
-
=
|
1
|
+
= MList
|
2
2
|
|
3
3
|
http://aiwilliams.github.com/mlist
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
|
-
An insane attempt to build a mail list server library that can be used
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
An insane attempt to build a mail list server library that can be used in other
|
8
|
+
applications very easily. The first target is Ruby applications that can load
|
9
|
+
MList models for direct, embedded integration. It will later have a RESTful API
|
10
|
+
so that any language/architecture can be easily integrated. That may depend
|
11
|
+
heavily on community involvement...
|
12
12
|
|
13
13
|
== FEATURES/PROBLEMS:
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
If you have any experience with mailing lists, things can be understood most
|
16
|
+
quickly with this: MList is the mailing list server and database, your
|
17
|
+
application is the list manager.
|
18
|
+
|
19
|
+
MList is being used in a production environment as a Ruby gem/Rails plugin. I
|
20
|
+
decided not to use other list software primarily because a) we already had a
|
21
|
+
running, sophisticated list manager that I didn't care to synchronize with
|
22
|
+
something else, b) we have an exceptional UI design for listing messages in
|
23
|
+
threads and ultimately will have search and c) integration options for the other
|
24
|
+
software looked to be a problem in themselves.
|
25
|
+
|
26
|
+
And then there's the fame and glory that comes with building something like
|
27
|
+
this...
|
28
|
+
|
29
|
+
There is a LOT to do: segmenting, i18n, backscatter - only the Mailman developers
|
30
|
+
know what else. I have enough experience to know that rewrites are NEVER as easy
|
31
|
+
as they seem. Alas, I go boldly forward.
|
19
32
|
|
20
33
|
==== Extracting 'from' IP address from emails is not implemented
|
21
34
|
|
@@ -29,9 +42,9 @@ required once at initialization, there will always only be one instance of the
|
|
29
42
|
model class, and therefore, many instances of the observer class (all but the
|
30
43
|
most recent invalid, since they were undefined) registered with it.
|
31
44
|
|
32
|
-
There are a number of ways to solve this, the best being the one that makes
|
33
|
-
'just work' such that I can delete this part of the document. For now, do
|
34
|
-
following in environment.rb:
|
45
|
+
There are a number of ways to solve this, the best being the one that makes
|
46
|
+
things 'just work' such that I can delete this part of the document. For now, do
|
47
|
+
the following in environment.rb:
|
35
48
|
|
36
49
|
* remove the observer from the Rails' config.active_record.observers list
|
37
50
|
* after the Rails::Initializer.run block, "require 'myobserver'"
|
@@ -42,11 +55,11 @@ class you are observing.
|
|
42
55
|
|
43
56
|
== SYNOPSIS:
|
44
57
|
|
45
|
-
Let's say you want your web application to have a mailing list feature.
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
58
|
+
Let's say you want your web application to have a mailing list feature. Let's
|
59
|
+
also say you care about the UI, and you don't want to learn all about creating
|
60
|
+
the correct HTML structures for a mailing list. You want to have lots of power
|
61
|
+
for searching the mail, and you have your own strategy for managing the lists.
|
62
|
+
You love Ruby. You want MList.
|
50
63
|
|
51
64
|
== REQUIREMENTS:
|
52
65
|
|
@@ -58,7 +71,57 @@ You'll need some gems.
|
|
58
71
|
|
59
72
|
== INSTALL:
|
60
73
|
|
61
|
-
|
74
|
+
sudo gem install mlist (you'll need to have github as a source).
|
75
|
+
|
76
|
+
For now, copy the mlist_ tables from the spec/fixtures/schema.rb file and move
|
77
|
+
them to a new migration in your application. Fun the migration.
|
78
|
+
|
79
|
+
Now you'll need to create the MList::Server and provide it with a list manager
|
80
|
+
and MList::EmailServer::Default instance. Something like this in your
|
81
|
+
environment.rb after the initialize block (our gem needs to have been loaded):
|
82
|
+
|
83
|
+
Rails::Initializer.run do |config|
|
84
|
+
# Please do specify a version, and check for the latest!
|
85
|
+
config.gem "mlist", :version => '0.1.0'
|
86
|
+
end
|
87
|
+
|
88
|
+
MLIST_SERVER = MList::Server.new(
|
89
|
+
:list_manager => MList::Manager::Database.new,
|
90
|
+
:email_server => MList::EmailServer::Default.new(
|
91
|
+
MList::EmailServer::Pop.new(
|
92
|
+
:ssl => false,
|
93
|
+
:server => 'pop.gmail.com',
|
94
|
+
:port => '995',
|
95
|
+
:username => 'yourusername',
|
96
|
+
:password => 'yourpassword'
|
97
|
+
),
|
98
|
+
MList::EmailServer::Smtp.new(
|
99
|
+
ActionMailer::Base.smtp_settings # probably good enough!
|
100
|
+
)
|
101
|
+
)
|
102
|
+
)
|
103
|
+
|
104
|
+
Your list manager needs to implement only two methods. Check out (and use if you
|
105
|
+
like) the MList::Manager::Database for more information.
|
106
|
+
|
107
|
+
You'll need something to trigger the incoming server process. Take your pick from
|
108
|
+
http://wiki.rubyonrails.org/rails/pages/HowToRunBackgroundJobsInRails. In the
|
109
|
+
end, if you don't write your own incoming server thing and go with the POP GMail
|
110
|
+
example above, your background process will "MLIST_SERVER.email_server.execute".
|
111
|
+
|
112
|
+
Take a look at MList::EmailPost if you're building a UI. It can be posted to a
|
113
|
+
list something like this:
|
114
|
+
|
115
|
+
class MyList # instances of these are given by your list manager
|
116
|
+
def post(attributes)
|
117
|
+
email = MList::EmailPost.new({
|
118
|
+
:mailer => 'MyApplication'
|
119
|
+
}.merge(attributes))
|
120
|
+
raise 'You can validate these' unless email.valid?
|
121
|
+
message = MLIST_SERVER.mail_list(self).post(email)
|
122
|
+
# do what you will with message. it's already saved.
|
123
|
+
end
|
124
|
+
end
|
62
125
|
|
63
126
|
== LICENSE:
|
64
127
|
|
@@ -66,21 +129,19 @@ You'll need some gems.
|
|
66
129
|
|
67
130
|
Copyright (c) 2008 Adam Williams (aiwilliams)
|
68
131
|
|
69
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
86
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
132
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
133
|
+
this software and associated documentation files (the 'Software'), to deal in the
|
134
|
+
Software without restriction, including without limitation the rights to use,
|
135
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
136
|
+
Software, and to permit persons to whom the Software is furnished to do so,
|
137
|
+
subject to the following conditions:
|
138
|
+
|
139
|
+
The above copyright notice and this permission notice shall be included in all
|
140
|
+
copies or substantial portions of the Software.
|
141
|
+
|
142
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
143
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
144
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
145
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
146
|
+
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
147
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/VERSION.yml
CHANGED
@@ -5,10 +5,9 @@ module MList
|
|
5
5
|
|
6
6
|
class Smtp < Base
|
7
7
|
def deliver(tmail, destinations)
|
8
|
-
sender = tmail['return-path'] || tmail.from
|
9
8
|
Net::SMTP.start(settings[:address], settings[:port], settings[:domain],
|
10
9
|
settings[:user_name], settings[:password], settings[:authentication]) do |smtp|
|
11
|
-
smtp.sendmail(tmail.encoded, sender, destinations)
|
10
|
+
smtp.sendmail(tmail.encoded, tmail['sender'], destinations)
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
data/lib/mlist/server.rb
CHANGED
@@ -10,7 +10,9 @@ module MList
|
|
10
10
|
|
11
11
|
def receive_email(email)
|
12
12
|
lists = list_manager.lists(email)
|
13
|
-
if
|
13
|
+
if lists.empty?
|
14
|
+
list_manager.no_lists_found(email)
|
15
|
+
elsif email.bounce?
|
14
16
|
process_bounce(lists.first, email)
|
15
17
|
else
|
16
18
|
process_post(lists, email)
|
@@ -38,15 +38,18 @@ module MList
|
|
38
38
|
self['reply-to'] = quoter(:quote_any_address_if_necessary)
|
39
39
|
self['subject'] = quoter(:quote_any_if_necessary)
|
40
40
|
|
41
|
+
self['sender'] = quoter(:quote_address_if_necessary)
|
42
|
+
self['errors-to'] = quoter(:quote_address_if_necessary)
|
41
43
|
self['in-reply-to'] = quoter(:quote_any_address_if_necessary)
|
42
44
|
self['x-mailer'] = quoter(:quote_if_necessary, false)
|
43
45
|
|
44
|
-
self['
|
45
|
-
self['
|
46
|
-
self['
|
47
|
-
self['
|
48
|
-
self['
|
49
|
-
self['
|
46
|
+
self['list-id'] = quoter(:quote_address_if_necessary)
|
47
|
+
self['list-help'] = quoter(:quote_address_if_necessary)
|
48
|
+
self['list-subscribe'] = quoter(:quote_address_if_necessary)
|
49
|
+
self['list-unsubscribe'] = quoter(:quote_address_if_necessary)
|
50
|
+
self['list-post'] = quoter(:quote_address_if_necessary)
|
51
|
+
self['list-owner'] = quoter(:quote_address_if_necessary)
|
52
|
+
self['list-archive'] = quoter(:quote_address_if_necessary)
|
50
53
|
end
|
51
54
|
|
52
55
|
def [](key)
|