Skip to content
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 18 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/codecovio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ on:
push:
branches: ["5-stable"]
pull_request:
branches: ["5-stable"]
branches: ["*"]
jobs:
codecov:
runs-on: ubuntu-latest
container: perl:latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Install modules
run: cpanm --installdeps .
- name: Install modules for the coverage
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/make-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ on:
push:
branches: ["5-stable"]
pull_request:
branches: ["5-stable"]
branches: ["*"]
jobs:
test:
name: Make Test with Perl ${{ matrix.perl }}
Expand All @@ -14,7 +14,9 @@ jobs:
perl: ["5.26", "5.38"]
steps:
- name: Checkout the repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Setup Perl
uses: shogo82148/actions-setup-perl@v1
with:
Expand Down
2 changes: 1 addition & 1 deletion lib/Sisimai/Lhost.pm
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ sub index {
# @return [Array] MTA list with order
return [qw|
Activehunter Amavis AmazonSES AmazonWorkMail Aol ApacheJames Barracuda Bigfoot Biglobe Courier
Domino EZweb EinsUndEins Exchange2003 Exchange2007 Exim FML Facebook GMX GSuite GoogleGroups
Domino DragonFly EZweb EinsUndEins Exchange2003 Exchange2007 Exim FML Facebook GMX GSuite GoogleGroups
Gmail IMailServer InterScanMSS KDDI MXLogic MailFoundry MailMarshalSMTP MailRu McAfee MessageLabs
MessagingServer Notes Office365 OpenSMTPD Outlook Postfix PowerMTA ReceivingSES SendGrid Sendmail
SurfControl V5sendmail Verizon X1 X2 X3 X4 X5 X6 Yahoo Yandex Zoho mFILTER qmail
Expand Down
160 changes: 160 additions & 0 deletions lib/Sisimai/Lhost/DragonFly.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
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 index($mhead->{'from'}, 'MAILER-DAEMON <>') > -1;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line above may not be needed (MAILER-DAEMON)

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 ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

== 0

# 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];

Check warning on line 82 in lib/Sisimai/Lhost/DragonFly.pm

View check run for this annotation

Codecov / codecov/patch

lib/Sisimai/Lhost/DragonFly.pm#L81-L82

Added lines #L81 - L82 were not covered by tests
}
$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];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove ||

$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

1 change: 1 addition & 0 deletions lib/Sisimai/Order.pm
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ sub make {
'mail-could' => ['Sisimai::Lhost::InterScanMSS'],
'mail-delivery' => [
'Sisimai::Lhost::Exim',
'Sisimai::Lhost::DragonFly',
'Sisimai::Lhost::MailRu',
'Sisimai::Lhost::GMX',
'Sisimai::Lhost::EinsUndEins',
Expand Down
1 change: 1 addition & 0 deletions lib/Sisimai/Reason/NoRelaying.pm
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ sub match {
'insecure mail relay',
'is not permitted to relay through this server without authentication',
'mail server requires authentication when attempting to send to a non-local e-mail address', # MailEnable
'no relaying',
'not a gateway',
'not allowed to relay through this machine',
'not an open relay, so get lost',
Expand Down
36 changes: 36 additions & 0 deletions set-of-emails/maildir/bsd/lhost-dragonfly-01.eml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Received: from MAILER-DAEMON
id e0720
by df.example.jp (DragonFly Mail Agent v0.13);
Tue, 11 Jun 2024 18:02:02 +0900
X-Original-To: <pseudo-local-part@google.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:02: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@google.example.com>.

gmail-smtp-in.l.google.com [74.125.203.27] did not like our final DATA:
550-5.7.26 Unauthenticated email from example.jp is not accepted due to domain's
550-5.7.26 DMARC policy. Please contact the administrator of example.jp domain if
550-5.7.26 this was a legitimate mail. To learn about the DMARC initiative, go
550-5.7.26 to
550 5.7.26 https://support.google.com/mail/?p=DmarcRejection 98e67ed59e1d1-2c2d0e28189si6418580a91.13 - gsmtp

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:02:00 +0900
Subject: Nyaan 01
To: <pseudo-local-part@google.example.com>
User-Agent: mail (GNU Mailutils 3.14)
Date: Tue, 11 Jun 2024 18:02:00 +0900
Message-Id: <66681288.e06d1.3824794@df.example.jp>
From: <kijitora@df.example.jp>

Expand Down
32 changes: 32 additions & 0 deletions set-of-emails/maildir/bsd/lhost-dragonfly-02.eml
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>

32 changes: 32 additions & 0 deletions set-of-emails/maildir/bsd/lhost-dragonfly-03.eml
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>

31 changes: 31 additions & 0 deletions set-of-emails/maildir/bsd/lhost-dragonfly-04.eml
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>

32 changes: 32 additions & 0 deletions set-of-emails/maildir/bsd/lhost-dragonfly-05.eml
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>

Loading
Loading