simple_mailing_list 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +52 -0
- data/LICENSE.txt +21 -0
- data/README.ja.md +78 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/example/config_example.ja.yaml +127 -0
- data/example/config_example.yaml +89 -0
- data/exe/daemons_simple_mailing_list +14 -0
- data/exe/simple_mailing_list +5 -0
- data/lib/simple_mailing_list/configfile.rb +87 -0
- data/lib/simple_mailing_list/delete_old.rb +45 -0
- data/lib/simple_mailing_list/lock.rb +22 -0
- data/lib/simple_mailing_list/main.rb +394 -0
- data/lib/simple_mailing_list/setup.rb +56 -0
- data/lib/simple_mailing_list/version.rb +3 -0
- data/lib/simple_mailing_list.rb +134 -0
- data/simple_mailing_list.gemspec +35 -0
- metadata +179 -0
@@ -0,0 +1,394 @@
|
|
1
|
+
require "json"
|
2
|
+
require "securerandom"
|
3
|
+
require "digest/sha2"
|
4
|
+
|
5
|
+
require "liquid"
|
6
|
+
|
7
|
+
require "simple_mailing_list/lock"
|
8
|
+
|
9
|
+
class User < ActiveRecord::Base ; end
|
10
|
+
class Confirmation < ActiveRecord::Base ; end
|
11
|
+
|
12
|
+
module SimpleMailingList
|
13
|
+
module System
|
14
|
+
private
|
15
|
+
|
16
|
+
def _check_mails(thread_join = true)
|
17
|
+
threads = receive_mails.map do |mail_filename|
|
18
|
+
Thread.start(File.join(@maillogs_dir, "temp", mail_filename)) do |filename|
|
19
|
+
_check_mail_file(filename)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
threads.each { |thread| thread.join } if thread_join
|
23
|
+
end
|
24
|
+
|
25
|
+
def _check_mail_file(filename)
|
26
|
+
mail = Mail.read(filename)
|
27
|
+
begin
|
28
|
+
return if register_mail(mail, filename)
|
29
|
+
return if delete_mail(mail, filename)
|
30
|
+
return if confirm_mail(mail, filename)
|
31
|
+
return if bounced_mail(mail, filename)
|
32
|
+
return if forward_mail(mail, filename)
|
33
|
+
return if unmatched_mail(mail, filename)
|
34
|
+
rescue => e
|
35
|
+
move_mail_file(filename, "error")
|
36
|
+
@log.error "Error Mail[#{File.basename(filename)}]!\n #{error_message(e)}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_rule(rules, mail)
|
41
|
+
mail_body = mail.body ? mail.body.decoded.to_s : ""
|
42
|
+
mail_body += mail.text_part.decoded.to_s if mail.text_part
|
43
|
+
return rules.find do |rule|
|
44
|
+
(!rule["address"] || Array(mail.to).index(rule["address"])) &&
|
45
|
+
(!rule["subject"] || mail.subject.to_s.index(rule["subject"])) &&
|
46
|
+
(!rule["body" ] || mail_body.index(rule["body"]))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def register_mail(mail, filename)
|
51
|
+
rule = find_rule(@register, mail)
|
52
|
+
address = Array(mail.from).first.to_s
|
53
|
+
return false if !rule || address.empty?
|
54
|
+
regisiter_options = rule["options"] || {}
|
55
|
+
@log.info "New register mail from #{address}."
|
56
|
+
return true if Confirmation.where(mail_address: address).size >= @max_check_times
|
57
|
+
|
58
|
+
check_code = create_check_code()
|
59
|
+
Confirmation.new(
|
60
|
+
mail_address: address,
|
61
|
+
check_code: check_code,
|
62
|
+
mode: "register",
|
63
|
+
options: JSON.generate(regisiter_options)
|
64
|
+
).save!
|
65
|
+
|
66
|
+
mail = create_mail(
|
67
|
+
to: address,
|
68
|
+
subject: @register_confirm_subject,
|
69
|
+
body: @register_confirm_body,
|
70
|
+
options: regisiter_options.merge({ "checkcode" => check_code })
|
71
|
+
)
|
72
|
+
mail.subject += check_code unless mail.subject.index(check_code)
|
73
|
+
mail.deliver!
|
74
|
+
sleep @sleep_time1
|
75
|
+
move_mail_file(filename, "register")
|
76
|
+
return true
|
77
|
+
end
|
78
|
+
|
79
|
+
def delete_mail(mail, filename)
|
80
|
+
rule = find_rule(@delete, mail)
|
81
|
+
address = Array(mail.from).first.to_s
|
82
|
+
return false if !rule || address.empty?
|
83
|
+
@log.info "New delete mail from #{address}."
|
84
|
+
return true if Confirmation.where(mail_address: address).size >= @max_check_times
|
85
|
+
|
86
|
+
check_code = create_check_code()
|
87
|
+
Confirmation.new(
|
88
|
+
mail_address: address,
|
89
|
+
check_code: check_code,
|
90
|
+
mode: "delete",
|
91
|
+
options: "{}"
|
92
|
+
).save!
|
93
|
+
|
94
|
+
mail = create_mail(
|
95
|
+
to: address,
|
96
|
+
subject: @delete_confirm_subject,
|
97
|
+
body: @delete_confirm_body,
|
98
|
+
options: { "checkcode" => check_code }
|
99
|
+
)
|
100
|
+
mail.subject += check_code unless mail.subject.index(check_code)
|
101
|
+
mail.deliver!
|
102
|
+
sleep @sleep_time1
|
103
|
+
move_mail_file(filename, "delete")
|
104
|
+
return true
|
105
|
+
end
|
106
|
+
|
107
|
+
def confirm_mail(mail, filename)
|
108
|
+
address = Array(mail.from).first.to_s
|
109
|
+
return false if address.empty?
|
110
|
+
subject = mail.subject.to_s
|
111
|
+
body = mail.body ? mail.body.decoded : ""
|
112
|
+
body += mail.text_part.decoded.to_s if mail.text_part
|
113
|
+
|
114
|
+
Confirmation.where(mail_address: address).each do |confirmation|
|
115
|
+
check_code = confirmation.check_code
|
116
|
+
next unless subject.index(check_code) || body.index(check_code)
|
117
|
+
|
118
|
+
confirm_options = {}
|
119
|
+
subject_text, body_text = case confirmation.mode
|
120
|
+
when "register"
|
121
|
+
@log.info "New register check mail from #{address}."
|
122
|
+
confirm_options = JSON.parse(confirmation.options)
|
123
|
+
_add_user(address, confirm_options)
|
124
|
+
[@register_success_subject, @register_success_body]
|
125
|
+
when "delete"
|
126
|
+
@log.info "New delete check mail from #{address}."
|
127
|
+
_delete_user(address)
|
128
|
+
[@delete_success_subject, @delete_success_body]
|
129
|
+
else
|
130
|
+
next
|
131
|
+
end
|
132
|
+
|
133
|
+
create_mail(
|
134
|
+
to: address,
|
135
|
+
subject: subject_text,
|
136
|
+
body: body_text,
|
137
|
+
reply_to: @reply_to_address,
|
138
|
+
options: confirm_options
|
139
|
+
).deliver!
|
140
|
+
sleep @sleep_time1
|
141
|
+
|
142
|
+
move_mail_file(filename, "#{confirmation.mode}_check")
|
143
|
+
confirmation.destroy
|
144
|
+
return true
|
145
|
+
end
|
146
|
+
|
147
|
+
return false
|
148
|
+
end
|
149
|
+
|
150
|
+
def bounced_mail(mail, filename)
|
151
|
+
unless mail.bounced?
|
152
|
+
return false
|
153
|
+
end
|
154
|
+
|
155
|
+
matched = mail.final_recipient.to_s.match(/;\s*([^@]+@[^@]+)/)
|
156
|
+
if matched
|
157
|
+
mail_address = matched[1]
|
158
|
+
@log.warn "Bounced mail[#{File.basename(filename)}] from #{mail_address}."
|
159
|
+
User.where(mail_address: mail_address).each do |user|
|
160
|
+
user.failed_count += 1
|
161
|
+
user.last_failed_at = Time.now
|
162
|
+
user.save
|
163
|
+
end
|
164
|
+
else
|
165
|
+
@log.warn "Bounced mail[#{File.basename(filename)}]."
|
166
|
+
end
|
167
|
+
move_mail_file(filename, "bounced")
|
168
|
+
return true
|
169
|
+
end
|
170
|
+
|
171
|
+
def forward_mail(mail, filename)
|
172
|
+
rule = find_rule(@forward, mail)
|
173
|
+
address = Array(mail.from).first.to_s
|
174
|
+
return false if !rule || address.empty?
|
175
|
+
forward_options = rule["options"] || {}
|
176
|
+
subject = mail.subject.to_s
|
177
|
+
@log.info "New forward mail from #{address}."
|
178
|
+
if @permitted_users
|
179
|
+
permitted_user = @permitted_users.find do |user|
|
180
|
+
(!user["address"] || user["address"] == address) &&
|
181
|
+
(!user["check_code"] || subject.index(["check_code"]))
|
182
|
+
end
|
183
|
+
return true unless permitted_user
|
184
|
+
subject.sub!(permitted_user["check_code"], "") if permitted_user["check_code"]
|
185
|
+
elsif @registered_user_only
|
186
|
+
return true unless User.find_by(mail_address: address)
|
187
|
+
end
|
188
|
+
danger_ext = /\.(exe|com|bat|cmd|vbs|vbe|js|jse|wsf|wsh|msc|jar|hta|scr|cpl|lnk)$/i
|
189
|
+
if mail.has_attachments?
|
190
|
+
attachment = mail.attachments.to_a.find do |attachment|
|
191
|
+
attachment.filename.to_s.match(danger_ext)
|
192
|
+
end
|
193
|
+
if attachment
|
194
|
+
@log.warn("Contains danger attachment![#{attachment}@#{File.basename(filename)}]")
|
195
|
+
return true
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
sendmail = create_forward_mail(mail, subject)
|
200
|
+
|
201
|
+
users = User.all.to_a.select do |user|
|
202
|
+
user_options = JSON.parse(user.options)
|
203
|
+
!forward_options.keys.any?{ |key| forward_options[key] != user_options[key] }
|
204
|
+
end
|
205
|
+
users.map! { |user| user.mail_address }
|
206
|
+
users.uniq!
|
207
|
+
users.delete(address)
|
208
|
+
|
209
|
+
domains = { "???" => [] }
|
210
|
+
users.each do |user|
|
211
|
+
domain = user.match(/@([^@]+)$/) ? $1 : "???"
|
212
|
+
domains[domain] ||= []
|
213
|
+
domains[domain].push(user)
|
214
|
+
end
|
215
|
+
max = domains.values.map(&:size).max
|
216
|
+
domains["???"][max] = address
|
217
|
+
0.upto(max) do |i|
|
218
|
+
time = Time.now
|
219
|
+
domains.each_value do |address_array|
|
220
|
+
mail_address = address_array[i]
|
221
|
+
next unless mail_address
|
222
|
+
|
223
|
+
@log.debug "Send to #{mail_address}"
|
224
|
+
sendmail.to = mail_address
|
225
|
+
begin
|
226
|
+
sendmail.deliver!
|
227
|
+
rescue => e
|
228
|
+
@log.warn "Sending Error!(#{mail_address})\n #{error_message(e)}"
|
229
|
+
User.where(mail_address: mail_address).each do |user|
|
230
|
+
user.failed_count += 1
|
231
|
+
user.last_failed_at = Time.now
|
232
|
+
user.save
|
233
|
+
end
|
234
|
+
end
|
235
|
+
sleep @sleep_time1
|
236
|
+
end
|
237
|
+
next if Time.now - time > @sleep_time2 || i+1 == max
|
238
|
+
sleep time - Time.now + @sleep_time2
|
239
|
+
end
|
240
|
+
@log.info "Forward mails to #{users.size + 1} user#{users.size > 0 ? 's' : ''}."
|
241
|
+
move_mail_file(filename, "forward")
|
242
|
+
return true
|
243
|
+
end
|
244
|
+
|
245
|
+
def unmatched_mail(mail, filename)
|
246
|
+
address = Array(mail.from).first.to_s
|
247
|
+
@log.warn "Unmatched mail[#{File.basename(filename)}] from #{address}."
|
248
|
+
move_mail_file(filename, "unmatched")
|
249
|
+
return true
|
250
|
+
end
|
251
|
+
|
252
|
+
def _add_user(address, user_options = {})
|
253
|
+
user = User.new
|
254
|
+
user.mail_address = address
|
255
|
+
user.options = JSON.generate(user_options)
|
256
|
+
user.save!
|
257
|
+
@log.info "Add user[#{address}]."
|
258
|
+
end
|
259
|
+
|
260
|
+
def _delete_user(address)
|
261
|
+
User.where(mail_address: address).destroy_all()
|
262
|
+
@log.info "Delete user[#{address}]."
|
263
|
+
end
|
264
|
+
|
265
|
+
def receive_mails()
|
266
|
+
mail_files = []
|
267
|
+
lock do
|
268
|
+
@receive_servers.each do |server|
|
269
|
+
begin
|
270
|
+
name = "#{server['options']['user_name']}@#{server['options']['address']}"
|
271
|
+
@log.debug "Check mails to #{name}."
|
272
|
+
Mail.defaults do
|
273
|
+
retriever_method(server["protocol"].to_sym, server["options"].symbolize_keys)
|
274
|
+
end
|
275
|
+
Mail.all(delete_after_find: true).each do |mail|
|
276
|
+
filename = mail_filename(mail)
|
277
|
+
File.binwrite(File.join(@maillogs_dir, "temp", filename), mail.raw_source)
|
278
|
+
@log.info "I got new mail[#{filename}]."
|
279
|
+
mail_files.push(filename)
|
280
|
+
end
|
281
|
+
rescue => e
|
282
|
+
@log.error "Mail Check Error!(#{name})\n #{error_message(e)}"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
return mail_files
|
287
|
+
end
|
288
|
+
|
289
|
+
def create_mail(from: nil, to: nil, subject: "", body: nil, reply_to: nil, options: {})
|
290
|
+
mail = Mail.new
|
291
|
+
mail.charset = @deliver_server["charset"] || "utf-8"
|
292
|
+
from = @deliver_server["address"] unless from
|
293
|
+
mail.from = options["from"] = from if from
|
294
|
+
mail.to = options["to" ] = to if to
|
295
|
+
mail.reply_to = reply_to if reply_to
|
296
|
+
mail.subject = render_text(subject, options)
|
297
|
+
mail.body = render_text(body , options) if body
|
298
|
+
return mail
|
299
|
+
end
|
300
|
+
|
301
|
+
def create_forward_mail(mail, subject)
|
302
|
+
from = @use_address_camouflage ? Array(mail.from).first.to_s : nil
|
303
|
+
new_mail = create_mail(
|
304
|
+
from: from,
|
305
|
+
subject: subject,
|
306
|
+
reply_to: @use_address_camouflage ? nil : @reply_to_address
|
307
|
+
)
|
308
|
+
new_mail.in_reply_to = mail.in_reply_to if mail.in_reply_to
|
309
|
+
new_mail.references = mail.references if mail.references
|
310
|
+
|
311
|
+
if (@enable_html_mail || !mail.html_part)
|
312
|
+
new_mail.content_type = mail.content_type
|
313
|
+
new_mail.content_transfer_encoding = mail.content_transfer_encoding
|
314
|
+
mail_head = new_mail.to_s.sub(/\r\n\r\n.*\z/m, "\r\n\r\n")
|
315
|
+
mail_body = mail.raw_source.gsub(/(\r\n|\n|\r)/, "\r\n").sub(/\A.*?\r\n\r\n/m, "")
|
316
|
+
return Mail.read_from_string(mail_head + mail_body)
|
317
|
+
end
|
318
|
+
|
319
|
+
body_text = mail.body ? mail.body.decoded.to_s : ""
|
320
|
+
if mail.charset && !mail.charset.match(/utf-?8/i) && !mail.text_part
|
321
|
+
body_text.force_encoding(mail.charset)
|
322
|
+
body_text.encode!("utf-8")
|
323
|
+
end
|
324
|
+
body_text = mail.text_part.decoded.to_s if mail.text_part
|
325
|
+
html_text = mail.html_part && mail.html_part.decoded.to_s
|
326
|
+
new_mail.text_part = Mail::Part.new { body body_text }
|
327
|
+
new_mail.html_part = Mail::Part.new { body html_text } if @enable_html_mail && html_text
|
328
|
+
if mail.has_attachments?
|
329
|
+
mail.attachments.each do |attachment|
|
330
|
+
attachment_filename = attachment.filename.to_s
|
331
|
+
if File.extname(attachment_filename).empty?
|
332
|
+
ext = case attachment.mime_type.to_s.downcase
|
333
|
+
when "text/plain"
|
334
|
+
".txt"
|
335
|
+
when "application/pdf"
|
336
|
+
".pdf"
|
337
|
+
when "application/rtf"
|
338
|
+
".rtf"
|
339
|
+
when "application/msword"
|
340
|
+
".doc"
|
341
|
+
when "application/vnd.ms-excel"
|
342
|
+
".xls"
|
343
|
+
when "application/vnd.ms-powerpoint"
|
344
|
+
".ppt"
|
345
|
+
when "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
346
|
+
".docx"
|
347
|
+
when "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
348
|
+
".xlsx"
|
349
|
+
when "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
350
|
+
".pptx"
|
351
|
+
when "application/x-js-taro"
|
352
|
+
".jtd"
|
353
|
+
when "image/gif"
|
354
|
+
".gif"
|
355
|
+
when "image/jpeg"
|
356
|
+
".jpeg"
|
357
|
+
when "image/png"
|
358
|
+
".png"
|
359
|
+
when "application/x-zip-compressed", "application/zip"
|
360
|
+
".zip"
|
361
|
+
else
|
362
|
+
""
|
363
|
+
end
|
364
|
+
attachment_filename += ext
|
365
|
+
end
|
366
|
+
new_mail.attachments[attachment_filename] = attachment.decoded
|
367
|
+
end
|
368
|
+
end
|
369
|
+
return new_mail
|
370
|
+
end
|
371
|
+
|
372
|
+
def create_check_code()
|
373
|
+
return SecureRandom.base64(9)
|
374
|
+
end
|
375
|
+
|
376
|
+
def mail_filename(mail)
|
377
|
+
Time.now.strftime("%Y%m%d-%H%M") +
|
378
|
+
"-#{Digest::SHA512.hexdigest(mail.to_s)[0,16]}.eml"
|
379
|
+
end
|
380
|
+
|
381
|
+
def render_text(text, render_options)
|
382
|
+
render_options.empty? ? text : Liquid::Template.parse(text).render(render_options)
|
383
|
+
end
|
384
|
+
|
385
|
+
def move_mail_file(filename, dir)
|
386
|
+
new_filename = File.join(@maillogs_dir, dir, File.basename(filename))
|
387
|
+
File.rename(filename, new_filename)
|
388
|
+
end
|
389
|
+
|
390
|
+
def error_message(error)
|
391
|
+
"#{error.inspect} #{error.backtrace.first}"
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
|
5
|
+
module SimpleMailingList
|
6
|
+
module System
|
7
|
+
private
|
8
|
+
|
9
|
+
def _setup()
|
10
|
+
ActiveRecord::Base.transaction do |a|
|
11
|
+
ActiveRecord::Migration.create_table :users do |t|
|
12
|
+
t.text :mail_address , null: false
|
13
|
+
t.integer :failed_count , null: false, default: 0
|
14
|
+
t.timestamp :last_failed_at , null: false, default: Time.at(0)
|
15
|
+
t.text :options , null: false, default: "{}"
|
16
|
+
t.timestamps null: false
|
17
|
+
end
|
18
|
+
|
19
|
+
ActiveRecord::Migration.create_table :confirmations do |t|
|
20
|
+
t.text :mail_address , null: false
|
21
|
+
t.text :check_code , null: false
|
22
|
+
t.text :mode , null: false
|
23
|
+
t.text :options , null: false, default: "{}"
|
24
|
+
t.timestamps null: false
|
25
|
+
end
|
26
|
+
|
27
|
+
FileUtils.makedirs(
|
28
|
+
%w[
|
29
|
+
temp
|
30
|
+
register
|
31
|
+
delete
|
32
|
+
register_check
|
33
|
+
delete_check
|
34
|
+
forward
|
35
|
+
bounced
|
36
|
+
unmatched
|
37
|
+
error
|
38
|
+
].map do |dir|
|
39
|
+
File.join(@maillogs_dir, dir)
|
40
|
+
end
|
41
|
+
)
|
42
|
+
end
|
43
|
+
@log.info "Setup successed."
|
44
|
+
end
|
45
|
+
|
46
|
+
def _cleanup(delete_maillogs = false)
|
47
|
+
ActiveRecord::Base.transaction do |a|
|
48
|
+
ActiveRecord::Migration.drop_table(:users)
|
49
|
+
ActiveRecord::Migration.drop_table(:confirmations)
|
50
|
+
|
51
|
+
FileUtils.remove_entry_secure(@maillogs_dir, true) if delete_maillogs
|
52
|
+
end
|
53
|
+
@log.info "Cleanup successed."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "logger"
|
3
|
+
|
4
|
+
require "mail"
|
5
|
+
require "active_record"
|
6
|
+
require "thor"
|
7
|
+
|
8
|
+
require "simple_mailing_list/configfile"
|
9
|
+
require "simple_mailing_list/version"
|
10
|
+
|
11
|
+
module SimpleMailingList
|
12
|
+
class CLI < Thor
|
13
|
+
include SimpleMailingList::System
|
14
|
+
package_name "SimpleMailingList"
|
15
|
+
default_command :main_jobs
|
16
|
+
map "--version" => :version
|
17
|
+
class_option :configfile,
|
18
|
+
aliases: "-c",
|
19
|
+
default: DEFAULT_CONFIGFILE,
|
20
|
+
desc: "configfile(YAML format) path."
|
21
|
+
|
22
|
+
def self.exit_on_failure?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "setup", "create tables and maillog_dir."
|
27
|
+
def setup()
|
28
|
+
require "simple_mailing_list/setup"
|
29
|
+
load_configfile(options[:configfile])
|
30
|
+
_setup()
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "cleanup", "drop tables."
|
34
|
+
option :delete_maillogs,
|
35
|
+
default: false,
|
36
|
+
type: :boolean
|
37
|
+
def cleanup()
|
38
|
+
require "simple_mailing_list/setup"
|
39
|
+
load_configfile(options[:configfile])
|
40
|
+
_cleanup(options[:delete_maillogs])
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "add_user MAIL_ADDRESS [JSON_FORMAT_OPTION]", "add a user."
|
44
|
+
def add_user(address, user_options="{}")
|
45
|
+
require "simple_mailing_list/main"
|
46
|
+
require "json"
|
47
|
+
load_configfile(options[:configfile])
|
48
|
+
_add_user(address, JSON.parse(user_options))
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "delete_user MAIL_ADDRESS", "delete a user."
|
52
|
+
def delete_user(address)
|
53
|
+
require "simple_mailing_list/main"
|
54
|
+
load_configfile(options[:configfile])
|
55
|
+
_delete_user(address)
|
56
|
+
end
|
57
|
+
|
58
|
+
desc "delete_failed_users", "delete users who do not receive mails."
|
59
|
+
option :failed_count,
|
60
|
+
aliases: "-f",
|
61
|
+
default: 10,
|
62
|
+
type: :numeric
|
63
|
+
option :failed_time,
|
64
|
+
aliases: "-t",
|
65
|
+
default: 5 * 24 * 60 * 60,
|
66
|
+
type: :numeric
|
67
|
+
def delete_failed_users()
|
68
|
+
require "simple_mailing_list/delete_old"
|
69
|
+
load_configfile(options[:configfile])
|
70
|
+
_delete_failed_users(options[:failed_count], options[:failed_time])
|
71
|
+
end
|
72
|
+
|
73
|
+
desc "delete_old_confirmations", "delete old confirmations."
|
74
|
+
def delete_old_confirmations()
|
75
|
+
require "simple_mailing_list/delete_old"
|
76
|
+
load_configfile(options[:configfile])
|
77
|
+
_delete_old_confirmations()
|
78
|
+
end
|
79
|
+
|
80
|
+
desc "delete_old_maillogs", "delete old maillogs."
|
81
|
+
def delete_old_maillogs()
|
82
|
+
require "simple_mailing_list/delete_old"
|
83
|
+
load_configfile(options[:configfile])
|
84
|
+
_delete_old_maillogs()
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "check_mails", "check new mails."
|
88
|
+
def check_mails()
|
89
|
+
require "simple_mailing_list/main"
|
90
|
+
load_configfile(options[:configfile])
|
91
|
+
_check_mails()
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "check_mail_file [MAIL_FILE]", "check new mail from file."
|
95
|
+
def check_mail_file(mailfile)
|
96
|
+
require "simple_mailing_list/main"
|
97
|
+
load_configfile(options[:configfile])
|
98
|
+
_check_mail_file(mailfile)
|
99
|
+
end
|
100
|
+
|
101
|
+
desc "main_jobs", "check new mails and delete old confirmations and maillogs."
|
102
|
+
def main_jobs()
|
103
|
+
require "simple_mailing_list/main"
|
104
|
+
require "simple_mailing_list/delete_old"
|
105
|
+
load_configfile(options[:configfile])
|
106
|
+
_check_mails()
|
107
|
+
_delete_old_confirmations()
|
108
|
+
_delete_old_maillogs()
|
109
|
+
end
|
110
|
+
|
111
|
+
desc "loop", "loop main_jobs."
|
112
|
+
option :sleep_time,
|
113
|
+
aliases: "-s",
|
114
|
+
default: 10,
|
115
|
+
type: :numeric,
|
116
|
+
desc: "wait time on a loop."
|
117
|
+
def loop()
|
118
|
+
require "simple_mailing_list/main"
|
119
|
+
require "simple_mailing_list/delete_old"
|
120
|
+
load_configfile(options[:configfile])
|
121
|
+
loop do
|
122
|
+
_check_mails(false)
|
123
|
+
_delete_old_confirmations()
|
124
|
+
_delete_old_maillogs()
|
125
|
+
sleep options[:sleep_time]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
desc "version", "output version."
|
130
|
+
def version()
|
131
|
+
puts "Simple Mailing List - #{SimpleMailingList::VERSION}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "simple_mailing_list/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "simple_mailing_list"
|
8
|
+
spec.version = SimpleMailingList::VERSION
|
9
|
+
spec.authors = ["nodai2hITC"]
|
10
|
+
spec.email = ["nodai2h.itc@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Simple Mailing List System.}
|
13
|
+
spec.description = %q{This is a simple mailing list system.}
|
14
|
+
spec.homepage = "https://github.com/nodai2hITC/simple_mailing_list"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
|
27
|
+
spec.add_dependency "mail"
|
28
|
+
spec.add_dependency "activerecord"
|
29
|
+
spec.add_dependency "liquid"
|
30
|
+
spec.add_dependency "daemons"
|
31
|
+
spec.add_dependency "thor"
|
32
|
+
# spec.add_dependency "mysql2"
|
33
|
+
# spec.add_dependency "pg"
|
34
|
+
spec.add_dependency "sqlite3"
|
35
|
+
end
|