Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: idSMTP SASL fails under Android..?


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 6 - Last Post: Apr 20, 2018 9:47 PM Last Post By: Bart Kindt
Bart Kindt

Posts: 33
Registered: 12/16/07
idSMTP SASL fails under Android..?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 18, 2018 4:32 AM
I am stumped by this.

I have my Windows client using IdSMTP to connect to my Linux EXIM4 server.
This always works perfectly.

I copied the entire unit over to my new Android App, that is, I copied the .pas file, and I made a new FMX Form for it on which I copied the exact same selection of SMTP, SSL and SASL etc. components.
I have set these up on the Form in exactly the same way.
Added the same 3 SASL Mechanisms in the IdSMTP and in the same order.
As far as I can see it is all exactly the same.

   SMTP: TIdSMTP;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
    IdUserPassProvider1: TIdUserPassProvider;
    IdSASLPlain1: TIdSASLPlain;
    IdSASLSKey1: TIdSASLSKey;
    IdSASLCRAMMD51: TIdSASLCRAMMD5;
    IdSASLCRAMSHA11: TIdSASLCRAMSHA1;
    IdSASLLogin1: TIdSASLLogin;
 
  procedure:
 (Note this works perfectly under Windows)
            if UsePLAINSASL then
            begin
              if Superuser then LocalLog('UsePLAINSASL: Logging in with Username='+AUsername);
              SMTP.Username := AUsername;
              SMTP.Password := APassword;
              IdUserPassProvider1.Username := AUsername;
              IdUserPassProvider1.Password := APassword;
              IdSASLPlain1.LoginAs := AUsername;
 
              SMTP.AuthType := satSASL;
              SMTP.UseEhlo := true;
 
              IdSSLIOHandlerSocketOpenSSL1.Port := APort;
              IdSSLIOHandlerSocketOpenSSL1.Host := AHost;
              IdSSLIOHandlerSocketOpenSSL1.ReadTimeout := 10000;
 
              IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmClient;
              IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
              IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1];
 
              SMTP.UseTLS := utUseExplicitTLS; // utNoTLSSupport; //
              SMTP.ValidateAuthLoginCapability := true;
            end else


But the Android system fails with a: "Doesn't support AUTH or the specified SASL handlers!!"

I use the Android-type OpenSSL libraries, which are loaded correctly (and which are also used by the an IdTCPClient when connecting to an IdTCPServer)

When I look at the debug output of the EXIM Server, it seems to me that the SASL authentication HAS in fact finished, because the Server is already in TLS mode and is waiting for its first TLS packet. Which it never gets.

The Server shows this:
17925 Listening...
17925 Connection request from 62.140.132.204 port 18027
 
