diff options
Diffstat (limited to 'lib/Sietima/Role/Headers.pm')
-rw-r--r-- | lib/Sietima/Role/Headers.pm | 93 |
1 files changed, 72 insertions, 21 deletions
diff --git a/lib/Sietima/Role/Headers.pm b/lib/Sietima/Role/Headers.pm index 1f11ecc..db58706 100644 --- a/lib/Sietima/Role/Headers.pm +++ b/lib/Sietima/Role/Headers.pm @@ -2,10 +2,13 @@ package Sietima::Role::Headers; use Moo::Role; use Try::Tiny; use Sietima::Policy; +use Sietima::HeaderURI; +use Email::Address; use Types::Standard qw(Str); +use Sietima::Types qw(HeaderUriFromThings); use namespace::clean; -our $VERSION = '1.0.0'; # VERSION +our $VERSION = '1.0.1'; # VERSION # ABSTRACT: adds standard list-related headers to messages @@ -15,6 +18,23 @@ has name => ( required => 0, ); +sub _normalise_address($self,$address) { + my @items = ref($address) eq 'ARRAY' ? $address->@* : $address; + + return map { + HeaderUriFromThings->coerce($_) + } @items; +} + +sub _set_header($self,$mail,$name,$value) { + my $header_name = 'List-' . ucfirst($name =~ s{[^[:alnum:]]+}{-}gr); + my @items = $self->_normalise_address($value); + + $mail->header_raw_set( + $header_name => join ', ', map { $_->as_header_raw } @items, + ); +} + sub _add_headers_to($self,$message) { my $addresses = $self->list_addresses; my $mail = $message->mail; @@ -23,7 +43,7 @@ sub _add_headers_to($self,$message) { # Identification of Mailing Lists" my $return_path = delete $addresses->{return_path}; if (my $name = $self->name) { - $mail->header_str_set( + $mail->header_raw_set( 'List-Id', sprintf '%s <%s>', $name,$return_path->address =~ s{\@}{.}r, ); @@ -31,22 +51,19 @@ sub _add_headers_to($self,$message) { # if nobody declared a "post" address, let's guess it's the same # as the address we send from - $addresses->{post} //= $return_path; + if (not exists $addresses->{post}) { + $self->_set_header( $mail, post => $return_path ); + } + # but if they explicitly set a false value, this list does not + # allow posting, so we need to set the special value 'NO' + elsif (not $addresses->{post}) { + delete $addresses->{post}; + $mail->header_raw_set('List-Post','NO'); + } + # otherwise we can treat 'post' as normal for my $name (sort keys $addresses->%*) { - my $header_name = 'List-' . ucfirst($name =~ s{[^[:alnum:]]+}{-}gr); - my $address = $addresses->{$name}; - - # if it's not an Email::Address obect, we'll just take it as a - # string: it could be a non-mailto URI, see RFC 2369 "The Use - # of URLs as Meta-Syntax for Core Mail List Commands and their - # Transport through Message Header Fields" - - $mail->header_str_set( - $header_name => try { - sprintf '<mailto:%s>',$address->address - } catch { "<$address>" }, - ); + $self->_set_header( $mail, $name => $addresses->{$name} ); } return; } @@ -72,7 +89,7 @@ Sietima::Role::Headers - adds standard list-related headers to messages =head1 VERSION -version 1.0.0 +version 1.0.1 =head1 SYNOPSIS @@ -95,10 +112,44 @@ $self->list_addresses->{return_path} >> value (which is normally the same as the L<< C<return_path>|Sietima/return_path >> attribute). Other C<List-*:> headers are built from the other values in the -C<list_addresses> hashref. Those values can either be L<< -C<Email::Address> >> objects (in which case the header will have a -C<mailto:> URI as value) or strings (which will be used literally for -the value of the header). +C<list_addresses> hashref. Each of those values can be: + +=over 4 + +=item * + +an L<< C<Sietima::HeaderURI> >> object + +=item * + +a thing that can be passed to that class's constructor: + +=over 4 + +=item * + +an L<< C<Email::Address> >> object + +=item * + +a L<< C<URI> >> object + +=item * + +a string parseable as either + +=back + +=item * + +an arrayref containing any mix of the above + +=back + +As a special case, if C<< $self->list_addresses->{post} >> exists and +is false, the C<List-Post> header will have the value C<NO> to +indicate that the list does not accept incoming messages (e.g. it's an +announcement list). =head1 ATTRIBUTES |