aboutsummaryrefslogtreecommitdiff
path: root/lib/Sietima/Role/Headers.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sietima/Role/Headers.pm')
-rw-r--r--lib/Sietima/Role/Headers.pm93
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