Perl: send mail using office 365 - perl

I am trying to send mail using perl through server office 365
The operation succeed 8 times out of 10 (i.e. randomly fail in 20% of cases).
use Net::SMTPS;
my $mailer = Net::SMTPS->new("smtp.office365.com",
Port => "587",
doSSL => "starttls",
SSL_version => "TLSv1",
Debug => 4
);
...
$mailer returns as undef ;
Below is the log:
Net::SMTPS>>> Net::SMTPS(0.10)
Net::SMTPS>>> IO::Socket::IP(0.41)
Net::SMTPS>>> IO::Socket(1.48)
Net::SMTPS>>> IO::Handle(1.48)
Net::SMTPS>>> Exporter(5.73)
Net::SMTPS>>> Net::SMTP(3.13)
Net::SMTPS>>> Net::Cmd(3.13)
Net::SMTPS=GLOB(0x30816b0)<<< 220 DU2PR04CA0355.outlook.office365.com Microsoft ESMTP MAIL Service ready at Fri, 22 Oct 2021 09:15:28 +0000
Net::SMTPS=GLOB(0x30816b0)>>> EHLO localhost.localdomain
Net::SMTPS=GLOB(0x30816b0)<<< 250-DU2PR04CA0355.outlook.office365.com Hello [54.77.44.87]
Net::SMTPS=GLOB(0x30816b0)<<< 250-SIZE 157286400
Net::SMTPS=GLOB(0x30816b0)<<< 250-PIPELINING
Net::SMTPS=GLOB(0x30816b0)<<< 250-DSN
Net::SMTPS=GLOB(0x30816b0)<<< 250-ENHANCEDSTATUSCODES
Net::SMTPS=GLOB(0x30816b0)<<< 250-STARTTLS
Net::SMTPS=GLOB(0x30816b0)<<< 250-8BITMIME
Net::SMTPS=GLOB(0x30816b0)<<< 250-BINARYMIME
Net::SMTPS=GLOB(0x30816b0)<<< 250-CHUNKING
Net::SMTPS=GLOB(0x30816b0)<<< 250 SMTPUTF8
Net::SMTPS=GLOB(0x30816b0)>>> STARTTLS
Net::SMTPS=GLOB(0x30816b0)<<< 220 2.0.0 SMTP server ready
DEBUG: .../IO/Socket/SSL.pm:3010: new ctx 51201296
DEBUG: .../IO/Socket/SSL.pm:1620: start handshake
DEBUG: .../IO/Socket/SSL.pm:787: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:832: not using SNI because hostname is unknown
DEBUG: .../IO/Socket/SSL.pm:864: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:880: set socket to non-blocking to enforce timeout=120
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:917: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:937: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> 0
DEBUG: .../IO/Socket/SSL.pm:945: connection failed - connect returned 0
DEBUG: .../IO/Socket/SSL.pm:946: local error: SSL connect attempt failed because of handshake problems
DEBUG: .../IO/Socket/SSL.pm:2043: downgrading SSL only, not closing socket
DEBUG: .../IO/Socket/SSL.pm:3059: free ctx 51201296 open=51201296
DEBUG: .../IO/Socket/SSL.pm:3063: free ctx 51201296 callback
DEBUG: .../IO/Socket/SSL.pm:3070: OK free ctx 51201296
Thanks for any help

