Openfire meeting - Jitsi Conference Failed Connection Error - xmpp

We are trying to deploy our Jitsi Meet instance. We've installed Openfire Meeting Plugin. I can see that the plugin was installed successfully. When I access the Jitsi URL /ofmeet/DemoMeeting1 it prompts me for username and password. After entering both it logs me in. However, I get the following error:
Here are the browser logs, I see in chrome.
Jitsi2:9 (TIME) index.html loaded: 467.68999999039806
Logger.js:125 [modules/browser/BrowserCapabilities.js] <new t>: This appears to be chrome, ver: 81.0
LocalStatsCollector.js:22 The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. goo.gl/7K7WLu
(anonymous) # strophe.js:53
Logger.js:125 [react/index.web.js] <HTMLDocument.<anonymous>>: (TIME) document ready: 1986.1649999947986
Logger.js:125 [react/features/base/storage/PersistenceRegistry.js] <e.value>: redux state rehydrated as Object
Logger.js:125 [modules/UI/videolayout/VideoLayout.js] <Object.changeUserAvatar>: Missed avatar update - no small video yet for undefined
o # index.js:1
Logger.js:125 [JitsiMeetJS.js] <Object.init>: Analytics disabled, disposing.
i # strophe.js:53
Logger.js:125 [modules/statistics/AnalyticsAdapter.js] <e.value>: Disposing of analytics adapter.
i # strophe.js:53
Logger.js:125 [modules/RTC/ScreenObtainer.js] <Object.init>: Desktop sharing disabled
Logger.js:125 [react/features/base/media/middleware.js] <>: Start muted:
Logger.js:125 [react/features/base/media/middleware.js] <>: Start audio only set to false
Logger.js:125 [react/features/base/conference/middleware.js] <>: Audio-only disabled
Logger.js:125 [modules/RTC/RTCUtils.js] <t.value>: Using the new gUM flow
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: P2P STUN servers: Array(3)
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: (TIME) Strophe connecting: 2436.8649999960326
Logger.js:125 [modules/RTC/RTCUtils.js] <t.<anonymous>>: Got media constraints: Object
Logger.js:125 [modules/RTC/RTCUtils.js] <>: onUserMediaSuccess
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: (TIME) Strophe connfail[x-strophe-bad-non-anon-jid]: 4145.414999991772
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: (TIME) Strophe disconnecting[x-strophe-bad-non-anon-jid]: 4146.200000002864
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: (TIME) Strophe disconnected: 4147.40499999607
Logger.js:125 [modules/statistics/statistics.js] <Function._.sendAnalyticsAndLog>: {"type":"operational","action":"connection.failed","attributes":{"error_type":"connection.passwordRequired"}}
Logger.js:125 [connection.js] <r.c>: CONNECTION FAILED: connection.passwordRequired
o # index.js:1
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: P2P STUN servers: Array(3)
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: (TIME) Strophe connecting: 10563.394999990123
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: (TIME) Strophe connected: 13849.285000003874
Logger.js:125 [modules/xmpp/xmpp.js] <t.value>: My Jabber ID: justin.credible#server01.com/1hh1yloy01
Logger.js:125 [conference.js] <>: initialized with 2 local tracks
Logger.js:125 [modules/xmpp/ChatRoom.js] <new t>: Joined MUC as jitsi2#conference.server01.com/justin-credible-d39f32
Logger.js:125 [modules/e2eping/e2eping.js] <new e>: Initializing e2e ping; pingInterval=10000, analyticsInterval=60000.
Logger.js:125 [modules/connectivity/ParticipantConnectionStatus.js] <new e>: RtcMuteTimeout set to: 2000
Logger.js:125 [modules/statistics/AvgRTPStatsReporter.js] <new e>: Avg RTP stats will be calculated every 15 samples
Logger.js:125 [JitsiConference.js] <new z>: backToP2PDelay: 5
Logger.js:125 [modules/UI/videolayout/VideoLayout.js] <Object.electLastVisibleVideo>: Last visible video no longer exists
Logger.js:125 [modules/UI/videolayout/VideoLayout.js] <Object.electLastVisibleVideo>: Fallback to local video...
Logger.js:125 [modules/UI/videolayout/VideoLayout.js] <Object.electLastVisibleVideo>: electLastVisibleVideo: undefined
Logger.js:125 [JitsiConference.js] <z._doReplaceTrack>: _doReplaceTrack - no JVB JingleSession
Logger.js:125 [JitsiConference.js] <z._doReplaceTrack>: _doReplaceTrack - no P2P JingleSession
Logger.js:125 [JitsiConference.js] <z._doReplaceTrack>: _doReplaceTrack - no JVB JingleSession
Logger.js:125 [JitsiConference.js] <z._doReplaceTrack>: _doReplaceTrack - no P2P JingleSession
Logger.js:125 [modules/xmpp/moderator.js] <d.setFocusUserJid>: Focus jid set to: focus#server01.com
Logger.js:125 [modules/xmpp/moderator.js] <d.createConferenceIq>: Session ID: null machine UID: b18ecd98d476e7e7c66dc547a12692b1
Logger.js:125 [modules/UI/videolayout/LargeVideoManager.js] <>: hover in %s undefined
Logger.js:125 [react/features/base/tracks/actions.js] <>: Replace audio track - unmuted
Logger.js:125 [react/features/base/tracks/actions.js] <>: Replace video track - unmuted
Logger.js:125 [modules/xmpp/strophe.ping.js] <s.value>: XMPP pings will be sent every 10000 ms
Logger.js:125 [modules/xmpp/moderator.js] <d.parseConfigOptions>: Authentication enabled: false
Logger.js:125 [modules/xmpp/moderator.js] <d.parseConfigOptions>: External authentication enabled: false
Logger.js:125 [modules/xmpp/moderator.js] <d.parseConfigOptions>: Sip gateway enabled: false
Logger.js:125 [modules/xmpp/ChatRoom.js] <t.value>: onPresError <presence xmlns=​"jabber:​client" to=​"justin.credible#server01.com/​1hh1yloy01" from=​"jitsi2#conference.server01.com/justin.credible-d39f32" type=​"error">​…​</presence>​<x xmlns=​"http:​/​/​jabber.org/​protocol/​muc">​</x>​<c xmlns=​"http:​/​/​jabber.org/​protocol/​caps" hash=​"sha-1" node=​"http:​/​/​igniterealtime.org/​ofmeet/​jitsi-meet/​" ver=​"12a0JlElgsvtkqcjvfNtayNtIdw=">​</c>​<avatar-id>​36105051c62f5a740aa3f9b498b355e1​</avatar-id>​<nick xmlns=​"http:​/​/​jabber.org/​protocol/​nick">​Change ​</nick>​<audiomuted xmlns=​"http:​/​/​jitsi.org/​jitmeet/​audio">​false​</audiomuted>​<videoType xmlns=​"http:​/​/​jitsi.org/​jitmeet/​video">​camera​</videoType>​<videomuted xmlns=​"http:​/​/​jitsi.org/​jitmeet/​video">​false​</videomuted>​<error code=​"407" type=​"auth">​…​</error>​</presence>​
i # strophe.js:53
Logger.js:125 [modules/UI/videolayout/VideoLayout.js] <Object.electLastVisibleVideo>: Last visible video no longer exists
Logger.js:125 [modules/UI/videolayout/VideoLayout.js] <Object.electLastVisibleVideo>: Fallback to local video...
Logger.js:125 [modules/UI/videolayout/VideoLayout.js] <Object.electLastVisibleVideo>: electLastVisibleVideo: justin.credible-d39f32
Logger.js:125 [conference.js] <e.value>: CONFERENCE FAILED: conference.connectionError
o # index.js:1
Logger.js:125 [modules/UI/videolayout/LargeVideoManager.js] <>: hover in %s justin.credible-d39f32
On the Openfire server I can see that Group Chat is created but room occupants only contain focus user.
Can anyone please analyze what could be the problem here? Thanks.