17927 SMTP>> 220 apollo.bart.gen.nz ESMTP Exim 4.80 Wed, 18 Apr 2018 13:24:42 +0200
17927 Process 17927 is ready for new message
17927 smtp_setup_msg entered
17927 SMTP<< EHLO localhost
17927 localhost in helo_lookup_domains? no (end of list)
17927 sender_fullhost = (localhost) [62.140.132.204]
17927 sender_rcvhost = [62.140.132.204] (helo=localhost)
17927 set_process_info: 17927 handling incoming connection from (localhost) [62.140.132.204]
17927 host in pipelining_advertise_hosts? yes (matched "*")
17927 host in auth_advertise_hosts? yes (matched "*")
17927 host in tls_advertise_hosts? yes (matched "*")
17927 SMTP>> 250-apollo.bart.gen.nz Hello localhost [62.140.132.204]
17927 250-SIZE 52428800
17927 250-8BITMIME
17927 250-PIPELINING
17927 250-AUTH PLAIN
17927 250-STARTTLS
17927 250 HELP
17927 SMTP<< STARTTLS                  <<<<<<<<<<<<<<<<<
17927 initialising GnuTLS as a server
17927 GnuTLS global init required.
17927 initialising GnuTLS server session
17927 Expanding various TLS configuration options for session credentials.
17927 certificate file = /etc/exim4/exim.crt
17927 key file = /etc/exim4/exim.key
17927 TLS: cert/key registered
17927 verify certificates = /etc/ssl/certs/ca-certificates.crt size=272519
17927 Added 172 certificate authorities.
17927 Initialising GnuTLS server params.
17927 Loading default hard-coded DH params
17927 Loaded fixed standard D-H parameters
17927 GnuTLS using default session cipher/priority "NORMAL"
17927 host in tls_verify_hosts? no (option unset)
17927 host in tls_try_verify_hosts? no (option unset)
17927 TLS: a client certificate will not be requested.   <<<<<<<<<<<<<<<<<<<<<
17927 SMTP>> 220 TLS go ahead                            <<<<<<<<<<<<<<<<<<<<<
17927 Received TLS SNI "sartrack.nl" (unused for certificate selection)
17927 gnutls_handshake was successful                   <<<<<<<<<<<<<<<<<<<<
17927 TLS: no certificate from peer ((nil) & 0)
17927 cipher: TLS1.0:DHE_RSA_AES_256_CBC_SHA1:256
17927 Have channel bindings cached for possible auth usage.
17927 sender_fullhost = [62.140.132.204]
17927 sender_rcvhost = [62.140.132.204]
17927 set_process_info: 17927 handling incoming TLS connection from [62.140.132.204]
17927 TLS active                              <<<<<<<<<<<<<<<<<<<<<<<<<
17927 Calling gnutls_record_recv(0x7f323331eae0, 0x7f32336060a0, 4096)  <<<<<<<<<<<<<<< Its waiting here.
 
17927 SMTP<< EHLO localhost           <<<<<<<<<<<<<<<<<<<<<< It seems the Client is trying again??? 
17927 localhost in helo_lookup_domains? no (end of list)
17927 sender_fullhost = (localhost) [62.140.132.204]
17927 sender_rcvhost = [62.140.132.204] (helo=localhost)
17927 set_process_info: 17927 handling TLS incoming connection from (localhost) [62.140.132.204]
17927 host in pipelining_advertise_hosts? yes (matched "*")
17927 host in auth_advertise_hosts? yes (matched "*")
17927 tls_do_write(0x7f32333012b8, 132)
17927 gnutls_record_send(SSL, 0x7f32333012b8, 132)
17927 outbytes=132
17927 SMTP>> 250-apollo.bart.gen.nz Hello localhost [62.140.132.204]
17927 250-SIZE 52428800
17927 250-8BITMIME
17927 250-PIPELINING
17927 250-AUTH PLAIN
17927 250 HELP
17927 Calling gnutls_record_recv(0x7f323331eae0, 0x7f32336060a0, 4096)      <<<<<<<<<<<< Waiting again. It stops here.
 

---
Bart Kindt
CEO & Developer
SARTrack Limited New Zealand
http://www.sartrack.nz

Edited by: Bart Kindt on Apr 19, 2018 12:17 AM

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: idSMTP SASL fails under Android..? [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 18, 2018 11:20 AM   in response to: Bart Kindt in response to: Bart Kindt
Bart Kindt wrote:

SMTP.Username := AUsername;
SMTP.Password := APassword;

Those properties are only used when AuthType=satDefault.

IdSSLIOHandlerSocketOpenSSL1.Port := APort;
IdSSLIOHandlerSocketOpenSSL1.Host := AHost;

You do not need to set those properties manually, Connect() handles
that for you.

IdSSLIOHandlerSocketOpenSSL1.ReadTimeout := 10000;

You should set the TIdSMTP.ReadTimeout instead of setting the
IOHandler.ReadTimeout directly.

IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1];

You do not need to set both of those properties. They are mutually
exclusive, setting one updates the other. So, set only one or the
other, not both.

