Haineko
view release on metacpan or search on metacpan
lib/Haineko/SMTPD/Relay/AmazonSES.pm view on Meta::CPAN
for my $e ( @{ $self->{'head'}->{'Received'} } ) {
# Convert email headers
push @$headerlist, 'Received' => $e;
}
for my $e ( keys %{ $self->{'head'} } ) {
# Make email headers except ``MIME-Version''
next if $e eq 'MIME-Version';
if( ref $self->{'head'}->{ $e } eq 'ARRAY' ) {
# Such as Received: header
for my $f ( @{ $self->{'head'}->{ $e } } ) {
push @$headerlist, $e => $f;
}
} else {
push @$headerlist, $e => $self->{'head'}->{ $e };
}
}
$methodargv->{'header'} = $headerlist;
my $mimeobject = Email::MIME->create( %$methodargv );
my $mailstring = MIME::Base64::encode_base64 $mimeobject->as_string;
# http://docs.aws.amazon.com/ses/latest/DeveloperGuide/query-interface.html
my $amazonses1 = sprintf( "https://%s/", SES_ENDPOINT );
my $dateheader = gmtime;
my $datestring = $dateheader->strftime;
my $parameters = {
'Action' => 'SendRawEmail',
'Source' => $self->{'mail'},
'RawMessage.Data' => $mailstring,
'Destinations.member.1' => $self->{'rcpt'},
'Timestamp' => $dateheader->datetime.'.000Z',
'Version' => SES_APIVERSION,
};
# AWS3 AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE,Signature=lBP67vCvGlDMBQ=dofZxg8E8SUEXAMPLE,Algorithm=HmacSHA256,SignedHeaders=Date;Host
my $headerkeys = [ 'AWSAccessKeyId', 'Signature', 'Algorithm' ];
my $reqheaders = {
'Date' => $datestring,
'Host' => SES_ENDPOINT,
};
my $identifier = {
'AWSAccessKeyId' => $self->{'username'},
'Signature' => __PACKAGE__->sign( $reqheaders->{'Date'}, $self->{'password'} ),
'Algorithm' => 'HmacSHA256',
'SignedHeaders' => 'Date',
};
my $authheader = join( ', ', map { sprintf( "%s=%s", $_, $identifier->{ $_ } ) } @$headerkeys );
$methodargv = {
'agent' => $self->{'ehlo'},
'timeout' => $self->{'timeout'},
'ssl_opts' => { 'SSL_verify_mode' => 0 },
'headers' => [
'date' => $datestring,
'host' => SES_ENDPOINT,
'content-type' => 'application/x-www-form-urlencoded',
'if-ssl-cert-subject' => sprintf( "/CN=%s", SES_ENDPOINT ),
'x-amzn-authorization' => sprintf( "AWS3-HTTPS %s", $authheader ),
],
};
my $httpclient = Furl->new( %$methodargv );
my $htresponse = undef;
my $retryuntil = $self->{'retry'} || 0;
my $smtpstatus = 0;
my $exceptions = 0;
my $sendmailto = sub {
$htresponse = $httpclient->post( $amazonses1, undef, $parameters );
return 0 unless defined $htresponse;
return 0 unless $htresponse->is_success;
$smtpstatus = 1;
return 1;
};
while(1) {
last if $sendmailto->();
last if $retryuntil == 0;
$retryuntil--;
sleep $self->{'sleep'};
}
if( defined $htresponse ) {
# Check response from API
my $htcontents = undef;
my $htmimetype = $htresponse->content_type || q();
my $nekoparams = {
'code' => $htresponse->code,
'host' => SES_ENDPOINT,
'port' => 443,
'rcpt' => $self->{'rcpt'},
'error' => $htresponse->is_success ? 0 : 1,
'mailer' => 'AmazonSES',
'message' => [ $htresponse->message ],
'command' => 'POST',
};
if( $htmimetype eq 'text/xml' ) {
# text/xml
try {
require XML::Simple;
} catch {
# XML::Simple is not installed
$nekoparams->{'error'} = 1;
$nekoparams->{'message'} = [ 'Please install XML::Simple 2.20 or later' ];
$exceptions = 1;
};
if( not $exceptions ) {
# XML::Simple is already installed
try {
# Amazon SES respond contents as a XML
$htcontents = XML::Simple::XMLin( $htresponse->content );
for my $e ( keys %{ $htcontents->{'Error'} } ) {
( run in 0.747 second using v1.01-cache-2.11-cpan-524268b4103 )