Related

Haproxy agent-check DRAIN(agent) status still accepts new connections

I am trying to perform a load balancing for my Node.js application which uses websockets. I need haproxy to stop load balance new connections on a server, which has reached its maximum number of connections, keeping the existing ones intact in the same time.
I do this by performing an agent-check for each of my servers. If a server cannot accept new connections it responds with "drain" to an agent-check. If a server is able to respond to a new connection, it responds with "ready" to an agent-check.
Here is my haproxy.cfg configuration file:
global
daemon
maxconn 240000
log /dev/log local0 debug
log /dev/log local1 notice
tune.ssl.default-dh-param 2048
defaults
mode http
log global
option httplog
option dontlognull
option dontlog-normal
option http-server-close
option redispatch
timeout connect 20000ms
timeout http-request 1m
timeout client 2100000ms
timeout server 2100000ms
timeout queue 30s
timeout check 5s
timeout http-keep-alive 180s
timeout tunnel 3600s
timeout tarpit 60s
frontend stats
bind *:8084
stats enable
stats uri /stats
stats refresh 10s
stats admin if TRUE
frontend test
mode http
bind *:5000
default_backend ws
backend ws
mode http
fullconn 100000
balance roundrobin
cookie SERVERID insert indirect nocache
server 1 backend1:9999 check agent-check agent-port 8080 cookie 1 inter 500 fall 1 rise 2
And here is how I respond to haproxy agent-check in my Node.js app:
const healthCheckServer = net.createServer((c) => {
let data = '';
if (currentConn < MAX_CONN) {
data += 'ready';
} else {
data += 'drain';
}
c.write(data + '\r\n');
c.destroy();
});
healthCheckServer.listen(8080, '0.0.0.0');
When number of connections to my application is reaching its maximum, haproxy correctly changes server status to DRAIN (agent) (I can observe this in haproxy web dashboard). The problem is, that new connections are still accepted by the application.
I am new to haproxy, so can someone point me to where I am wrong?
Found out that when server is drained by agent (status is set to DRAIN (agent)) and if server is the only one existing in the backend it will still accept new connections.
When there are multiple servers present and each server is drained the behavior is just like expected: haproxy returns HTTP 503.
UPDATE:
Turned out that I was looking in the wrong direction all the time.
First I had to mark my backend which processes WebSocket connections as a non-http (remove mode http line). My guess is haproxy incorrectly counts current sessions for http backend when using WebSockets. Removing mode http solved my problem.
Second, returning maxconn:<conn> in agent-check looks like much simple and more idiomatic way to limit the number of concurrent connections.
Sources:
https://cbonte.github.io/haproxy-dconv/1.8/configuration.html#5.2-agent-check
https://www.haproxy.com/blog/websockets-load-balancing-with-haproxy/
I hope this will help someone.