SMTP.ValidateAuthLoginCapability := true;

That property is only used when AuthType=satDefault.

But the Android system fails with a: "Doesn't support AUTH or the
specified SASL handlers!!"

That error means the server's latest EHLO response does not specify any
SASL mechanisms that match what you have configured in the
TIdSMTP.SASLMechanisms collection.

I use the Android-type OpenSSL libraries, which are loaded correctly
(and which are also used by the an IdTCPClient when connecting to an
IdTCPServer)

This is not an SSL/TLS issue. You would be getting a completely
different type of error if SSL/TLS were not working. The fact that you
are getting any SMTP traffic logged at all after STARTTLS is finished
means that SSL/TLS is working fine.

When I look at the debug output of the EXIM Server, it seems to me
that the SASL authentication HAS in fact finished

No, it hasn't, because authentication hasn't been attempted yet when
the error you are seeing occurs.

because the Server is already in TLS mode and is waiting for its first
TLS packet.

Encryption and Authentication are two completely different things.

Which it never gets.

Correct, because the error you are seeing is raised by TIdSMTP before
it sends any AUTH command to the server.

SMTP<< EHLO localhost

An SMTP client should not be sending 'localhost' as its reported name.
It should be sending its actual machine hostname. TIdSMTP has a
HeloName property that you can set to any name you want. If HeloName
is empty, GStack.HostName() is used, and if that is empty, then
IndyComputerName() is used. None of those should be returning
'localhost'. If they are, that is a bug that needs to be fixed.

SMTP>> 250-apollo.bart.gen.nz Hello localhost [62.140.132.204]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN
250-STARTTLS
250 HELP

