Haineko
view release on metacpan or search on metacpan
lib/Haineko/Sendmail.pm view on Meta::CPAN
my $relayclass = q(); # (String) Class name of $smtpmailer
my $smtpmailer = undef; # (Haineko::SMTPD::Relay::*) Mailer object
my $relayingto = undef; # (Ref->Hash) Mailertable
my $credential = undef; # (Ref->Hash) Username and password for SMTP-AUTH or API
$relayingto = $mailerconf->{'rcpt'}->{ $r->host } // $sendershub;
$relayingto = $sendershub if $relayingto->{'disabled'};
$relayingto = $defaulthub unless keys %$relayingto;
$relayingto = $defaulthub if $relayingto->{'disabled'};
$relayingto->{'port'} //= 25;
$relayingto->{'host'} //= '127.0.0.1';
$relayingto->{'mailer'} //= 'ESMTP';
if( $relayingto->{'auth'} ) {
$credential = $autheninfo->{ $relayingto->{'auth'} } // {};
}
$relayingto->{'auth'} = q() unless keys %$credential;
if( $relayingto->{'mailer'} =~ m/\A(?:ESMTP|Haineko|MX)\z/ ) {
# Use Haineko::SMTPD::Relay::ESMTP or Haineko::SMTPD::Relay::Haineko
# ::MX = Directly connect to the host listed in MX Resource record
# ::ESMTP = Generic SMTP connection to an external server
# ::Haineko = Relay an message to Haineko running on other host
my $methodargv = {
'ehlo' => $serverconf->{'hostname'},
'mail' => $submission->addresser->address,
'rcpt' => $r->address,
'head' => $mailheader,
'body' => \$body,
'attr' => $attributes,
'host' => $relayingto->{'host'} // '127.0.0.1',
'retry' => $relayingto->{'retry'} // 0,
'sleep' => $relayingto->{'sleep'} // 5,
'timeout' => $relayingto->{'timeout'} // 59,
'starttls' => $relayingto->{'starttls'},
};
if( $relayingto->{'mailer'} eq 'ESMTP' ) {
# use well-known port for SMTP
$methodargv->{'port'} = $relayingto->{'port'} // 25;
$methodargv->{'debug'} = $relayingto->{'debug'} // 0;
} elsif( $relayingto->{'mailer'} eq 'Haineko' ) {
# Haineko uses 2794 by default
$methodargv->{'port'} = $relayingto->{'port'} // 2794;
} elsif( $relayingto->{'mailer'} eq 'MX' ) {
# Mail Exchanger is waiting on *:25
$methodargv->{'port'} = 25;
$methodargv->{'debug'} = $relayingto->{'debug'} // 0;
}
$relayclass = sprintf( "Haineko::SMTPD::Relay::%s", $relayingto->{'mailer'} );
Module::Load::load( $relayclass );
$smtpmailer = $relayclass->new( %$methodargv );
if( $relayingto->{'auth'} ) {
# Load credentials for SMTP-AUTH
$smtpmailer->auth( 1 );
$smtpmailer->username( $credential->{'username'} );
$smtpmailer->password( $credential->{'password'} );
}
$smtpmailer->sendmail();
} elsif( $relayingto->{'mailer'} =~ m/(?:Discard|Screen)/ ) {
# These mailer does not open new connection to any host.
# Haineko::SMTPD::Relay::
# - Discard: email blackhole. It will discard all messages
# - Screen: print the email message to STDERR
$relayclass = sprintf( "Haineko::SMTPD::Relay::%s", $relayingto->{'mailer'} );
Module::Load::load( $relayclass );
my $methodargv = {
'ehlo' => $serverconf->{'hostname'},
'mail' => $submission->addresser->address,
'rcpt' => $r->address,
'head' => $mailheader,
'body' => \$body,
'attr' => $attributes,
};
$smtpmailer = $relayclass->new( %$methodargv );
$smtpmailer->sendmail();
} elsif( $relayingto->{'mailer'} =~ m|\A/| or $relayingto->{'mailer'} eq 'File' ) {
# Haineko::SMTPD::Relay::File mailer
require Haineko::SMTPD::Relay::File;
my $mailfolder = $relayingto->{'mailer'} eq 'File' ? '/tmp' : $relayingto->{'mailer'};
my $methodargv = {
'ehlo' => $serverconf->{'hostname'},
'host' => $mailfolder,
'mail' => $submission->addresser->address,
'rcpt' => $r->address,
'head' => $mailheader,
'body' => \$body,
'attr' => $attributes,
};
$smtpmailer = Haineko::SMTPD::Relay::File->new( %$methodargv );
$smtpmailer->sendmail();
} else {
$mailheader->{'To'} = $r->address;
my $methodargv = {
'ehlo' => $serverconf->{'hostname'},
'mail' => $submission->addresser->address,
'rcpt' => $r->address,
'head' => $mailheader,
'body' => \$body,
'attr' => $attributes,
'retry' => $relayingto->{'retry'} // 0,
'timeout' => $relayingto->{'timeout'} // 60,
};
if( length $relayingto->{'mailer'} ) {
# Use Haineko::SMTPD::Relay::* except H::S::R::ESMTP,
# H::S::R::Haineko and H::S::R::Discard.
try {
$relayclass = sprintf( "Haineko::SMTPD::Relay::%s", $relayingto->{'mailer'} );
Module::Load::load( $relayclass );
$smtpmailer = $relayclass->new( %$methodargv );
if( $relayingto->{'auth'} ) {
# Load credentials for SMTP-AUTH
$smtpmailer->auth( 1 );
$smtpmailer->username( $credential->{'username'} );
$smtpmailer->password( $credential->{'password'} );
}
$smtpmailer->sendmail();
if( not $smtpmailer->response->dsn ) {
# D.S.N. is empty or undefined.
if( $smtpmailer->response->error ) {
# Error but no D.S.N.
$smtpmailer->response->dsn( '5.0.0' );
} else {
# Successfully sent but no D.S.N.
$smtpmailer->response->dsn( '2.0.0' );
}
}
} catch {
require Haineko::E;
my $v = [ split( "\n", $_ ) ]->[0];
my $E = Haineko::E->new( $v );
my $R = {
'code' => 500,
'error' => 1,
'message' => [ $E->mesg->[0] ],
};
$smtpmailer = Haineko::SMTPD::Relay->new( %$methodargv );
$smtpmailer->response( Haineko::SMTPD::Response->new( %$R ) );
};
} else {
# The value of "mailer" is empty
$smtpmailer = Haineko::SMTPD::Relay->new( %$methodargv );
my $R = {
'code' => 500,
'error' => 1,
'message' => [ 'The value of "mailer" is empty' ],
};
$smtpmailer->response( Haineko::SMTPD::Response->new( %$R ) );
}
}
if( $maxworkers > 1 ) {
# Send the received response as a JSON from child process
# to parent process via pipe.
my $p = $preforkipc->[ $thisworker ];
$p->writer;
print( { $p } Haineko::JSON->dumpjson( $smtpmailer->response->damn ) );
close $p;
} else {
# Add the received response as a Haineko::SMTPD::Response object
# into Haineko::SMTPD::Session object.
$submission->add_response( $smtpmailer->response );
}
} # End of for(ONE_TO_ONE)
( run in 1.051 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )