File Coverage

lib/Sisimai/Rhost/NTTDOCOMO.pm
Criterion Covered Total %
statement 22 24 91.6
branch 9 14 64.2
condition 9 11 81.8
subroutine 4 4 100.0
pod 0 1 0.0
total 44 54 81.4


line stmt bran cond sub pod time code
1             package Sisimai::Rhost::NTTDOCOMO;
2 7     7   3741 use v5.26;
  7         31  
3 7     7   43 use strict;
  7         12  
  7         187  
4 7     7   31 use warnings;
  7         12  
  7         2637  
5              
6             sub find {
7             # Detect bounce reason from NTT docomo
8             # @param [Sisimai::Fact] argvs Decoded email object
9             # @return [String] The bounce reason for docomo.ne.jp
10             # @since v4.25.15
11 67     67 0 1253 my $class = shift;
12 67 100 100     296 my $argvs = shift // return ""; return "" unless $argvs->{'diagnosticcode'};
  66         244  
13              
14 65         590 my $messagesof = {
15             'mailboxfull' => ['552 too much mail data'],
16             'ratelimited' => ['552 too many recipients'],
17             'syntaxerror' => ['503 bad sequence of commands', '504 command parameter not implemented'],
18             'userunknown' => ['550 unknown user'],
19             };
20 65   100     335 my $statuscode = $argvs->{'deliverystatus'} || '';
21 65   50     280 my $issuedcode = lc $argvs->{'diagnosticcode'} || '';
22 65   100     563 my $thecommand = $argvs->{'command'} || '';
23              
24             # Check the value of Status: field, an SMTP Reply Code, and the SMTP Command
25             #
26             # ----- Transcript of session follows -----
27             # ... while talking to mfsmax.docomo.ne.jp.:
28             # >>> RCPT To:<***@docomo.ne.jp>
29             # <<< 550 Unknown user ***@docomo.ne.jp
30             # 550 5.1.1 <***@docomo.ne.jp>... User unknown
31             # >>> DATA
32             # <<< 503 Bad sequence of commands
33             # ---------------------------------------------------------------------------------------------
34             # ----- The following addresses had permanent fatal errors -----
35             # <***@docomo.ne.jp>
36             # (reason: 550 Unknown user ***@docomo.ne.jp)
37             #
38             # ----- Transcript of session follows -----
39             # ... while talking to mfsmax.docomo.ne.jp.:
40             # >>> DATA
41             # <<< 550 Unknown user ***@docomo.ne.jp
42             # 554 5.0.0 Service unavailable
43             # ...
44             # Final-Recipient: RFC822; ***@docomo.ne.jp
45             # Action: failed
46             # Status: 5.2.0
47 65 100 66     418 return 'userunknown' if $statuscode eq '5.1.1' || $statuscode eq '5.9.213';
48 60 100       240 return 'filtered' if $statuscode eq '5.2.0';
49              
50 44         162 for my $e ( keys %$messagesof ) {
51             # The value of "Diagnostic-Code:" field is not empty
52             # - The key name is a bounce reason name
53             # - https://github.com/sisimai/go-sisimai/issues/64
54             # - After March 12, 2025, if an error message contains "550 Unknown user", the
55             # bounce reason will be definitively "userunknown". This is because NTT DOCOMO
56             # no longer rejects emails via SMTP for domain-specific rejection or specified
57             # reception filters.
58 111 100       185 return $e if grep { index($issuedcode, $_) > -1 } $messagesof->{ $e }->@*;
  137         515  
59             }
60              
61             # A bounce reason did not decide from a status code, an error message.
62 12 50       86 if( $statuscode eq '5.0.0' ) {
63             # Your message to the following recipients cannot be delivered:
64             #
65             # <***@docomo.ne.jp>:
66             # mfsmax.docomo.ne.jp [203.138.181.112]:
67             # >>> RCPT TO:<***@docomo.ne.jp>
68             # <<< 550 Unknown user ***@docomo.ne.jp
69             # ...
70             #
71             # Final-Recipient: rfc822; ***@docomo.ne.jp
72             # Action: failed
73             # Status: 5.0.0
74             # Remote-MTA: dns; mfsmax.docomo.ne.jp [203.138.181.112]
75             # Diagnostic-Code: smtp; 550 Unknown user ***@docomo.ne.jp
76             # -----------------------------------------------------------------------------------------
77             # <***@docomo.ne.jp>: host mfsmax.docomo.ne.jp[203.138.181.240] said:
78             # 550 Unknown user ***@docomo.ne.jp (in reply to end of DATA
79             # command)
80             # ...
81             # Final-Recipient: rfc822; ***@docomo.ne.jp
82             # Original-Recipient: rfc822;***@docomo.ne.jp
83             # Action: failed
84             # Status: 5.0.0
85             # Remote-MTA: dns; mfsmax.docomo.ne.jp
86             # Diagnostic-Code: smtp; 550 Unknown user ***@docomo.ne.jp
87 0 0       0 return 'userunknown' if $thecommand eq 'RCPT';
88 0 0       0 return 'rejected' if $thecommand eq 'DATA';
89             }
90              
91             # 1. Rejected by other SMTP commands: AUTH, MAIL,
92             # 2. Status: field is neither 5.0.0 nor values defined in code above
93             # もしもこのブロックを通過するNTTドコモからのエラーメッセージを見つけたら
94             # https://github.com/sisimai/p5-sisimai/issues からご連絡ねがいます。
95             #
96             # If you found a error message from mfsmax.docomo.ne.jp which passes this block,
97             # please open an issue at https://github.com/sisimai/p5-sisimai/issues .
98 12         74 return "";
99             }
100              
101             1;
102             __END__