That is the server's initial greeting. As you can see, when you first
connect to the server, before SSL/TLS is activated, the only SASL
available is PLAIN (as it doesn't require a secure connection).

SMTP<< STARTTLS

That is the client's request to initiate a SSL/TLS session.

SMTP>> 220 TLS go ahead

That is the server's response giving the OK to start an SSL/TLS
handshake.

TLS active <<<<<<<<<<<<<<<<<<<<<<<<<
Calling gnutls_record_recv(0x7f323331eae0, 0x7f32336060a0, 4096)
<<<<<<<<<<<<<<< Its waiting here.

Which makes sense, since the SSL/TLS handshake is finished, and the
server is waiting for the client's next (encrypted) SMTP command.

SMTP<< EHLO localhost <<<<<<<<<<<<<<<<<<<<<< It seems
the Client is trying again???

Yes, because it is supposed to. After an SSL/TLS session is
established, the server's capabilities MAY change, so the client has to
query the server again to get its updated capabilities. Most notably,
SASLs that require a secure connection are not reported in the initial
unencrypted EHLO but are reported in the subsequent encrypted EHLO.

However, as you can see in the log, the only change to the server's
capabilities after a STARTTLS command is performed is that the STARTTLS
capability disappears from the list, which makes sense as a new
STARTTLS command is not allowed after a previous STARTTLS command is
successful.

We can clearly see in the log that the AUTH capabilities are not
changing after STARTTLS. In both unencrypted and encrypted modes, your
server only supports PLAIN authentication.

You claim to have hooked up a TIdSASLPlain to TIdSMTP, but the ONLY way
to get the error you are seeing is if TIdSMTP cannot find the
TIdSASLPlain in the SASLMechanisms collection. Which means you HAVE
NOT hooked it up correctly. It is not enough to just drop TIdSASLPlain
onto your Form. You need to add an entry to the SASLMechanisms
collection and set its SASL property to point at the TIdSASLPlain
object. Double-check that is actually the case. And double-check that
what you set at design-time is being loaded correctly at run-time.

Calling gnutls_record_recv(0x7f323331eae0, 0x7f32336060a0,
4096) <<<<<<<<<<<< Waiting again. It stops here.

Again, because it is waiting for the client's next SMTP command.

--
Remy Lebeau (TeamB)
Bart Kindt

Posts: 33
Registered: 12/16/07
Re: idSMTP SASL fails under Android..? [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 18, 2018 9:31 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

SMTP<< EHLO localhost

An SMTP client should not be sending 'localhost' as its reported name.
It should be sending its actual machine hostname. TIdSMTP has a
HeloName property that you can set to any name you want. If HeloName
is empty, GStack.HostName() is used, and if that is empty, then
IndyComputerName() is used. None of those should be returning
'localhost'. If they are, that is a bug that needs to be fixed.

This is an Android (7) phone. As you can see, by default it sends 'localhost'. So if that is not right, then maybe the Indy system must be looked into.
I have now manually set the HeloName.

We can clearly see in the log that the AUTH capabilities are not
changing after STARTTLS. In both unencrypted and encrypted modes, your
server only supports PLAIN authentication.

You claim to have hooked up a TIdSASLPlain to TIdSMTP, but the ONLY way
to get the error you are seeing is if TIdSMTP cannot find the
TIdSASLPlain in the SASLMechanisms collection. Which means you HAVE
NOT hooked it up correctly. It is not enough to just drop TIdSASLPlain
onto your Form. You need to add an entry to the SASLMechanisms
collection and set its SASL property to point at the TIdSASLPlain
object. Double-check that is actually the case. And double-check that
what you set at design-time is being loaded correctly at run-time.

I checked and re-checked.
The SMTP is linked to the IdSSLIOHandlerSocketOpenSSL1.
The SMTP.SASLMechanisms is linked to CRAM-MD5, IdSASLLogin and IdSASLPlain in that order. I can see this in the selection box, and in the IDE Structure.

However, there is one thing which worries me. In the visual IDE SASLMechanisms selection window, I have TWO copies of all the components. I only select ONE of the ones I need.
This issue do NOT occur on the VCL Form (of my Windows program); it only occurs on the FMX Form for my Android App.
Note: You can test this yourself. But I use Delphi 10.2.3.

All these:

IdSASLPlain1: TIdSASLPlain;
IdSASLSKey1: TIdSASLSKey;
IdSASLCRAMMD51: TIdSASLCRAMMD5;
IdSASLCRAMSHA11: TIdSASLCRAMSHA1;
IdSASLLogin1: TIdSASLLogin;
are linked to the
IdUserPassProvider1: TIdUserPassProvider;

Can you please advise how I can set the SMTP.SASLMechanisms at runtime in the code? That way we can be absolutely sure it is in fact set up properly, and you can confirm the while setup is in fact correct.
Especially because the FMX form selection does not seem right.

Thanks, Bart

---
Bart Kindt
CEO & Developer
SARTrack Limited New Zealand
http://www.sartrack.nz
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: idSMTP SASL fails under Android..? [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 19, 2018 11:28 AM   in response to: Bart Kindt in response to: Bart Kindt
Bart Kindt wrote:

I checked and re-checked.

The SMTP.SASLMechanisms is linked to CRAM-MD5, IdSASLLogin and
IdSASLPlain in that order. I can see this in the selection box, and
in the IDE Structure.

But, did you check it *at run-time*? Loop through the SASLMechanisms
and output each item's SASL.ServiceName property value, make sure you
find an item for 'PLAIN'.

However, there is one thing which worries me. In the visual IDE
SASLMechanisms selection window, I have TWO copies of all the
components.

There should not be multiple copies. SASLMechanism is a simple
TCollection, so either you really have multiple entries/objects that
you need to remove, or the IDE has a bug in its native collection
editor.

I only select ONE of the ones I need. This issue do NOT occur on the
VCL Form (of my Windows program); it only occurs on the FMX Form for
my Android App.

What does the content of your FMX Form's DFM look like for the
SASLMechanisms?

Note: You can test this yourself.

Actually, I can't.

Can you please advise how I can set the SMTP.SASLMechanisms at
runtime in the code?

SMTP.SASLMechanisms.Clear;
SMTP.SASLMechanisms.Add.SASL := IdSASLCRAMMD51;
SMTP.SASLMechanisms.Add.SASL := IdSASLCRAMSHA11;
SMTP.SASLMechanisms.Add.SASL := IdSASLLogin1;
SMTP.SASLMechanisms.Add.SASL := IdSASLPlain1;
SMTP.SASLMechanisms.Add.SASL := IdSASLSKey1;


--
Remy Lebeau (TeamB)
Bart Kindt

Posts: 33
Registered: 12/16/07
Re: idSMTP SASL fails under Android..? [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 19, 2018 9:56 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Bart Kindt wrote:

What does the content of your FMX Form's DFM look like for the
SASLMechanisms?

EDIT: I just looked at it more properly, and I now see the problem is totally in the IDE: It adds stuff in front of the component name, which causes the fault you see below in the code.

object MailTCLForm: TMailTCLForm
 // snip
  object SMTP: TIdSMTP
    IOHandler = IdSSLIOHandlerSocketOpenSSL1
    AuthType = satSASL
    SASLMechanisms = <
      item
        SASL = IdSASLCRAMMD51
      end
      item
        SASL = form_006D0D20.IdSASLCRAMSHA11
      end
      item
        SASL = form_006D0D20.IdSASLPlain1
      end
      item
        SASL = IdSASLLogin1
      end
      item
        SASL = form_006D0D20.IdSASLSKey1
      end>
    UseTLS = utUseExplicitTLS
    Left = 32
    Top = 32
  end
  object IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL
    Destination = ':25'
    MaxLineAction = maException
    Port = 25
    DefaultPort = 0
    SSLOptions.Mode = sslmClient
    SSLOptions.VerifyMode = []
    SSLOptions.VerifyDepth = 0
    Left = 136
    Top = 40
  end
  object IdUserPassProvider1: TIdUserPassProvider
    Left = 128
    Top = 96
  end
  object IdSASLPlain1: TIdSASLPlain
    UserPassProvider = IdUserPassProvider1
    Left = 120
    Top = 168
  end
  object IdSASLSKey1: TIdSASLSKey
    UserPassProvider = IdUserPassProvider1
    Left = 256
    Top = 280
  end
  object IdSASLCRAMMD51: TIdSASLCRAMMD5
    UserPassProvider = IdUserPassProvider1
    Left = 264
    Top = 152
  end
  object IdSASLCRAMSHA11: TIdSASLCRAMSHA1
    UserPassProvider = IdUserPassProvider1
    Left = 248
    Top = 216
  end
  object IdSASLLogin1: TIdSASLLogin
    UserPassProvider = IdUserPassProvider1
    Left = 112
    Top = 240
  end
end


Now look what happens:
if UsePLAINSASL then
            begin
              if Superuser then LocalLog('UsePLAINSASL: Logging in with Username='+AUsername);
              IdUserPassProvider1.Username := AUsername;
              IdUserPassProvider1.Password := APassword;
              IdSASLPlain1.LoginAs := AUsername;
 
              SMTP.AuthType := satSASL;
              SMTP.UseEhlo := true;
              // Testing the Designtime settings:
              LogService('Testing designtime SASLMechanisms: Count='+IntToStr(SMTP.SASLMechanisms.Count));
// result= Testing designtime SASLMechanisms: Count=5   <<<< 5 !
              try
                for i := 0 to SMTP.SASLMechanisms.Count-1 do
                begin
                  LogService('SASLMechanisms('+IntToStr(i)+') '+SMTP.SASLMechanisms[i].SASL.ServiceName);
                end;
              except
                on E:Exception do LogEService('Stepping through Designtime SASLMechanisms: '+E.Message);
              end;
// The result is this!
UsePLAINSASL: Logging in with Username...
SASLMechanisms(0) CRAM-MD5
ERROR: Stepping through Designtime SASLMechanisms: Access violation at address 8BF9A3D4, accessing address 00000003
 
              SMTP.SASLMechanisms.Clear;
              SMTP.SASLMechanisms.Add.SASL := IdSASLCRAMMD51;
              SMTP.SASLMechanisms.Add.SASL := IdSASLCRAMSHA11;
              SMTP.SASLMechanisms.Add.SASL := IdSASLLogin1;
              SMTP.SASLMechanisms.Add.SASL := IdSASLPlain1;
              SMTP.SASLMechanisms.Add.SASL := IdSASLSKey1;
 
              // Testing the Runtime settings:
              try
                for i := 0 to SMTP.SASLMechanisms.Count-1 do
                begin
                  LogService('SASLMechanisms('+IntToStr(i)+') '+SMTP.SASLMechanisms[i].SASL.ServiceName);
                end;
              except
                on E:Exception do LogEService('Stepping through Runtime SASLMechanisms: '+E.Message);
              end;
// Result:
SASLMechanisms(0) CRAM-MD5
SASLMechanisms(1) CRAM-SHA1
SASLMechanisms(2) LOGIN
SASLMechanisms(3) PLAIN
SASLMechanisms(4) SKEY
 
              IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmClient;
              IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
 
              SMTP.UseTLS := utUseExplicitTLS;
              SMTP.ValidateAuthLoginCapability := true;
            end else


This is a major bug.
First, in the IDE, it does not clear the design time windows on the left side, it keeps adding more and more copies of the components.
However, I can select correctly select one copy of each, which show in the IDE 'Structure' window.

EDIT: The componentsdo NOT correctly show in the .FMX file: They have stuff like "form_006D0D20." in front of the component name.
As a result, they are not initialized when they are added to the SASLMechanisms.

Do you want me to report this?

My program now works perfectly, after adding the SASLMechanisms in the code.

Thanks, Bart

---
Bart Kindt
CEO & Developer
SARTrack Limited New Zealand
http://www.sartrack.nz

Edited by: Bart Kindt on Apr 20, 2018 4:58 PM
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: idSMTP SASL fails under Android..? [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 20, 2018 1:41 PM   in response to: Bart Kindt in response to: Bart Kindt
Bart Kindt wrote:

EDIT: I just looked at it more properly, and I now see the problem is
totally in the IDE: It adds stuff in front of the component name,
which causes the fault you see below in the code.

Yup, that would do it, assuming form_006D0D20 doesn't actually exist.
You should have gotten a runtime error when the DFM is loading and
couldn't resolve the references. If not, I would consider that a bug
on Embarcadero's part.

ERROR: Stepping through Designtime SASLMechanisms: Access violation
at address 8BF9A3D4, accessing address 00000003

Yup, a nil pointer is being accessed. When the DFM couldn't resolve
'form_006D0D20.IdSASLCRAMSHA11', it set that TIdSASLListEntry.SASL
property to nil instead of raising an exception. Same with
'form_006D0D20.IdSASLPlain1' and 'form_006D0D20.IdSASLSKey1'. And
those nils would cause TIdSMTP to ignore those entries during login,
thus resulting in the EIdSASLNotSupported exception you were originally
seeing.

This is a major bug.

Yup, but in the DFM itself, not in Indy.

Do you want me to report this?

Yes, to Embarcadero. There are clearly IDE-related bugs at play here.

--
Remy Lebeau (TeamB)
Bart Kindt

Posts: 33
Registered: 12/16/07
Re: idSMTP SASL fails under Android..? [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 20, 2018 9:47 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Do you want me to report this?

Yes, to Embarcadero. There are clearly IDE-related bugs at play here.

https://quality.embarcadero.com/browse/RSP-20418

---
Bart Kindt
CEO & Developer
SARTrack Limited New Zealand
http://www.sartrack.nz

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02