aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2017-01-02 17:43:00 +0000
committerdakkar <dakkar@thenautilus.net>2017-01-02 17:43:00 +0000
commit951a85d25ff25d2f4924a5ce35ce1272000fa017 (patch)
tree4e11189641f6a981b5688d2929d478973e6e9fe4 /lib
parentremove unused --verbose option (diff)
downloadSietima-951a85d25ff25d2f4924a5ce35ce1272000fa017.tar.gz
Sietima-951a85d25ff25d2f4924a5ce35ce1272000fa017.tar.bz2
Sietima-951a85d25ff25d2f4924a5ce35ce1272000fa017.zip
documentation for the base class
Diffstat (limited to 'lib')
-rw-r--r--lib/Sietima.pm212
1 files changed, 207 insertions, 5 deletions
diff --git a/lib/Sietima.pm b/lib/Sietima.pm
index 94e082e..fb74bcc 100644
--- a/lib/Sietima.pm
+++ b/lib/Sietima.pm
@@ -16,6 +16,91 @@ use namespace::clean;
with 'MooX::Traits';
+=head1 NAME
+
+Sietima - minimal mailing list manager
+
+=head1 SYNOPSIS
+
+ use Sietima;
+
+ Sietima->new({
+ return_path => 'the-list@the-domain.tld',
+ subscribers => [ 'person@some.were', @etc ],
+ })->handle_mail_from_stdin;
+
+=head1 DESCRIPTION
+
+Sietima is a minimal mailing list manager written in modern Perl. It
+aims to be the spiritual successor of L<Siesta>.
+
+The base C<Sietima> class does very little: it just puts the email
+message from C<STDIN> into a new envelope using L<< /C<return_path> >>
+as sender and all the L<< /C<subscribers> >> addresses as recipients,
+and sends it.
+
+Additional behaviour is provided via traits / roles. This class
+consumes L<< C<MooX::Traits> >> to simplify composing roles:
+
+ Sietima->with_traits(qw(AvoidDups NoMail))->new(\%args);
+
+These are the traits provided with the default distribution:
+
+=over
+
+=item L<< C<AvoidDups>|Sietima::Role::AvoidDups >>
+
+prevents the sender from receiving copies of their own messages
+
+=item L<< C<Debounce>|Sietima::Role::Debounce >>
+
+avoids mail-loops using a C<X-Been-There> header
+
+=item L<< C<Headers>|Sietima::Role::Headers >>
+
+adds C<List-*> headers to all outgoing messages
+
+=item L<< C<NoMail>|Sietima::Role::NoMail >>
+
+avoids sending messages to subscribers who don't want them
+
+=item L<< C<ReplyTo>|Sietima::Role::ReplyTo >>
+
+optionally sets the C<Reply-To> header to the mailing list address
+
+=item L<< C<SubjectTag>|Sietima::Role::SubjectTag >>
+
+prepends a C<[tag]> to the subject header of outgoing messages that
+aren't already tagged
+
+=item L<< C<SubscriberOnly::Drop>|Sietima::Role::SubscriberOnly::Drop >>
+
+silently drops all messages coming from addresses not subscribed to
+the list
+
+=item L<< C<SubscriberOnly::Moderate>|Sietima::Role::SubscriberOnly::Moderate >>
+
+holds messages coming from addresses not subscribed to the list for
+moderation, and provides commands to manage the moderation queue
+
+=back
+
+The only "configuration mechanism" currently supported is to
+initialise a C<Sietima> object in your driver script, passing all the
+needed values to the constructor. L<< C<Sietima::CmdLine> >> is the
+recommended way of doing that: it adds command-line parsing capability
+to Sietima.
+
+=head1 ATTRIBUTES
+
+=head2 C<return_path>
+
+A L<< C<Email::Address> >> instance, coerced from string if
+necessary. This is the address that Sietima will send messages
+I<from>.
+
+=cut
+
has return_path => (
isa => Address,
is => 'ro',
@@ -23,11 +108,21 @@ has return_path => (
coerce => AddressFromStr,
);
-sub list_addresses($self) {
- return +{
- return_path => $self->return_path,
- };
-}
+=head2 C<subscribers>
+
+An array-ref of L<< C<Sietima::Subscriber> >> objects, defaults to the
+empty array.
+
+Each item can be coerced from a string or a L<< C<Email::Address> >>
+instance, or a hashref of the form
+
+ { address => $string, prefs => \%preferences_hash }
+
+The base Sietima class does not use any per-subscriber preferences,
+but some roles do (L<< C<NoMail>|Sietima::Role::NoMail >>, for
+example)
+
+=cut
my $subscribers_array = ArrayRef[
Subscriber->plus_coercions(
@@ -43,12 +138,33 @@ has subscribers => (
);
sub _build_subscribers { +[] }
+=head2 C<transport>
+
+A L<< C<Email::Sender::Transport> >> instance, which will be used to
+send messages. If not passed in, Sietima uses L<<
+C<Email::Sender::Simple> >>'s L<<
+C<default_transport>|Email::Sender::Simple/default_transport >>.
+
+=cut
+
has transport => (
isa => Transport,
is => 'lazy',
);
sub _build_transport { Email::Sender::Simple->default_transport }
+=head1 METHODS
+
+=head2 C<handle_mail_from_stdin>
+
+ $sietima->handle_mail_from_stdin();
+
+This is the main entry-point when Sietima is invoked from a MTA. It
+will parse a L<< C<Email::MIME> >> object out of the standard input,
+then pass it to L<< /C<handle_mail> >> for processing.
+
+=cut
+
sub handle_mail_from_stdin($self,@) {
my $mail_text = do { local $/; <> };
# we're hoping that, since we probably got called from an MTA/MDA,
@@ -57,6 +173,16 @@ sub handle_mail_from_stdin($self,@) {
return $self->handle_mail($incoming_mail);
}
+=head2 C<handle_mail>
+
+ $sietima->handle_mail($email_mime);
+
+Main driver method: converts the given email message into a list of
+L<< C<Sietima::Message> >> objects by calling L<< /C<munge_mail> >>,
+then sends each of them by calling L<< /C<send_message> >>.
+
+=cut
+
sub handle_mail($self,$incoming_mail) {
state $check = compile(Object,EmailMIME); $check->(@_);
@@ -67,12 +193,42 @@ sub handle_mail($self,$incoming_mail) {
return;
}
+=head2 C<subscribers_to_send_to>
+
+ my $subscribers_aref = $sietima->subscribers_to_send_to($email_mime);
+
+Returns an array-ref of L<< C<Sietima::Subscriber> >> objects that
+should receive copies of the given email message.
+
+In this base class, it just returns the value of the L<<
+/C<subscribers> >> attribute. Roles such as L<<
+C<AvoidDups>|Sietima::Role::AvoidDups >> modify this method to exclude
+some subscribers.
+
+=cut
+
sub subscribers_to_send_to($self,$incoming_mail) {
state $check = compile(Object,EmailMIME); $check->(@_);
return $self->subscribers;
}
+=head2 C<munge_mail>
+
+ my @messages = $sietima->munge_mail($email_mime);
+
+Returns a list of L<< C<Sietima::Message> >> objects representing the
+messages to send to subscribers, based on the given email message.
+
+In this base class, this method returns a single instance to send to
+all L<< /C<subscribers_to_send_to> >>, containing exactly the given
+email message.
+
+Roles such as L<< C<SubjectTag>|Sietima::Role::SubjectTag >> modify
+this method to alter the message.
+
+=cut
+
sub munge_mail($self,$incoming_mail) {
state $check = compile(Object,EmailMIME); $check->(@_);
@@ -83,6 +239,16 @@ sub munge_mail($self,$incoming_mail) {
});
}
+=head2 C<send_message>
+
+ $sietima->send_message($sietima_message);
+
+Sends the given L<< C<Sietima::Message> >> object via the L<<
+/C<transport> >>, but only if the message's
+L<envelope|Sietima::Message/envelope> specifies some recipients.
+
+=cut
+
sub send_message($self,$outgoing_message) {
state $check = compile(Object,Message); $check->(@_);
@@ -99,6 +265,42 @@ sub send_message($self,$outgoing_message) {
sub _trait_namespace { 'Sietima::Role' }
+=head2 C<list_addresses>
+
+ my $addresses_href = $sietima->list_addresses;
+
+Returns a hashref of L<< C<Email::Address> >> instances or strings,
+that declare various addresses related to this list.
+
+This base class declares only the L<< /C<return_path> >>, and does not
+use this method at all.
+
+The L<< C<Headers>|Sietima::Role::Headers >> role uses this to
+populate the various C<List-*> headers.
+
+=cut
+
+sub list_addresses($self) {
+ return +{
+ return_path => $self->return_path,
+ };
+}
+
+=head2 C<command_line_spec>
+
+ my $app_spec_data = $sietima->command_line_spec;
+
+Returns a hashref describing the command line processing for L<<
+C<App::Spec> >>. L<< C<Sietima::CmdLine> >> uses this to build the
+command line parser.
+
+This base class declares a single sub-command, C<send>, that invokes
+the L<< /C<handle_mail_from_stdin> >> method.
+
+Roles can extend this to provide additional sub-commands and options.
+
+=cut
+
sub command_line_spec($self) {
return {
name => 'sietima',