+=head2 determine_recipients
+
+ my @recipients = determine_recipients(recipients => \%recipients,
+ bcc => 1,
+ );
+ my %recipients => determine_recipients(recipients => \%recipients,);
+
+ # or a crazy example:
+ send_mail_message(message => $message,
+ recipients =>
+ [make_list(
+ values %{{determine_recipients(
+ recipients => \%recipients)
+ }})
+ ],
+ );
+
+Using the recipient hashref, determines the set of recipients.
+
+If you specify one of C<bcc>, C<cc>, or C<to>, you will receive only a
+LIST of recipients which the main should be Bcc'ed, Cc'ed, or To'ed
+respectively. By default, a LIST with keys bcc, cc, and to is returned
+with ARRAYREF values corresponding to the users to whom a message
+should be sent.
+
+=over
+
+=item address_only -- whether to only return mail addresses without reasons or realnamesq
+
+=back
+
+Passing more than one of bcc, cc or to is a fatal error.
+
+=cut
+
+sub determine_recipients {
+ my %param = validate_with(params => \@_,
+ spec => {recipients => {type => HASHREF,
+ },
+ bcc => {type => BOOLEAN,
+ default => 0,
+ },
+ cc => {type => BOOLEAN,
+ default => 0,
+ },
+ to => {type => BOOLEAN,
+ default => 0,
+ },
+ address_only => {type => BOOLEAN,
+ default => 0,
+ }
+ },
+ );
+
+ if (1 < scalar grep {$param{$_}} qw(to cc bcc)) {
+ croak "Passing more than one of to, cc, or bcc is non-sensical";
+ }
+
+ my %final_recipients;
+ # start with the to recipients
+ for my $addr (keys %{$param{recipients}}) {
+ my $level = 'bcc';
+ my @reasons;
+ for my $reason (keys %{$param{recipients}{$addr}}) {
+ my @bugs;
+ for my $bug (keys %{$param{recipients}{$addr}{$reason}}) {
+ push @bugs, $bug;
+ my $t_level = $param{recipients}{$addr}{$reason}{$bug};
+ if ($level eq 'to' or
+ $t_level eq 'to') {
+ $level = 'to';
+ }
+ elsif ($t_level eq 'cc') {
+ $level = 'cc';
+ }
+ }
+ # RFC 2822 comments cannot contain specials and
+ # unquoted () or \; there's no reason for us to allow
+ # insane things here, though, so we restrict this even
+ # more to 20-7E ( -~)
+ $reason =~ s/\\/\\\\/g;
+ $reason =~ s/([\)\(])/\\$1/g;
+ $reason =~ s/[^\x20-\x7E]//g;
+ push @reasons, $reason . ' for {'.join(',',@bugs).'}';
+ }
+ if ($param{address_only}) {
+ push @{$final_recipients{$level}}, get_addresses($addr);
+ }
+ else {
+ push @{$final_recipients{$level}}, $addr . ' ('.join(', ',@reasons).')';
+ }
+ }
+ for (qw(to cc bcc)) {
+ if ($param{$_}) {
+ if (exists $final_recipients{$_}) {
+ return @{$final_recipients{$_}||[]};
+ }
+ return ();
+ }
+ }
+ return %final_recipients;
+}
+
+