my $mailer = Net::SMTPS->new("smtp.office365.com",
...
SSL_version => "TLSv1",
For some unknown reason you are trying to enforce TLS 1.0 with SSL_version => 'TLSv1'. But some of the servers behind smtp.office365.com only support TLS 1.1 and later:
$ dig smtp.office365.com
...
SXF-efz.ms-acdc.office.com. 36 IN A 52.98.199.194
SXF-efz.ms-acdc.office.com. 36 IN A 40.101.61.130
SXF-efz.ms-acdc.office.com. 36 IN A 52.98.208.114
From these the first two support TLS 1.0, the last only TLS 1.1 and later, which means depending on which server is actually chosen the TLS handshake will succeed or fail. Note that from your perspective or at a different time you might see other IP addresses which exhibit a different behavior.
The solution is simple: stop explicitly restricting the SSL_version. In this case it will offer the best version the linked version of OpenSSL offers which since many years should be better than TLS 1.0.
Apart from that, the CORE module Net::SMTP has builtin support for TLS for several years, so there is probably no need to use Net::SMTPS (which inside uses Net::SMTP anyway).

Related

Mojo::UserAgent fails to verify certificate, where LWP::UserAgent succeeds

I have a simple perl script that uses LWP::UserAgent to connect to a secure site. It works fine. When I use Mojo::UserAgent, it fails to validate the certificate. This is reliable and repeatable. The basic Perl code is:
use strict;
use warnings;
use IO::Socket::SSL 1.980;
use LWP::UserAgent;
use Mojo::UserAgent;
$IO::Socket::SSL::DEBUG=3;
my $dst = "<DOMAIN>";
my $url = "<URL-AT-DOMAIN>";
my $A_OR_B = 1;
my $ua;
if ($A_OR_B) {
$ua = Mojo::UserAgent->new();
$ua->connect_timeout(20);
} else {
$ua = LWP::UserAgent->new();
}
my $resp = $ua->get($url);
if ($A_OR_B) {
print $resp->result->message;
print $resp;
} else {
print $resp->status_line."\n";
}
The output from the IO::Socket debugging is:
For the Mojo (failure):
DEBUG: .../IO/Socket/SSL.pm:3010: new ctx 48892560
DEBUG: .../IO/Socket/SSL.pm:1638: don't start handshake: IO::Socket::SSL=GLOB(0x2e957d8)
DEBUG: .../IO/Socket/SSL.pm:787: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:829: using SNI with hostname <DOMAIN>
DEBUG: .../IO/Socket/SSL.pm:864: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2911: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2864: ok=0 [3] /O=Digital Signature Trust Co./CN=DST Root CA X3/O=Digital Signature Trust Co./CN=DST Root CA X3
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:900: SSL connect attempt failed
DEBUG: .../IO/Socket/SSL.pm:900: local error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:903: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:3059: free ctx 48892560 open=
DEBUG: .../IO/Socket/SSL.pm:3063: free ctx 48892560 callback
DEBUG: .../IO/Socket/SSL.pm:3070: OK free ctx 48892560
SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
at /home/briefly/bad.pl line 26.
and the output for the LWP version (success), is:
DEBUG: .../IO/Socket/SSL.pm:3010: new ctx 41136976
DEBUG: .../IO/Socket/SSL.pm:762: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:764: socket connected
DEBUG: .../IO/Socket/SSL.pm:787: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:829: using SNI with hostname <DOMAIN>
DEBUG: .../IO/Socket/SSL.pm:864: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:880: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:917: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:937: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2911: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:917: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:937: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [2] /C=US/O=Internet Security Research Group/CN=ISRG Root X1/C=US/O=Internet Security Research Group/CN=ISRG Root X1
DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [1] /C=US/O=Internet Security Research Group/CN=ISRG Root X1/C=US/O=Let's Encrypt/CN=R3
DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [0] /C=US/O=Let's Encrypt/CN=R3/CN=tls.automattic.com
DEBUG: .../IO/Socket/SSL.pm:1840: scheme=www cert=41975232
DEBUG: .../IO/Socket/SSL.pm:1850: identity=< **VERY LONG LIST OF DOMAINS** >
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:917: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:937: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> 1
DEBUG: .../IO/Socket/SSL.pm:952: ssl handshake done
DEBUG: .../IO/Socket/SSL.pm:3059: free ctx 41136976 open=
DEBUG: .../IO/Socket/SSL.pm:3063: free ctx 41136976 callback
DEBUG: .../IO/Socket/SSL.pm:3070: OK free ctx 41136976
200 OK
Does anyone have any insights?
I would suggest that LWP:UserAgent and Mojo::UserAgent use different trust stores. LWP::UserAgent will default to using Mozilla::CA while Mojo::UserAgent not. Try to enforce the use of Mozilla::CA with Mojo::UserAgent with
$ua->ca(Mozilla::CA::SSL_ca_file());

IO::Socket::SSL: SSL connect attempt failed

I do request to https://bank.gov.ua
my $ua = Mojo::UserAgent->new;
$ua->get("https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?valcode=EUR&date=$date_now&json");
And get error:
DEBUG: .../IO/Socket/SSL.pm:3010: new ctx 146452496
DEBUG: .../IO/Socket/SSL.pm:1638: don't start handshake: IO::Socket::SSL=GLOB(0xc955978)
DEBUG: .../IO/Socket/SSL.pm:787: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:829: using SNI with hostname bank.gov.ua
DEBUG: .../IO/Socket/SSL.pm:864: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:900: local error: SSL connect attempt failed
DEBUG: .../IO/Socket/SSL.pm:903: fatal SSL error: SSL connect attempt failed
DEBUG: .../IO/Socket/SSL.pm:3059: free ctx 146452496 open=
DEBUG: .../IO/Socket/SSL.pm:3063: free ctx 146452496 callback
DEBUG: .../IO/Socket/SSL.pm:3070: OK free ctx 146452496
I can do request with curl from this host to give url with no problem.
Does any know what problem is when I do this via IO::Socket::SSL (Mojo::UserAgent)?
This server is pretty strange:
the first request with openssl s_client -connect bank.gov.ua:443 fails with the server simply closing the connection: "SSL handshake has read 0 bytes and written 303 bytes"
the Mojo::UserAgent code fails too
doing a request with an explicit TLS 1.2 succeeds: openssl s_client -connect bank.gov.ua:443 -tls1_2
trying the first request again suddenly succeeds too
an the Mojo::UserAgent code now succeeds too
My only explanation is some firewall or load balancer which temporarily white lists an IP address in case it has seen a valid TLS ClientHello - and which considers TLS 1.3 not a valid one.

Cannot complete SSL handshake with gateway.push.apple.com using perl IO::Socket::SSL

I am very new to this type of thing and not sure what I am doing wrong.
Inside Mojolicious app, I am battling to connect to the Apple Push Notification SSL Socket. I would like to send a push notification to an app.
Debug Information:
DEBUG: .../IO/Socket/SSL.pm:2700: new ctx 138351632
DEBUG: .../IO/Socket/SSL.pm:612: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:614: socket connected
DEBUG: .../IO/Socket/SSL.pm:636: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:669: using SNI with hostname gateway.push.apple.com
DEBUG: .../IO/Socket/SSL.pm:704: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:736: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2601: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:2554: ok=0 [1] /O=Entrust.net/OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Certification Authority (2048)/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
DEBUG: .../IO/Socket/SSL.pm:739: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:742: SSL connect attempt failed
DEBUG: .../IO/Socket/SSL.pm:742: local error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:745: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: ...5.18/IO/Socket.pm:48: ignoring less severe local error 'IO::Socket::IP configuration failed', keep 'SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed'
DEBUG: .../IO/Socket/SSL.pm:2733: free ctx 138351632 open=138351632
DEBUG: .../IO/Socket/SSL.pm:2738: free ctx 138351632 callback
DEBUG: .../IO/Socket/SSL.pm:2745: OK free ctx 138351632
Code snip bit:
use IO::Socket::SSL qw(debug3);
my $cl = IO::Socket::SSL->new(
PeerHost => 'gateway.push.apple.com',
# PeerHost => 'gateway.sandbox.push.apple.com',
PeerPort => '2195',
SSL_verify_mode => SSL_VERIFY_PEER,
SSL_ca_file => '/var/www/foo/bar/cert/ck.pem',
);
I'm not sure where to go or what to do from here?
I figured it out: I was using the incorrect pass phrase! I was able to implement the much simpler perl module Net::APNS
use Net::APNS;
my %settings = (
cert => "$Cert_file",
key => "$Cert_key_file",
passwd => "$passphrase",
);
if(my $Notifier = Net::APNS->new->notify(\%settings)) {
$Notifier->write({
devicetoken => "$device_token",
message => "$message",
sound => 'default',
badge => 1
});
return 1 if defined($Notifier) and ref($Notifier) eq "Net::APNS::Notification";
}
Thank you for all your input!

Error "sslv3 alert handshake failure" using Net::SMTP::TLS

I'm trying to send email with Perl. My code works fine with Yahoo's SMTP server but when I try to use another SMTP server (with a self-signed SSL certificate), I get this error:
Couldn't start TLS: SSL connect attempt failed because of handshake problems error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
at mail2.pl line 2.
My code is:
use Net::SMTP::TLS;
my $mailer = new Net::SMTP::TLS(
'mail.SomeHost.com',
Hello => 'mail.SomeHost.com',
Port => 587,
User => 'info#SomeHost.com',
Password=> '123456789'
);
$mailer->mail('info#SomeHost.com');
$mailer->to('info#SomeHost.com');
$mailer->data();
$mailer->datasend("From: info#SomeHost.com\n");
$mailer->datasend("To: info#SomeHost.com\n");
$mailer->datasend("Subject: test\n");
$mailer->datasend("Content-type: text/html\n\n");
$mailer->datasend("\n");
$mailer->datasend("<html><body><p>hi text</p><br></body></html>\n");
$mailer->dataend();
$mailer->quit;
How can I fix this?
Result with -MIO::Socket::SSL=debug4:
DEBUG: .../IO/Socket/SSL.pm:2537: new ctx 17003088
DEBUG: .../IO/Socket/SSL.pm:1343: start handshake
DEBUG: .../IO/Socket/SSL.pm:553: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:589: not using SNI because hostname is unknown
DEBUG: .../IO/Socket/SSL.pm:621: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:640: set socket to non-blocking to enforce timeout=5
DEBUG: .../IO/Socket/SSL.pm:653: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:663: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:673: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:693: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:653: Net::SSLeay::connect -> 0
DEBUG: .../IO/Socket/SSL.pm:701: connection failed - connect returned 0
DEBUG: .../IO/Socket/SSL.pm:1769: SSL connect attempt failed because of handshake problems
DEBUG: .../IO/Socket/SSL.pm:1774: SSL connect attempt failed because of handshake problems
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
DEBUG: .../IO/Socket/SSL.pm:2570: free ctx 17003088 open=17003088
DEBUG: .../IO/Socket/SSL.pm:2575: free ctx 17003088 callback
DEBUG: .../IO/Socket/SSL.pm:2582: OK free ctx 17003088 Couldn't start TLS:
SSL connect attempt failed because of handshake problems
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake
failure at mail2.pl line 2.

Emacs (24.4.2) Gnus (0.12) TLS connection not working

Recently, I've been experiencing problems with my email setup using Emacs (24.4.2) + Gnus (0.12). It seems that the TSL connection is not working:
gnutls.c: [0] (Emacs) fatal error: The TLS connection was non-properly terminated.
gnutls.el: (err=[-110] The TLS connection was non-properly terminated.) boot: (:priority NORMAL :hostname smtp.me.com :loglevel 0 :min-prime-bits 256 :trustfiles nil :crlfiles nil :keylist nil :verify-flags nil :verify-error nil :callbacks nil)
smtpmail-send-it: Sending failed: 530 5.7.0 No STARTTLS command has been given.
Is it a Gnus or Openssl problem? How should I debug and fix it?
Here is the output of the smtp trace buffer:
220 nk11p00mm-asmtp003.example.com -- Server ESMTP (Oracle Communications Messaging Server 7u4-27.10(7.0.4.27.9) 64bit (built Jun 6 2014))
250-nk11p00mm-asmtp003.example.com
250-8BITMIME
250-PIPELINING
250-CHUNKING
250-DSN
250-ENHANCEDSTATUSCODES
250-EXPN
250-HELP
250-XADR
250-XSTA
250-XCIR
250-XGEN
250-XLOOP 098E7F59418D8F04E0C7135651497A4E
250-STARTTLS
250-NO-SOLICITING
250 SIZE 28311552
220 2.5.0 Go ahead with TLS negotiation.
Process smtpmail deleted
220 nk11p00mm-asmtp003.example.com -- Server ESMTP (Oracle Communications Messaging Server 7u4-27.10(7.0.4.27.9) 64bit (built Jun 6 2014))
MAIL FROM:<john.doe#example.com>
250-nk11p00mm-asmtp003.example.com
250-8BITMIME
250-PIPELINING
250-CHUNKING
250-DSN
250-ENHANCEDSTATUSCODES
250-EXPN
250-HELP
250-XADR
250-XSTA
250-XCIR
250-XGEN
250-XLOOP 098E7F59418D8F04E0C7135651497A4E
250-STARTTLS
250-NO-SOLICITING
250 SIZE 28311552
RCPT TO:<john.doe#example.com>
530 5.7.0 No STARTTLS command has been given.
QUIT
503 5.5.0 No MAIL FROM command has been issued.