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

SecureSocket.connect throws HandshakeException: WRONG_VERSION_NUMBER #52886

Open
rubenferreira97 opened this issue Jul 8, 2023 · 10 comments
Open
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io

Comments

@rubenferreira97
Copy link

rubenferreira97 commented Jul 8, 2023

I am using Dart on the server and trying to send an email by connecting and authenticating to a SMTP server using TLS (let's say mail.myserver.com on port 587) with the package mailer. After setting everything up correctly (as far as I know), a HandshakeException is thrown here.

After some debugging and attempting to isolate the problem, I wrote the following script that simply connects to a secure host:

import 'dart:io';

void main() async {
  try {
    // Executes successfully and prints 'Connected!':
    // await SecureSocket.connect('mail.myserver.com', 465, timeout: Duration(seconds: 3));
    // await SecureSocket.connect('smtp.gmail.com', 465, timeout: Duration(seconds: 3));
    // await SecureSocket.connect('google.com', 443, timeout: Duration(seconds: 3));
    
    // Fails with a `HandshakeException`
    await SecureSocket.connect('smtp.gmail.com', 587, timeout: Duration(seconds: 3));
    // await SecureSocket.connect('mail.myserver.com', 587, timeout: Duration(seconds: 3));
    print('Connected!');
  } catch (e) {
    print('$e');
  }
}

The following error is thrown:

HandshakeException: Handshake error in client (OS Error: 
	WRONG_VERSION_NUMBER(../../third_party/boringssl/src/ssl/tls_record.cc:242))

Changing the port from 587 to 465 prints Connected!.


For testing purposes, I tried the following commands on the same machine where I executed the previous Dart script:

Using the telnet smtp.gmail.com 587 command in cmd (Windows) successfully connects and outputs:

220 smtp.gmail.com ESMTP t25-20020a1c7719000000b003fbfef555d2sm4374952wmi.23 - gsmtp

Using the telnet smtp.gmail.com 465 and telnet google.com 443 commands also connect successfully.

Is this a bug or am I missing something?

@rubenferreira97 rubenferreira97 changed the title SecureSocket throws HandshakeException: WRONG_VERSION_NUMBER SecureSocket.connect throws HandshakeException: WRONG_VERSION_NUMBER Jul 8, 2023
@lrhn lrhn added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io labels Jul 8, 2023
@busslina
Copy link

busslina commented Jun 15, 2024

Same error here using mailer.

@rubenferreira97 as you closed the issue as completed, can you share the solution you found?

I was thinking that maybe Dart doesn't support the latest TLS protocols. Or maybe Dart delegates it to the OS... but still is weird because I'm testing it on a fresh latest Raspberry OS (Debian 12).

UPDATE I:

It is really strange. I tested with https://www.checktls.com/TestReceiver and my SMTP server seems to work fine:
imagen

The error that I get on the SMTP server (Postfix) when executin Dart's mailer is:

postfix/smtpd[12656]: connect from [...]
postfix/smtpd[12656]: improper command pipelining after CONNECT from [...]
postfix/smtpd[12656]: lost connection after CONNECT from [...]
postfix/smtpd[12656]: disconnect from [...]

UPDATE II:

This simple Dart code fails with the same output so I'm pretty sure that Dart is not supporting latest version of TLS, as a simple openssl command works...

import 'dart:io';

void main(List<String> arguments) async {
  final socket = await SecureSocket.connect('example.com', 587);
  await Future.delayed(const Duration(seconds: 10));
  await socket.close();
}
openssl s_client -starttls smtp -connect example.com:587

UPDATE III:

Executing plain openssl without -starttls smtp gives me the same error so this changes my mind:

openssl s_client -connect example.com:587

@rubenferreira97
Copy link
Author

Hey @busslina I will be honest, I forgot how I solved the problem. I am almost sure that it was a problem on my end. I am looking at the old code and this is working for me:

import 'package:mailer/mailer.dart';
import 'package:mailer/smtp_server.dart';

void main() async {
  final address = Address('youremail@email.com', 'YourEmailName');

  final smtpServer = SmtpServer(
    'yourhost',
    port: 587,
    name: address.name,
    username: address.mailAddress,
    password: 'yourpassword',
  );

  final message = Message()
    ..from = address
    ..recipients.addAll(['to@tempmail.com'])
    ..subject = 'Test'
    ..text = 'Test'
    ..html = 'Test';

  await send(message, smtpServer);
}

What's your dart version? I don't know if it's the case but sometimes exceptions are reported by the IDE but they are handled internally (if you use VSCode check if All Exceptions is off).

@busslina
Copy link

busslina commented Jun 15, 2024

@rubenferreira97 thanks.

I updated my previous message.

What's your dart version?

3.3.3 (not latest but close)

VSCode.

I'm not executing it with VSCode.

As I posted in my previous message: It's really strange that a simple openssl command opens TLS connection without error and analogous code in Dart gives exactly the same error that Dart's mailer code.

If you solved it, maybe you changed your SMTP server configuration to allow lower TLS versions.

@busslina
Copy link

busslina commented Jun 15, 2024

@rubenferreira97

In your code seems that your solution was to disable TLS, as it's disabled by default on mailer.

imagen

So this could be a mailer issue. Gonna report it.

@rubenferreira97
Copy link
Author

rubenferreira97 commented Jun 15, 2024

@busslina I reopened the issue for further investigation. It seems the default options are all good (allowInsecure is false so it shouldn't allow insecure connections. ignoreBadCertificate is also false). As far as I recall TLS is an improved version of SSL so they are different.

@busslina
Copy link

busslina commented Jun 15, 2024

@rubenferreira97 Thanks

You can see here that what matters to select between SecureSocket and Socket is the ssl parameter... so you are sending emails over an insecure connection.

@rubenferreira97
Copy link
Author

You are right! I was debugging and isSecure returns false.

image

@close2
Copy link

close2 commented Jun 17, 2024

TL;DR: Don't use ssl. mailer will automatically upgrade the connection to an encrypted connection using the smtp command starttls. If the server does not support tls mailer will either continue over an insecure connection if the option allowInsecure is given (off by default) or fail otherwise.

There are 2 ways to send mails over secure connections:

  • Connect over a secure ssl connection. (This is the ssl option in mailer).
  • First connect over an unencrypted connection and upgrade the connection to a secure connection using the starttls smtp command. The mailer library will automatically use starttls if the server supports it. (The server will respond with its capabilities after the initial greeting.)

In your screenshot we are waiting for the response to get list of capabilities. That's also the reason for the 2 different exceptions. If we don't get a response at all, it is possible, that we should have used an ssl connection and the server is waiting for commands to initiate a secure ssl connection.

The openssl command shows that we should use starttls. If the -starttls smtp option is given, openssl will connect over an unencrypted connection and then send the starttls command, upgrading the connection to an encrypted connection.

@rubenferreira97
Copy link
Author

@busslina ☝️ Now that I remember, this was the conclusion that I got. At the time, I inspected/debugged more careful and checked the logs of my SMTP server. It was indeed upgraded to a secure connection.

@busslina
Copy link

Thanks both :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io
Projects
None yet
Development

No branches or pull requests

4 participants