171 end |
143 end |
172 end |
144 end |
173 end |
145 end |
174 end |
146 end |
175 end |
147 end |
176 |
148 alias_method :remove_subscriber, :unsubscribe |
177 |
149 |
178 =begin |
150 |
179 ### Return the Date parsed from the last post to the list. |
151 ### Returns an Array of email addresses of people responsible for |
180 ### |
152 ### moderating subscription of a closed list. |
181 def last_message_date |
153 ### |
182 mail = self.last_post or return nil |
154 def moderators |
183 return mail.date |
155 return self.read_subscriber_dir( 'mod' ) |
184 end |
156 end |
185 |
157 |
186 |
158 ### Returns +true+ if +address+ is a moderator. |
187 ### Return the author of the last post to the list. |
159 ### |
188 ### |
160 def is_moderator?( addr ) |
189 def last_message_author |
161 return self.include?( addr, section: 'mod' ) |
190 mail = self.last_post or return nil |
162 end |
191 return mail.from |
163 |
192 end |
164 ### Subscribe +addr+ to the list as a Moderator. |
193 |
165 ### |
194 |
166 def add_moderator( *addr ) |
195 ### Returns +true+ if subscription to the list is moderated. |
167 return self.subscribe( *addr, section: 'mod' ) |
196 ### |
168 end |
197 def closed? |
169 |
198 return (self.listdir + 'modsub').exist? || (self.listdir + 'remote').exist? |
170 ### Remove +addr+ from the list as a Moderator. |
199 end |
171 ### |
200 |
172 def remove_moderator( *addr ) |
201 |
173 return self.unsubscribe( *addr, section: 'mod' ) |
202 ### Returns +true+ if posting to the list is moderated. |
174 end |
|
175 |
|
176 |
|
177 ### Returns an Array of email addresses denied access |
|
178 ### to the list. |
|
179 ### |
|
180 def blacklisted |
|
181 return self.read_subscriber_dir( 'deny' ) |
|
182 end |
|
183 |
|
184 ### Returns +true+ if +address+ is disallowed from participating. |
|
185 ### |
|
186 def is_blacklisted?( addr ) |
|
187 return self.include?( addr, section: 'deny' ) |
|
188 end |
|
189 |
|
190 ### Blacklist +addr+ from the list. |
|
191 ### |
|
192 def add_blacklisted( *addr ) |
|
193 return self.subscribe( *addr, section: 'deny' ) |
|
194 end |
|
195 |
|
196 ### Remove +addr+ from the blacklist. |
|
197 ### |
|
198 def remove_blacklisted( *addr ) |
|
199 return self.unsubscribe( *addr, section: 'deny' ) |
|
200 end |
|
201 |
|
202 |
|
203 |
|
204 ### Returns an Array of email addresses that act like |
|
205 ### regular subscribers for user-post only lists. |
|
206 ### |
|
207 def allowed |
|
208 return self.read_subscriber_dir( 'allow' ) |
|
209 end |
|
210 |
|
211 ### Returns +true+ if +address+ is given the same benefits as a |
|
212 ### regular subscriber for user-post only lists. |
|
213 ### |
|
214 def is_allowed?( addr ) |
|
215 return self.include?( addr, section: 'allow' ) |
|
216 end |
|
217 |
|
218 ### Add +addr+ to allow posting to user-post only lists, |
|
219 ### when +addr+ isn't a subscriber. |
|
220 ### |
|
221 def add_allowed( *addr ) |
|
222 return self.subscribe( *addr, section: 'allow' ) |
|
223 end |
|
224 |
|
225 ### Remove +addr+ from the allowed list. |
|
226 ### |
|
227 def remove_allowed( *addr ) |
|
228 return self.unsubscribe( *addr, section: 'allow' ) |
|
229 end |
|
230 |
|
231 |
|
232 ### Returns +true+ if message threading is enabled. |
|
233 ### |
|
234 def threaded? |
|
235 return ( self.listdir + 'threaded' ).exist? |
|
236 end |
|
237 |
|
238 ### Disable or enable message threading. |
|
239 ### |
|
240 ### This automatically builds message indexes and thread |
|
241 ### information on an incoming message. |
|
242 ### |
|
243 def threaded=( enable=true ) |
|
244 if enable |
|
245 self.touch( 'threaded' ) |
|
246 else |
|
247 self.unlink( 'threaded' ) |
|
248 end |
|
249 end |
|
250 |
|
251 |
|
252 ### Returns +true+ if the list is configured to respond |
|
253 ### to remote mangement requests. |
|
254 ### |
|
255 def public? |
|
256 return ( self.listdir + 'public' ).exist? |
|
257 end |
|
258 |
|
259 ### Disable or enable remote management requests. |
|
260 ### |
|
261 def public=( enable=true ) |
|
262 if enable |
|
263 self.touch( 'public' ) |
|
264 else |
|
265 self.unlink( 'public' ) |
|
266 end |
|
267 end |
|
268 |
|
269 ### Returns +true+ if the list is not configured to respond |
|
270 ### to remote mangement requests. |
|
271 ### |
|
272 def private? |
|
273 return ! self.public? |
|
274 end |
|
275 |
|
276 ### Disable or enable remote management requests. |
|
277 ### |
|
278 def private=( enable=false ) |
|
279 self.public = ! enable |
|
280 end |
|
281 |
|
282 |
|
283 ### Returns +true+ if the list supports remote administration |
|
284 ### subscribe/unsubscribe requests from moderators. |
|
285 ### |
|
286 def remote_subscriptions? |
|
287 return ( self.listdir + 'remote' ).exist? |
|
288 end |
|
289 |
|
290 ### Disable or enable remote subscription requests. |
|
291 ### |
|
292 def remote_subscriptions=( enable=false ) |
|
293 if enable |
|
294 self.touch( 'remote' ) |
|
295 else |
|
296 self.unlink( 'remote' ) |
|
297 end |
|
298 end |
|
299 |
|
300 |
|
301 ### Returns +true+ if list subscription requests require moderator |
|
302 ### approval. |
|
303 ### |
|
304 def moderated_subscriptions? |
|
305 return ( self.listdir + 'modsub' ).exist? |
|
306 end |
|
307 |
|
308 ### Disable or enable subscription moderation. |
|
309 ### |
|
310 def moderated_subscriptions=( enable=false ) |
|
311 if enable |
|
312 self.touch( 'modsub' ) |
|
313 else |
|
314 self.unlink( 'modsub' ) |
|
315 end |
|
316 end |
|
317 |
|
318 |
|
319 ### Returns +true+ if message moderation is enabled. |
203 ### |
320 ### |
204 def moderated? |
321 def moderated? |
205 return (self.listdir + 'modpost').exist? |
322 return ( self.listdir + 'modpost' ).exist? |
206 end |
323 end |
207 |
324 |
208 |
325 ### Disable or enable message moderation. |
209 ### Return a Mail::Message object loaded from the last post to the list. Returns |
326 ### |
210 ### +nil+ if there are no archived posts. |
327 ### This has special meaning when combined with user_post_only setting. |
|
328 ### Lists act as unmoderated for subscribers, and posts from unknown |
|
329 ### addresses go to moderation. |
|
330 ### |
|
331 def moderated=( enable=false ) |
|
332 if enable |
|
333 self.touch( 'modpost' ) |
|
334 self.touch( 'noreturnposts' ) if self.user_posts_only? |
|
335 else |
|
336 self.unlink( 'modpost' ) |
|
337 self.unlink( 'noreturnposts' ) if self.user_posts_only? |
|
338 end |
|
339 end |
|
340 |
|
341 |
|
342 ### Returns +true+ if posting is only allowed by moderators. |
|
343 ### |
|
344 def moderator_posts_only? |
|
345 return ( self.listdir + 'modpostonly' ).exist? |
|
346 end |
|
347 |
|
348 ### Disable or enable moderation only posts. |
|
349 ### |
|
350 def moderator_posts_only=( enable=false ) |
|
351 if enable |
|
352 self.touch( 'modpostonly' ) |
|
353 else |
|
354 self.unlink( 'modpostonly' ) |
|
355 end |
|
356 end |
|
357 |
|
358 |
|
359 ### Returns +true+ if posting is only allowed by subscribers. |
|
360 ### |
|
361 def user_posts_only? |
|
362 return ( self.listdir + 'subpostonly' ).exist? |
|
363 end |
|
364 |
|
365 ### Disable or enable user only posts. |
|
366 ### This is easily defeated, moderated lists are preferred. |
|
367 ### |
|
368 ### This has special meaning for moderated lists. Lists act as |
|
369 ### unmoderated for subscribers, and posts from unknown addresses |
|
370 ### go to moderation. |
|
371 ### |
|
372 def user_posts_only=( enable=false ) |
|
373 if enable |
|
374 self.touch( 'subpostonly' ) |
|
375 self.touch( 'noreturnposts' )if self.moderated? |
|
376 else |
|
377 self.unlink( 'subpostonly' ) |
|
378 self.unlink( 'noreturnposts' ) if self.moderated? |
|
379 end |
|
380 end |
|
381 |
|
382 |
|
383 |
|
384 ### Returns +true+ if message archival is enabled. |
|
385 ### |
|
386 def archived? |
|
387 return ( self.listdir + 'archived' ).exist? || ( self.listdir + 'indexed' ).exist? |
|
388 end |
|
389 |
|
390 ### Disable or enable message archiving (and indexing.) |
|
391 ### |
|
392 def archive=( enable=true ) |
|
393 if enable |
|
394 self.touch( 'archived' ) |
|
395 self.touch( 'indexed' ) |
|
396 else |
|
397 self.unlink( 'archived' ) |
|
398 self.unlink( 'indexed' ) |
|
399 end |
|
400 end |
|
401 |
|
402 ### Returns +true+ if the message archive is accessible only to |
|
403 ### moderators. |
|
404 ### |
|
405 def private_archive? |
|
406 return ( self.listdir + 'modgetonly' ).exist? |
|
407 end |
|
408 |
|
409 ### Disable or enable private access to the archive. |
|
410 ### |
|
411 def private_archive=( enable=true ) |
|
412 if enable |
|
413 self.touch( 'modgetonly' ) |
|
414 else |
|
415 self.unlink( 'modgetonly' ) |
|
416 end |
|
417 end |
|
418 |
|
419 ### Returns +true+ if the message archive is accessible to anyone. |
|
420 ### |
|
421 def public_archive? |
|
422 return ! self.private_archive? |
|
423 end |
|
424 |
|
425 ### Returns +true+ if the message archive is accessible only to |
|
426 ### list subscribers. |
|
427 ### |
|
428 def guarded_archive? |
|
429 return ( self.listdir + 'subgetonly' ).exist? |
|
430 end |
|
431 |
|
432 ### Disable or enable loimited access to the archive. |
|
433 ### |
|
434 def guarded_archive=( enable=true ) |
|
435 if enable |
|
436 self.touch( 'subgetonly' ) |
|
437 else |
|
438 self.unlink( 'subgetonly' ) |
|
439 end |
|
440 end |
|
441 |
|
442 |
|
443 ### Returns +true+ if message digests are enabled. |
|
444 ### |
|
445 def digested? |
|
446 return ( self.listdir + 'digested' ).exist? |
|
447 end |
|
448 |
|
449 ### Disable or enable message digesting. |
|
450 ### |
|
451 def digest=( enable=true ) |
|
452 if enable |
|
453 self.touch( 'digested' ) |
|
454 else |
|
455 self.unlink( 'digested' ) |
|
456 end |
|
457 end |
|
458 |
|
459 ### If the list is digestable, trigger the digest after this amount |
|
460 ### of message body since the latest digest, in kbytes. |
|
461 ### |
|
462 ### See: ezmlm-tstdig(1) |
|
463 ### |
|
464 def digest_kbytesize |
|
465 size = self.read( 'digsize' ).to_i |
|
466 return size.zero? ? 64 : size |
|
467 end |
|
468 |
|
469 ### If the list is digestable, trigger the digest after this amount |
|
470 ### of message body since the latest digest, in kbytes. |
|
471 ### |
|
472 ### See: ezmlm-tstdig(1) |
|
473 ### |
|
474 def digest_kbytesize=( size=64 ) |
|
475 self.write( 'digsize' ) {|f| f.puts size.to_i } |
|
476 end |
|
477 |
|
478 ### If the list is digestable, trigger the digest after this many |
|
479 ### messages have accumulated since the latest digest. |
|
480 ### |
|
481 ### See: ezmlm-tstdig(1) |
|
482 ### |
|
483 def digest_count |
|
484 count = self.read( 'digcount' ).to_i |
|
485 return count.zero? ? 30 : count |
|
486 end |
|
487 |
|
488 ### If the list is digestable, trigger the digest after this many |
|
489 ### messages have accumulated since the latest digest. |
|
490 ### |
|
491 ### See: ezmlm-tstdig(1) |
|
492 ### |
|
493 def digest_count=( count=30 ) |
|
494 self.write( 'digcount' ) {|f| f.puts count.to_i } |
|
495 end |
|
496 |
|
497 ### If the list is digestable, trigger the digest after this much |
|
498 ### time has passed since the last digest, in hours. |
|
499 ### |
|
500 ### See: ezmlm-tstdig(1) |
|
501 ### |
|
502 def digest_timeout |
|
503 hours = self.read( 'digtime' ).to_i |
|
504 return hours.zero? ? 48 : hours |
|
505 end |
|
506 |
|
507 ### If the list is digestable, trigger the digest after this much |
|
508 ### time has passed since the last digest, in hours. |
|
509 ### |
|
510 ### See: ezmlm-tstdig(1) |
|
511 ### |
|
512 def digest_timeout=( hours=48 ) |
|
513 self.write( 'digtime' ) {|f| f.puts hours.to_i } |
|
514 end |
|
515 |
|
516 |
|
517 ### Returns +true+ if the list requires subscriptions to be |
|
518 ### confirmed. AKA "help" mode if disabled. |
|
519 ### |
|
520 def confirm_subscriptions? |
|
521 return ! ( self.listdir + 'nosubconfirm' ).exist? |
|
522 end |
|
523 |
|
524 ### Disable or enable subscription confirmation. |
|
525 ### AKA "help" mode if disabled. |
|
526 ### |
|
527 def confirm_subscriptions=( enable=true ) |
|
528 if enable |
|
529 self.unlink( 'nosubconfirm' ) |
|
530 else |
|
531 self.touch( 'nosubconfirm' ) |
|
532 end |
|
533 end |
|
534 |
|
535 ### Returns +true+ if the list requires unsubscriptions to be |
|
536 ### confirmed. AKA "jump" mode. |
|
537 ### |
|
538 def confirm_unsubscriptions? |
|
539 return ! ( self.listdir + 'nounsubconfirm' ).exist? |
|
540 end |
|
541 |
|
542 ### Disable or enable unsubscription confirmation. |
|
543 ### AKA "jump" mode. |
|
544 ### |
|
545 def confirm_unsubscriptions=( enable=true ) |
|
546 if enable |
|
547 self.unlink( 'nounsubconfirm' ) |
|
548 else |
|
549 self.touch( 'nounsubconfirm' ) |
|
550 end |
|
551 end |
|
552 |
|
553 |
|
554 ### Returns +true+ if the list requires regular message postings |
|
555 ### to be confirmed by the original sender. |
|
556 ### |
|
557 def confirm_postings? |
|
558 return ( self.listdir + 'confirmpost' ).exist? |
|
559 end |
|
560 |
|
561 ### Disable or enable message confirmation. |
|
562 ### |
|
563 def confirm_postings=( enable=false ) |
|
564 if enable |
|
565 self.touch( 'confirmpost' ) |
|
566 else |
|
567 self.unlink( 'confirmpost' ) |
|
568 end |
|
569 end |
|
570 |
|
571 |
|
572 ### Returns +true+ if the list allows moderators to |
|
573 ### fetch a subscriber list remotely. |
|
574 ### |
|
575 def allow_remote_listing? |
|
576 return ( self.listdir + 'modcanlist' ).exist? |
|
577 end |
|
578 |
|
579 ### Disable or enable the ability for moderators to |
|
580 ### remotely fetch a subscriber list. |
|
581 ### |
|
582 def allow_remote_listing=( enable=false ) |
|
583 if enable |
|
584 self.touch( 'modcanlist' ) |
|
585 else |
|
586 self.unlink( 'modcanlist' ) |
|
587 end |
|
588 end |
|
589 |
|
590 |
|
591 ### Returns +true+ if the list automatically manages |
|
592 ### bouncing subscriber addresses. |
|
593 ### |
|
594 def bounce_warnings? |
|
595 return ! ( self.listdir + 'nowarn' ).exist? |
|
596 end |
|
597 |
|
598 ### Disable or enable automatic bounce probes and warnings. |
|
599 ### |
|
600 def bounce_warnings=( enable=true ) |
|
601 if enable |
|
602 self.unlink( 'nowarn' ) |
|
603 else |
|
604 self.touch( 'nowarn' ) |
|
605 end |
|
606 end |
|
607 |
|
608 |
|
609 ### Return the maximum message size, in bytes. Messages larger than |
|
610 ### this size will be rejected. |
|
611 ### |
|
612 ### See: ezmlm-reject(1) |
|
613 ### |
|
614 def maximum_message_size |
|
615 size = self.read( 'msgsize' ) |
|
616 return size ? size.split( ':' ).first.to_i : 0 |
|
617 end |
|
618 |
|
619 ### Set the maximum message size, in bytes. Messages larger than |
|
620 ### this size will be rejected. |
|
621 ### |
|
622 ### See: ezmlm-reject(1) |
|
623 ### |
|
624 def maximum_message_size=( size=307200 ) |
|
625 if size.to_i.zero? |
|
626 self.unlink( 'msgsize' ) |
|
627 else |
|
628 self.write( 'msgsize' ) {|f| f.puts "#{size.to_i}:0" } |
|
629 end |
|
630 end |
|
631 |
|
632 |
|
633 ### Return the number of messages in the list archive. |
|
634 ### |
|
635 def message_count |
|
636 count = self.read( 'archnum' ) |
|
637 return count ? Integer( count ) : 0 |
|
638 end |
|
639 |
|
640 ### Returns the last message to the list as a Mail::Message, if |
|
641 ### archiving was enabled. |
211 ### |
642 ### |
212 def last_post |
643 def last_post |
213 archivedir = self.listdir + 'archive' |
644 num = self.message_count |
214 return nil unless archivedir.exist? |
645 return if num.zero? |
215 |
646 |
216 # Find the last numbered directory under the archive dir |
647 hashdir = num / 100 |
217 last_archdir = Pathname.glob( archivedir + '[0-9]*' ). |
648 message = "%02d" % [ num % 100 ] |
218 sort_by {|pn| Integer(pn.basename.to_s) }.last |
649 |
219 |
650 post = self.listdir + 'archive' + hashdir.to_s + message.to_s |
220 return nil unless last_archdir |
651 return unless post.exist? |
221 |
652 |
222 # Find the last numbered file under the last numbered directory we found |
653 return Mail.read( post.to_s ) |
223 # above. |
654 end |
224 last_post_path = Pathname.glob( last_archdir + '[0-9]*' ). |
|
225 sort_by {|pn| pn.basename.to_s }.last |
|
226 |
|
227 raise RuntimeError, "unexpectedly empty archive directory '%s'" % [ last_archdir ] \ |
|
228 unless last_post_path |
|
229 |
|
230 require 'pry' |
|
231 binding.pry |
|
232 last_post = TMail::Mail.load( last_post_path.to_s ) |
|
233 end |
|
234 =end |
|
235 |
655 |
236 |
656 |
237 ######### |
657 ######### |
238 protected |
658 protected |
239 ######### |
659 ######### |