-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sisimai::Lhost::DragonFly #526
Merged
Merged
Changes from 16 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
f4c9636
Implement Sisimai::Lhost::DragonFly #478
azumakuniyuki 1d7a4da
List Sisimai::Lhost::DragonFly #478
azumakuniyuki 74e2836
Add "no relaying" into the list of error message patterns
azumakuniyuki 9f1bdae
Add "Lhost/DragonFly.pm" into the list of module files #478
azumakuniyuki 3acccfd
Register 28 sample emails generated by DMA: DragonFly Mail Agent #478
azumakuniyuki 45ab931
Test Sisimai::Lhost::DragonFly #478
azumakuniyuki b8ba767
Try to checkout the head branch on Pull-Request
azumakuniyuki 125cd00
?
azumakuniyuki 6a8fdc1
??
azumakuniyuki 40fc862
???
azumakuniyuki d2a61fe
????
azumakuniyuki ce4563e
Try to rename Dragonfly.pm to DragonFly.pm on macOS (1)
azumakuniyuki 31697b8
Try to rename Dragonfly.pm to DragonFly.pm on macOS (2)
azumakuniyuki 23252f7
Try to use checkout-v4
azumakuniyuki 83e477f
No need to check the From: header value #478
azumakuniyuki 397f2e2
Tiny code improvement: Remove `||` #478
azumakuniyuki 23bdc2a
Tiny code improvement #478
azumakuniyuki 7f4958a
Update the comment #478
azumakuniyuki File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package Sisimai::Lhost::DragonFly; | ||
use parent 'Sisimai::Lhost'; | ||
use v5.26; | ||
use strict; | ||
use warnings; | ||
|
||
sub description { 'DragonFly' } | ||
sub inquire { | ||
# Detect an error from DMA: DragonFly Mail Agent | ||
# @param [Hash] mhead Message headers of a bounce email | ||
# @param [String] mbody Message body of a bounce email | ||
# @return [Hash] Bounce data list and message/rfc822 part | ||
# @return [undef] failed to parse or the arguments are missing | ||
# @since v5.0.4 | ||
my $class = shift; | ||
my $mhead = shift // return undef; | ||
my $mbody = shift // return undef; | ||
|
||
return undef unless index($mhead->{'subject'}, 'Mail delivery failed') > -1; | ||
return undef unless grep { rindex($_, ' (DragonFly Mail Agent') > -1 } $mhead->{'received'}->@*; | ||
|
||
state $indicators = __PACKAGE__->INDICATORS; | ||
state $boundaries = ['Original message follows.', 'Message headers follow']; | ||
state $startingof = { | ||
# https://github.com/corecode/dma/blob/ffad280aa40c242aa9a2cb9ca5b1b6e8efedd17e/mail.c#L84 | ||
'message' => ['This is the DragonFly Mail Agent '], | ||
}; | ||
state $messagesof = { | ||
'expired' => [ | ||
# https://github.com/corecode/dma/blob/master/dma.c#L370C1-L374C19 | ||
# dma.c:370| if (gettimeofday(&now, NULL) == 0 && | ||
# dma.c:371| (now.tv_sec - st.st_mtim.tv_sec > MAX_TIMEOUT)) { | ||
# dma.c:372| snprintf(errmsg, sizeof(errmsg), | ||
# dma.c:373| "Could not deliver for the last %d seconds. Giving up.", | ||
# dma.c:374| MAX_TIMEOUT); | ||
# dma.c:375| goto bounce; | ||
# dma.c:376| } | ||
'Could not deliver for the last ', | ||
], | ||
'hostunknown' => [ | ||
# net.c:663| snprintf(errmsg, sizeof(errmsg), "DNS lookup failure: host %s not found", host); | ||
'DNS lookup failure: host ', | ||
], | ||
}; | ||
|
||
my $dscontents = [__PACKAGE__->DELIVERYSTATUS]; | ||
my $emailparts = Sisimai::RFC5322->part($mbody, $boundaries); | ||
my $readcursor = 0; # (Integer) Points the current cursor position | ||
my $recipients = 0; # (Integer) The number of 'Final-Recipient' header | ||
my $v = undef; | ||
|
||
require Sisimai::Address; | ||
require Sisimai::SMTP::Command; | ||
|
||
for my $e ( split("\n", $emailparts->[0]) ) { | ||
# Read error messages and delivery status lines from the head of the email to the previous | ||
# line of the beginning of the original message. | ||
unless( $readcursor ) { | ||
# Beginning of the bounce message or message/delivery-status part | ||
$readcursor |= $indicators->{'deliverystatus'} if index($e, $startingof->{'message'}->[0]) == 0; | ||
next; | ||
} | ||
next unless $readcursor & $indicators->{'deliverystatus'}; | ||
next unless length $e; | ||
|
||
# This is the DragonFly Mail Agent v0.13 at df.example.jp. | ||
# | ||
# There was an error delivering your mail to <kijitora@example.com>. | ||
# | ||
# email.example.jp [192.0.2.25] did not like our RCPT TO: | ||
# 552 5.2.2 <kijitora@example.com>: Recipient address rejected: Mailbox full | ||
# | ||
# Original message follows. | ||
$v = $dscontents->[-1]; | ||
|
||
if( index($e, 'There was an error delivering your mail to <') > -1 ) { | ||
# There was an error delivering your mail to <kijitora@example.com>. | ||
if( $v->{'recipient'} ) { | ||
# There are multiple recipient addresses in the message body. | ||
push @$dscontents, __PACKAGE__->DELIVERYSTATUS; | ||
$v = $dscontents->[-1]; | ||
} | ||
$v->{'recipient'} = Sisimai::Address->s3s4(substr($e, index($e, '<'), -1)); | ||
$recipients++; | ||
|
||
} else { | ||
# Pick the error message | ||
$v->{'diagnosis'} .= $e; | ||
|
||
# Pick the remote hostname, and the SMTP command | ||
# net.c:500| snprintf(errmsg, sizeof(errmsg), "%s [%s] did not like our %s:\n%s", | ||
next if index($e, ' did not like our ') < 0; | ||
next if length $v->{'rhost'} > 0; | ||
|
||
my $p = [split(' ', $e, 3)]; | ||
$v->{'rhost'} = index($p->[0], '.') > 1 ? $p->[0] : $p->[1]; | ||
$v->{'command'} = Sisimai::SMTP::Command->find($e) || ''; | ||
} | ||
} | ||
return undef unless $recipients; | ||
|
||
for my $e ( @$dscontents ) { | ||
$e->{'diagnosis'} = Sisimai::String->sweep($e->{'diagnosis'}); | ||
|
||
SESSION: for my $r ( keys %$messagesof ) { | ||
# Verify each regular expression of session errors | ||
next unless grep { index($e->{'diagnosis'}, $_) > -1 } $messagesof->{ $r }->@*; | ||
$e->{'reason'} = $r; | ||
last; | ||
} | ||
} | ||
return { 'ds' => $dscontents, 'rfc822' => $emailparts->[1] }; | ||
} | ||
|
||
1; | ||
__END__ | ||
|
||
=encoding utf-8 | ||
|
||
=head1 NAME | ||
|
||
Sisimai::Lhost::DragonFly - bounce mail parser class for C<DMA: DragonFly Mail Agent>. | ||
|
||
=head1 SYNOPSIS | ||
|
||
use Sisimai::Lhost::DragonFly; | ||
|
||
=head1 DESCRIPTION | ||
|
||
C<Sisimai::Lhost::DragonFly> parses a bounce email which created by C<DMA: DragonFly Mail Agent>. | ||
Methods in the module are called from only C<Sisimai::Message>. | ||
|
||
=head1 CLASS METHODS | ||
|
||
=head2 C<B<description()>> | ||
|
||
C<description()> returns description string of this module. | ||
|
||
print Sisimai::Lhost::DragonFly->description; | ||
|
||
=head2 C<B<inquire(I<header data>, I<reference to body string>)>> | ||
|
||
C<inquire()> method parses 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 azumakuniyuki, All rights reserved. | ||
|
||
=head1 LICENSE | ||
|
||
This software is distributed under The BSD 2-Clause License. | ||
|
||
=cut | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
Received: from MAILER-DAEMON | ||
id e0720 | ||
by df.example.jp (DragonFly Mail Agent v0.13); | ||
Tue, 11 Jun 2024 18:04:02 +0900 | ||
X-Original-To: <pseudo-local-part@outlook.example.com> | ||
From: MAILER-DAEMON <> | ||
To: kijitora@df.example.jp | ||
Subject: Mail delivery failed | ||
Message-Id: <e0720@df.example.jp> | ||
Date: Tue, 11 Jun 2024 18:04:02 +0900 | ||
|
||
This is the DragonFly Mail Agent v0.13 at df.example.jp. | ||
|
||
There was an error delivering your mail to <pseudo-local-part@outlook.example.com>. | ||
|
||
outlook-com.olc.protection.outlook.com [52.101.42.17] did not like our final DATA: | ||
550 5.7.509 Access denied, sending domain [DF.EXAMPLE.JP] does not pass DMARC verification and has a DMARC policy of reject. [TYCP286MB3363.JPNP286.PROD.OUTLOOK.COM 2024-06-11T09:04:02.679Z 08DC8850F12E1502] [MW4PR04CA0381.namprd04.prod.outlook.com 2024-06-11T09:04:02.743Z 08DC87B4931D8FD2] [CO1PEPF000066EC.namprd05.prod.outlook.com 2024-06-11T09:04:02.731Z 08DC89E7235090DB] | ||
|
||
Message headers follow. | ||
|
||
Received: from root (uid 0) | ||
(envelope-from kijitora@df.example.jp) | ||
id e06d1 | ||
by df.example.jp (DragonFly Mail Agent v0.13); | ||
Tue, 11 Jun 2024 18:04:00 +0900 | ||
Subject: Nyaan 01 | ||
To: <pseudo-local-part@outlook.example.com> | ||
User-Agent: mail (GNU Mailutils 3.14) | ||
Date: Tue, 11 Jun 2024 18:04:00 +0900 | ||
Message-Id: <66681300.e06d1.6964aaf9@df.example.jp> | ||
From: <kijitora@df.example.jp> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
Received: from MAILER-DAEMON | ||
id e0720 | ||
by df.example.jp (DragonFly Mail Agent v0.13); | ||
Tue, 11 Jun 2024 18:09:35 +0900 | ||
X-Original-To: <pseudo-local-part@yahoo-inc.example.com> | ||
From: MAILER-DAEMON <> | ||
To: kijitora@df.example.jp | ||
Subject: Mail delivery failed | ||
Message-Id: <e0720@df.example.jp> | ||
Date: Tue, 11 Jun 2024 18:09:35 +0900 | ||
|
||
This is the DragonFly Mail Agent v0.13 at df.example.jp. | ||
|
||
There was an error delivering your mail to <pseudo-local-part@yahoo-inc.example.com>. | ||
|
||
mta5.am0.yahoodns.net [67.195.204.79] did not like our final DATA: | ||
554 5.7.9 Message not accepted for policy reasons. See https://senders.yahooinc.com/error-codes | ||
|
||
Message headers follow. | ||
|
||
Received: from root (uid 0) | ||
(envelope-from kijitora@df.example.jp) | ||
id e06d1 | ||
by df.example.jp (DragonFly Mail Agent v0.13); | ||
Tue, 11 Jun 2024 18:09:33 +0900 | ||
Subject: Nyaan 01 | ||
To: <pseudo-local-part@yahoo-inc.example.com> | ||
User-Agent: mail (GNU Mailutils 3.14) | ||
Date: Tue, 11 Jun 2024 18:09:33 +0900 | ||
Message-Id: <6668144d.e06d1.1bdca37a@df.example.jp> | ||
From: <kijitora@df.example.jp> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
Received: from MAILER-DAEMON | ||
id e0724 | ||
by df.example.jp (DragonFly Mail Agent v0.13); | ||
Tue, 11 Jun 2024 18:15:33 +0900 | ||
X-Original-To: <postmaster@cx.libsisimai.org> | ||
From: MAILER-DAEMON <> | ||
To: kijitora@df.example.jp | ||
Subject: Mail delivery failed | ||
Message-Id: <e0724@df.example.jp> | ||
Date: Tue, 11 Jun 2024 18:15:33 +0900 | ||
|
||
This is the DragonFly Mail Agent v0.13 at df.example.jp. | ||
|
||
There was an error delivering your mail to <postmaster@cx.libsisimai.org>. | ||
|
||
DNS lookup failure: host cx.libsisimai.org not found | ||
|
||
Message headers follow. | ||
|
||
Received: from root (uid 0) | ||
(envelope-from kijitora@df.example.jp) | ||
id e0722 | ||
by df.example.jp (DragonFly Mail Agent v0.13); | ||
Tue, 11 Jun 2024 18:15:33 +0900 | ||
Subject: Nyaan 01 | ||
To: <postmaster@cx.libsisimai.org> | ||
User-Agent: mail (GNU Mailutils 3.14) | ||
Date: Tue, 11 Jun 2024 18:15:33 +0900 | ||
Message-Id: <666815b5.e0722.4e479ce6@df.example.jp> | ||
From: <kijitora@df.example.jp> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
Received: from MAILER-DAEMON | ||
id e0724 | ||
by df.example.jp (DragonFly Mail Agent v0.13); | ||
Tue, 11 Jun 2024 18:17:34 +0900 | ||
X-Original-To: <authfailure@libsisimai.net> | ||
From: MAILER-DAEMON <> | ||
To: kijitora@df.example.jp | ||
Subject: Mail delivery failed | ||
Message-Id: <e0724@df.example.jp> | ||
Date: Tue, 11 Jun 2024 18:17:34 +0900 | ||
|
||
This is the DragonFly Mail Agent v0.13 at df.example.jp. | ||
|
||
There was an error delivering your mail to <authfailure@libsisimai.net>. | ||
|
||
mail-inbound.libsisimai.net [192.0.2.25] did not like our RCPT TO: | ||
550 5.7.26 <authfailure@libsisimai.net>: Recipient address rejected: Multiple authentication checks failed | ||
|
||
Message headers follow. | ||
|
||
Received: from root (uid 0) | ||
(envelope-from kijitora@df.example.jp) | ||
id e0722 | ||
by df.example.jp (DragonFly Mail Agent v0.13); | ||
Tue, 11 Jun 2024 18:17:33 +0900 | ||
Subject: Nyaan 01 | ||
To: <authfailure@libsisimai.net> | ||
User-Agent: mail (GNU Mailutils 3.14) | ||
Date: Tue, 11 Jun 2024 18:17:33 +0900 | ||
Message-Id: <6668162d.e0722.3a6a6f36@df.example.jp> | ||
From: <kijitora@df.example.jp> | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
== 0