package Sisimai::RFC3464::ThirdParty;
use v5.26;
use strict;
use warnings;

state $ThirdParty = {
    #"Aol"     => ["X-Outbound-Mail-Relay-"], # X-Outbound-Mail-Relay-(Queue-ID|Sender)
    "PowerMTA" => ["X-PowerMTA-"],            # X-PowerMTA-(VirtualMTA|BounceCategory)
    #"Yandex"  => ["X-Yandex-"],              # X-Yandex-(Queue-ID|Sender)
};

sub is3rdparty {
    # is3rdparty() returns true if the argument is a line generated by a MTA which have fields defined
    # in RFC3464 inside of a bounce mail the MTA returns
    # @param    string argv1   A line of a bounce mail
    # @return   bool           The line indicates that a bounce mail generated by the 3rd party MTA
    my $class = shift;
    my $argv1 = shift || return 0; return __PACKAGE__->returnedby($argv1) ? 1 : 0;
}

sub returnedby {
    # returnedby() returns an MTA name of the 3rd party
    # @param    string argv1   A line of a bounce mail
    # @return   string         An MTA name of the 3rd party
    my $class = shift;
    my $argv1 = shift || return 0; return 0 unless index($argv1, "X-") == 0;

    for my $e ( keys %$ThirdParty ) {
        # Does the argument include the 3rd party specific field?
        return $e if index($argv1, $ThirdParty->{ $e }->[0]) == 0;
    }
    return ""
}

sub xfield {
    # xfield() returns rfc1894.Field() compatible slice for the specific field of the 3rd party MTA
    # @param    string argv1  A line of the error message
    # @return   []            RFC1894->field() compatible array
    # @see      Sisimai::RFC1894
    my $class = shift;
    my $argv1 = shift || return [];
    my $party = __PACKAGE__->returnedby($argv1); return [] unless $party;
    return sprintf("Sisimai::RFC3464::ThirdParty::%s", $party)->xfield($argv1);
}
1;

# -------------------------------------------------------------------------------------------------
package Sisimai::RFC3464::ThirdParty::PowerMTA;
use v5.26;
use strict;
use warnings;

state $FieldGroup = {
    "x-powermta-virtualmta"     => "host", # X-PowerMTA-VirtualMTA: mx22.neko.example.jp
    "x-powermta-bouncecategory" => "text", # X-PowerMTA-BounceCategory: bad-mailbox
};
state $MessagesOf = {
    "bad-domain"          => "hostunknown",
    "bad-mailbox"         => "userunknown",
    "inactive-mailbox"    => "disabled",
    "message-expired"     => "expired",
    "no-answer-from-host" => "networkerror",
    "policy-related"      => "policyviolation",
    "quota-issues"        => "mailboxfull",
    "routing-errors"      => "systemerror",
    "spam-related"        => "spamdetected",
};

sub xfield {
    # Returns an array which is compatible with the value returned from Sisimai::RFC1894->field()
    # @param    string argv1   A line of the error message
    # @return   Array          ["field-name", "value-type", "value", "field-group", "comment"]
    # @see      https://bird.com/email/power-mta
    my $class = shift;
    my $argv1 = shift || return [];

    my $fieldparts = [split(":", $argv1, 2)]; # ["Final-Recipient", " rfc822; <neko@nyaan.jp>"]
    my $xfieldname = lc $fieldparts->[0];     # "final-recipient"
    my $xgroupname = $FieldGroup->{ $xfieldname }; return [] unless $xgroupname;
    my $xfieldlist = ["", "", Sisimai::String->sweep($fieldparts->[1]), $xgroupname, "", "PowerMTA"];

    # - 0: Field-Name
    # - 1: Sub Type: RFC822, DNS, X-Unix, and so on)
    # - 2: Value
    # - 3: Field Group(addr, code, date, host, stat, text)
    # - 4: Comment
    # - 5: 3rd Party MTA-Name
    if( $xfieldname eq "x-powermta-bouncecategory" ) {
        # X-PowerMTA-BounceCategory: bad-mailbox
        # Set the bounce reason picked from the value of the field
        $xfieldlist->[0] = $xfieldname;
        $xfieldlist->[4] = sprintf("reason:%s", $MessagesOf->{ $xfieldlist->[2] } || "");

    } elsif( $xfieldname eq "x-powermta-virtualmta" ) {
        # X-PowerMTA-VirtualMTA: mx22.neko.example.jp
        $xfieldlist->[0] = "Reporting-MTA";
    }

    return $xfieldlist;
}

1;

__END__
=encoding utf-8

=head1 NAME

Sisimai::RFC3464::ThirdParty - bounce mail decoder class for a bounce mail which have fields defined
in RFC3464 and some fields begin with "X-"

=head1 SYNOPSIS

    use Sisimai::RFC3464::ThirdParty;

=head1 DESCRIPTION

C<Sisimai::RFC3464::ThirdParty> is a class which called from called from only C<Sisimai::RFC3464> 
when the bounce message have a field which begins with "X-" such as "X-PowerMTA-BounceCategory:"

=head1 CLASS METHODS

=head2 C<B<is3rdparty()>>

C<is3rdparty()> method returns true when the argument is a supported "X-" field

    print Sisimai::RFC3464->is3rdparty();

=head2 C<B<inquire(I<header data>, I<reference to body string>)>>

C<inquire()> method method decodes a bounced email and return results as an array reference.
See C<Sisimai::Message> for more details.

=head1 AUTHOR

azumakuniyuki

=head1 COPYRIGHT

Copyright (C) 2024,2025 azumakuniyuki, All rights reserved.

=head1 LICENSE

This software is distributed under The BSD 2-Clause License.

=cut

