pentacent / keila

Open Source Newsletter Tool.
https://keila.io
GNU Affero General Public License v3.0
1.45k stars 81 forks source link

How to use SMTP with self-signed certificate? #287

Closed dompie closed 6 months ago

dompie commented 7 months ago

I use Keila 0.14.4 and want to send newsletters via our SMTP-Server.

:~/docker/keila$ docker exec -ti keila-keila-1 sh
~ # bin/keila version
keila 0.14.4

The error message for SSL/TLS with port 587 looks like:

:~/docker/keila$ docker logs -n100 keila-keila-1
[...]
10:12:56.007 [warning] Failed sending email to email1@dompie.de for campaign nmc_2jgZaVDG: {:retries_exceeded, {:network_failure, ~c"172.16.252.31", {:error, {:tls_alert, {:unexpected_message, ~c"TLS client: In state hello at tls_record.erl:561 generated CLIENT ALERT: Fatal - Unexpected Message\n {unsupported_record_type,50}"}}}}}
10:12:56.008 [notice] TLS :client: In state :hello at tls_record.erl:561 generated CLIENT ALERT: Fatal - Unexpected Message
 - {:unsupported_record_type, 50}
10:12:56.011 [warning] Failed sending email to email2@dompie.de for campaign nmc_2jgZaVDG: {:retries_exceeded, {:network_failure, ~c"172.16.252.31", {:error, {:tls_alert, {:unexpected_message, ~c"TLS client: In state hello at tls_record.erl:561 generated CLIENT ALERT: Fatal - Unexpected Message\n {unsupported_record_type,50}"}}}}}
10:12:56.014 [notice] TLS :client: In state :hello at tls_record.erl:561 generated CLIENT ALERT: Fatal - Unexpected Message
 - {:unsupported_record_type, 50}
[...]

With STARTTLS and port 587 I get the following error:

10:31:01.916 [warning] Failed sending email to email1@dompie.de for campaign nmc_Xar2Xg4x: {:retries_exceeded, {:temporary_failure, ~c"172.16.252.31", :tls_failed}}
10:31:01.916 [notice] TLS :client: In state :certify at ssl_handshake.erl:2123 generated CLIENT ALERT: Fatal - Bad Certificate

So I think I need to use STARTTLS. I can connect to our mail server on port 587 from the machine where the docker container is running.

:~/docker/keila$ telnet 172.16.252.31 587
Trying 172.16.252.31...
Connected to 172.16.252.31.
Escape character is '^]'.
220 mail.frivol.com ESMTP
quit
221 2.0.0 Bye
Connection closed by foreign host.

When I double check with openssl, I see the following output

:~/docker/keila$ openssl s_client -connect 172.16.252.31:587 -starttls smtp
CONNECTED(00000003)
Can't use SSL_get_servername
[...redacted...]
verify error:num=18:self-signed certificate
verify return:1
[...redacted...]
verify return:1
    [...redacted...]
    Protocol  : TLSv1.3
    [...redacted...]
    Start Time: 1714130702
    Timeout   : 7200 (sec)
    Verify return code: 18 (self-signed certificate)
    Extended master secret: no
    Max Early Data: 0
---

Is there a way to skip certificate check before sending - or to have it use my sender anyway? Or any other options?

dompie commented 7 months ago

Is it possible to put our self-signed cert somwhere, so that elixir/keila recognizes it as trusted certificate?

wmnnd commented 7 months ago

Erlang/OTP should be using the operating system CA store these days. You could try adding it like this:

COPY my-cert.pem /usr/local/share/ca-certificates/my-cert.crt

RUN cat /usr/local/share/ca-certificates/my-cert.crt >> /etc/ssl/certs/ca-certificates.crt

via https://stackoverflow.com/a/67232164 (I haven’t personally tried it)

dompie commented 6 months ago

We have added our certificate to the OS certs location. Openssl now verifies without an error, but unfortunately keila logs keep telling me

08:25:45.034 [notice] TLS :client: In state :certify at ssl_handshake.erl:2123 generated CLIENT ALERT: Fatal - Bad Certificate

08:25:45.035 [warning] Failed sending email to test7@example.com for campaign nmc_neLWkLwd: {:retries_exceeded, {:temporary_failure, ~c"172.16.252.31", :tls_failed}}

Any other ideas how to skip verification or teach keila about our certificates?

wmnnd commented 6 months ago

Since you’re using an internal IP address, you might also get around the issue by disabling SSL altogether for now.

Debugging this would be kinda hard for me since I can't test it directly. If you have a similar SMTP server with a public IP available with a self-signed certificate, I could take a closer look.

dompie commented 6 months ago

We ended up with an additional Docker container working as SMTP relay and configuring Keila to use "no connection security". So we now have the following authentication/communication order:

Keila -> SMTP relay -> Self-Signed Certificate SMTP Server

It would have been easier if Keila allowed the use of SMTP without username and password.

An option to skip certificate verification in Keila would definitely have saved several hours of work.