Sietima — a minimalist MLM

Author: dakkar <dakkar@thenautilus.net>

Date: 2016-08-08

A bit of history

Siesta

written in 2003

14 years ago

Class::DBI

no Moo

Perl 5.8

Plugin style

simple base class


sub handle_mail($self,$incoming_mail) {
 my (@outgoing_messages) = $self->munge_mail($incoming_mail);
 for my $outgoing_message (@outgoing_messages) {
  $self->send_message($outgoing_message);
 }
 return;
}
            

provide all the needed extensions points


sub munge_mail($self,$incoming_mail) {
 return Sietima::Message->new({
  mail => $incoming_mail,
  from => $self->return_path,
  to => $self->subscribers_to_send_to($incoming_mail),
 });
}
            

but no more than that

traits / roles

  • AvoidDups
  • Debounce
  • Headers
  • ManualSubscription
  • NoMail
  • ReplyTo
  • SubjectTag
  • SubscriberOnly::Drop
  • SubscriberOnly::Moderate

try to avoid cross-trait dependencies

«ReplyTo needs WithPostAddress» is fine

but «SubscriberOnly::Moderate should be added after Debounce» is not

sadly I couldn't avoid it, suggestions welcome

Driver

App::Spec

minimal spec in base class


sub command_line_spec($self) {
 return {
  name => 'sietima',
  title => 'a simple mailing list manager',
  subcommands => {
   send => {
    op => 'handle_mail_from_stdin',
    summary => 'send email from STDIN',
   },
  },
 };
}
            

enriched by plugins


around command_line_spec => sub ($orig,$self) {
 my $spec = $self->$orig();

 my $list_mail_ids = sub ($self,$runner,$args) {
  $self->mail_store->retrieve_ids_by_tags('moderation');
 };

 my $with_mail_id = sub($cmd) { return (
  summary => "$cmd the given mail, currently held for moderation",
  parameters => [ {
   name => 'mail-id', required => 1,
   summary => "id of the mail to $cmd",
   completion => { op => $list_mail_ids },
  } ],
 ) };

 $spec->{subcommands}{'list-held'} = {
  op => 'list_mails_in_moderation_queue',
  summary => 'list all mails currently held for moderation',
 };
 $spec->{subcommands}{'show-held'} = {
  op => 'show_mail_from_moderation_queue',
  $with_mail_id->('show'),
 };
 $spec->{subcommands}{'resume-held'} = {
  op => sub ($self,$runner,$args) {
   $self->resume($runner->parameters->{'mail-id'});
  },
  $with_mail_id->('resume'),
 };
 $spec->{subcommands}{'drop-held'} = {
  op => sub ($self,$runner,$args) {
   $self->drop($runner->parameters->{'mail-id'});
  },
  $with_mail_id->('drop'),
 };

 return $spec;
};
            

$ sietima-test <TAB>
drop-held   -- drop the given mail, currently held for moderation
help        -- Show command help
list-held   -- list all mails currently held for moderation
resume-held -- resume the given mail, currently held for moderation
send        -- send email from STDIN
show-held   -- show the given mail, currently held for moderation
            

$ sietima-test resume-held <TAB>
0f0571203ef5ee2f786b7f7f2832093ed4c34fe8
4d43ee7a2a17457606c07475b14054839fad9b7e
            

Production ready!

all my lists now run with Sietima

coming soon to a CPAN near you

CPAN is awesome

Email::*, RJBS

Moo, MST + HAARG

Type::Tiny, TOBYINK

App::Spec, TINITA

Test2, EXODIST

Thank you