SleekXMPP (Slixmpp) Server Component not receiving all MUC messages from ejabberd

we want to build a simple server component for ejabberd which receives all messages sent to MUC rooms (we have many rooms and new ones are being created all the time) and, after processing some of these messages, performs some operations.
We don't want our server component to act like a bot, so we don't want it to reply to messages or things like that, we just want it to receive copies of all messages in order to process some of them.
To do so, we have followed the tutorial available here: https://sleekxmpp.readthedocs.io/en/latest/getting_started/component.html
The problem is that the component seems to receive only some of the messages (approximately 1 out of 5).
Also, we are observing a weird behavior: message delivery seems to be "exclusive", meaning that a message is delivered either to clients connected to the room or to the server component, which is weird to be honest. In other words, 1 message out of 5 is delivered to the server component, and the other 4 are delivered to clients as usual.
Here's our component code (we have tried with both sleekxmpp and slixmpp but we always have the same behavior):
import sys
import logging
#import sleekxmpp
#from sleekxmpp.componentxmpp import ComponentXMPP
import slixmpp
from slixmpp.componentxmpp import ComponentXMPP
if sys.version_info < (3, 0):
from sleekxmpp.util.misc_ops import setdefaultencoding
setdefaultencoding('utf8')
else:
raw_input = input
class NotificationsComponent(ComponentXMPP):
def __init__(self):
ComponentXMPP.__init__(self, "muc.ourservice.it", "secret", "jabber.ourservice.it", 5233)
# add handler
self.add_event_handler("message", self.message)
#self.add_event_handler("groupchat_message", self.message)
def message(self, msg):
if msg['type'] == 'groupchat':
print('Received group chat message')
print(msg)
#msg.reply('Well received').send()
else:
print('Received another message')
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG,format='%(levelname)-8s %(message)s')
xmpp = NotificationsComponent()
xmpp.register_plugin('xep_0030') # Service Discovery
#xmpp.register_plugin('xep_0004') # Data Forms
#xmpp.register_plugin('xep_0060') # PubSub
xmpp.register_plugin('xep_0199') # XMPP Ping
#xmpp.register_plugin('xep_0045') # MUC
# Connect to the XMPP server and start processing XMPP stanzas.
xmpp.connect()
xmpp.process()
and here's a snippet of our ejabberd 18.03 configuration:
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
starttls: true
certfile: 'CERTFILE'
protocol_options: 'TLSOPTS'
## dhfile: 'DHFILE'
## ciphers: 'CIPHERS'
##
## To enforce TLS encryption for client connections,
## use this instead of the "starttls" option:
##
starttls_required: true
##
## Stream compression
##
zlib: true
##
max_stanza_size: 65536
shaper: none
access: c2s
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
"/admin": ejabberd_web_admin
"/bosh": mod_bosh
#request_handlers:
# "/ws": ejabberd_http_ws
# "/bosh": mod_bosh
# "/api": mod_http_api
## "/pub/archive": mod_http_fileserver
web_admin: true
http_bind: true
## register: true
captcha: false
certfile: 'CERTFILE'
tls: true
-
port: 5233
ip: "::"
module: ejabberd_service
access: all
privilege_access:
message: "outgoing"
password: "secret"
shaper: none
we have also tried to play with access, privilege_access and things like that but no luck.
Do you have any idea what might cause this weird behavior? Is there any particular plugin or module that should be enabled?
Of course, we have enabled debug logs on both sleekxmpp and ejabberd, but we don't see any errors, it's just that messages are missing.
We also did one more test. Even by using the official "echo component" example available in the slixmpp repository, we have the same issue. So it looks like there is some issue at our server, maybe on the message routing part, we don't know.
Thanks
I think you mixed a couple of things here. The component you created here seems to connect to ejabber as External Component (see https://xmpp.org/extensions/xep-0114.html or https://xmpp.org/extensions/xep-0225.html) judging from http://sleekxmpp.com/getting_started/component.html which means that ejabber (seems to at least) routes some messages to it's internal component and some to your (external) component. This would explain why your component receives only certain messages.
You have two options:
use SleekXMPP but connect as regular user (you can use "bot" example and simply listen for messages without responding)
create dedicated component/handler within ejabberd that would receive all messages and process them accordingly.
Both options has pros and cons:
client-in-room - easier (for you, it seems) development, but require to be constantly connected and may loose some messages if connection is dropped
dedicated handler in ejabberd - most likely slightly more difficult to implement.
It turns out I totally misunderstood the purpose of Jabber external components.
I was expecting to receive a "copy" of all events occurring within ejabberd, but I was wrong.
To achieve the result I was expecting, I'm using a module called "mod_post_log" which sends an HTTP request for every message sent by user. That works for me.

How to force CoTURN long term credentials validation from WebRTC Flutter application?

I use this example of Flutter data channel to connect my Android app to my CoTURN server on my local network. The CoTURN logs show that the Android app connects successfully to the CoTURN server but doesn't show any username. I would like to make sure that no access is possible to my CoTURN server while not using long term credentials.
The version of my CoTURN server is 4.5.1.1-1.1 on Debian Linux Stable (10 Buster). The lt-cred-mech is already set in the CoTURN server configuration while no-auth is not set (it is commented). I am using verbose to check the logs. I have a user created in my MySQL database for long term credentials. It is verified using this command on the secured port:
turnutils_uclient -p 5349 -u myuser -w mypassword 192.168.188.28
It leads to the following in the coturn logs:
1992: handle_udp_packet: New UDP endpoint: local addr 192.168.188.28:5349, remote addr 192.168.188.28:58256
1992: session 002000000000000002: realm <myrealm> user <>: incoming packet message processed, error 401: Unauthorized
1992: IPv4. Local relay addr: 192.168.188.28:64632
1992: IPv4. Local reserved relay addr: 192.168.188.28:64633
1992: session 002000000000000002: new, realm=<myrealm>, username=<myuser>, lifetime=777
1992: session 002000000000000002: realm <myrealm> user <myuser>: incoming packet ALLOCATE processed, success
1992: session 002000000000000002: refreshed, realm=<myrealm>, username=<myuser>, lifetime=777
1992: session 002000000000000002: realm <myrealm> user <myuser>: incoming packet REFRESH processed, success
...
2007: session 003000000000000003: delete: realm=<myrealm>, username=<myuser>
2007: session 003000000000000003: peer 0.0.0.0:3481 deleted
2008: session 001000000000000008: usage: realm=<myrealm>, username=<myuser>, rp=13, rb=1360, sp=8, sb=768
2008: session 001000000000000008: closed (2nd stage), user <myuser> realm <myrealm> origin <>, local 192.168.188.28:5349, remote 192.168.188.28:48266, reason: allocation timeout
2008: session 001000000000000008: delete: realm=<myrealm>, username=<myuser>
2008: session 001000000000000008: peer 0.0.0.0:3481 deleted
If I try the same command with an intentionally invalid user, I get the expected following results in the server logs:
2227: handle_udp_packet: New UDP endpoint: local addr 192.168.188.28:5349, remote addr 192.168.188.28:40431
2227: session 002000000000000003: realm <myrealm> user <>: incoming packet message processed, error 401: Unauthorized
2227: check_stun_auth: Cannot find credentials of user <myuserfaulty>
2227: session 002000000000000003: realm <myrealm> user <myuserfaulty>: incoming packet message processed, error 401: Unauthorized
2227: check_stun_auth: Cannot find credentials of user <myuserfaulty>
...
So, this means that the credentials are indeed checked by the CoTURN server.
However, when I add credentials to the Flutter app as follows, I get server logs that don't seem to show any user. Worst, if the user is intentionally faulty, it changes nothing. Here is the portion of code adapted:
...
Map<String, dynamic> configuration = {
"iceServers": [
{"url": "stun:192.168.188.28:5349"},
{"username": "myuserfaulty"},
{"credential": "mypassword"},
]
};
...
Note that I guessed the username and credential entries in the configuration from the following files:
https://github.com/cloudwebrtc/flutter-webrtc/blob/master/ios/Classes/FlutterWebRTCPlugin.m
https://github.com/cloudwebrtc/flutter-webrtc/blob/master/android/src/main/java/com/cloudwebrtc/webrtc/FlutterWebRTCPlugin.java
Here are the CoTURN logs while using intentionally wrong credentials from Flutter:
2945: handle_udp_packet: New UDP endpoint: local addr 192.168.188.28:5349, remote addr 192.168.188.31:58350
2945: session 002000000000000004: realm <myrealm> user <>: incoming packet BINDING processed, success
2955: session 002000000000000004: realm <myrealm> user <>: incoming packet BINDING processed, success
2965: session 002000000000000004: realm <myrealm> user <>: incoming packet BINDING processed, success
2975: session 002000000000000004: realm <myrealm> user <>: incoming packet BINDING processed, success
2985: session 002000000000000004: realm <myrealm> user <>: incoming packet BINDING processed, success
2995: session 002000000000000004: realm <myrealm> user <>: incoming packet BINDING processed, success
3005: session 002000000000000004: usage: realm=<myrealm>, username=<>, rp=6, rb=120, sp=6, sb=528
3005: session 002000000000000004: closed (2nd stage), user <> realm <myrealm> origin <>, local 192.168.188.28:5349, remote 192.168.188.31:58350, reason: allocation watchdog determined stale session state
3005: handle_udp_packet: New UDP endpoint: local addr 192.168.188.28:5349, remote addr 192.168.188.31:58350
3005: session 002000000000000005: realm <myrealm> user <>: incoming packet BINDING processed, success
3015: session 002000000000000005: realm <myrealm> user <>: incoming packet BINDING processed, success
...
So, I have the following questions:
How can I make sure that my CoTURN server cannot be used without authorized long term credentials?
How come the Flutter app is not subject to the same credentials validation as the turnutils_uclient?
Did I guess correctly the way to specify the credentials in the Flutter app with the addition of the username and credential entries in the configuration?
With this configuration (lt-cred-mech), the TURN server cannot be used without authorized long term credentials. However, the STUN server never requires authentication.
The turnutils_uclient command requires authentication because it calls the TURN server. To make a STUN server test call, the turnutils_stunclient command can be used and no credentials can be given to it.
The format for long term authentication on TURN server in Flutter is described in a comment in this file:
https://github.com/cloudwebrtc/flutter-webrtc-demo/blob/master/lib/src/call_sample/signaling.dart
...
{
'url': 'turn:123.45.67.89:3478',
'username': 'change_to_real_user',
'credential': 'change_to_real_secret'
},
...
which shows that my attempts were wrong for two reasons:
The protocol must be set to turn instead of stun.
The configuration items must be in the same array.
After those corrections, I do get the username in the coturn server logs as shown below:
87055: session 000000000000000540: new, realm=<myrealm>, username=<myuser>, lifetime=600
87055: session 000000000000000540: realm <myrealm> user <myuser>: incoming packet ALLOCATE processed, success
87065: session 000000000000000540: realm <myrealm> user <myuser>: incoming packet BINDING processed, success
Note that the coturn server configuration can require authentication for the STUN binding request as well:
...
# Require authentication of the STUN Binding request.
# By default, the clients are allowed anonymous access to the STUN Binding functionality.
#
#secure-stun
...

Unable to hide CONNECT requests in Fiddler

I'm using Fiddler v4.6.20171.26113 on Windows 8.1. I have enabled the Hide CONNECTs option under the Rules menu and even tried put this script in the custom rules file:
if (oSession.HTTPMethodIs("CONNECT"))
{
oSession["ui-hide"] = "true";
}
However the CONNECT requests are still shown even when their flag UI-HIDE: true is set.
SESSION STATE: Done.
Response Entity Size: 0 bytes.
== FLAGS ==================
BitFlags: [ResponseGeneratedByFiddler, IsDecryptingTunnel, ProtocolViolationInRequest, RequestBodyDropped] 0x10a100
HTTPS-CLIENT-SESSIONID: empty
HTTPS-CLIENT-SNIHOSTNAME: mtalk.google.com
LOG-DROP-REQUEST-BODY: yes
LOG-DROP-RESPONSE-BODY: yes
UI-BACKCOLOR: LightYellow
UI-HIDE: true
X-CLIENTIP: ::ffff:***.***.**.**
X-CLIENTPORT: 5033
X-EGRESSPORT: 55428
X-HOSTIP: **.***.***.***
X-HTTPPROTOCOL-VIOLATION: [ProtocolViolation] HTTP/1.1 Request was missing the required HOST header.
X-ORIGINAL-HOST:
X-REQUESTBODYFINALLENGTH: 1,384
X-RESPONSEBODYTRANSFERLENGTH: 0
== TIMING INFO ============
ClientConnected: 07:05:03.136
ClientBeginRequest: 07:05:03.339
GotRequestHeaders: 07:05:03.339
ClientDoneRequest: 07:05:03.339
Determine Gateway: 0ms
DNS Lookup: 0ms
TCP/IP Connect: 61ms
HTTPS Handshake: 215ms
ServerConnected: 07:05:03.777
FiddlerBeginRequest: 07:05:03.777
ServerGotRequest: 07:05:03.777
ServerBeginResponse: 00:00:00.000
GotResponseHeaders: 00:00:00.000
ServerDoneResponse: 00:00:00.000
ClientBeginResponse: 07:05:03.777
ClientDoneResponse: 07:05:03.777
Overall Elapsed: 0:00:00.437
The response was buffered before delivery to the client.
== WININET CACHE INFO ============
This URL is not present in the WinINET cache. [Code: 2]
* Note: Data above shows WinINET's current cache state, not the state at the time of the request.
* Note: Data above shows WinINET's Medium Integrity (non-Protected Mode) cache only.
So what should I do now?

Cannot send email (via GMail) with Indy. Protocol version mismatch

I want to send an email via GMail server.
TRY
SMTP.Connect; // <---- This is TIdSMTP
EXCEPT
Log.AddError('Cannot connect to the email server.');
END;
if SMTP.Connected then
TRY
SMTP.Send(MailMessage);
EXCEPT
on E:Exception DO
begin
Log.AddError('Connected to server but could not send email!');
Log.AddError(E.Message);
end;
END;
if SMTP.Connected
then SMTP.Disconnect;
This piece of code worked in 2014 with Delphi XE.
The program connects to the server ok but in the end it says "SSL is not available on this server":
Resolving hostname smtp.Gmail.com.
Connecting to 74.125.xxx.xxx
Connected.
Connected to SMTP server...
SSL status: "before/connect initialization"
SSL status: "before/connect initialization"
SSL status: "SSLv3 write client hello A"
SSL status: "SSLv3 read server hello A"
SSL status: "SSLv3 read server hello A"
Disconnected.
Connected to server but could not send email!
SSL is not available on this server.
I have the latest version of OpenSSL (downloaded today) and Delphi XE7.
The WireShark says:
Alert (Level: Fatal, Description: Protocol version)
Why I cannot send email?
I have tried all: no TSL, implicit, explicit, startTSL...
SOLUTION: sslvTLSv1 must be included in the SSLIOHandler.SSLVersions property.