B4J Question SMTP error: 503 5.5.2 Need mail command.

amykonio

Active Member
Licensed User
Longtime User
Hi.

We are using SMTP to send a mail from an SMTP server which isn’t public. We do have access to this SMTP through some firewall rules. I’ve a simple test application written in c# that successfully sends an email through the described configuration. The code in c# is almost identical to the code we developed in B4J.

We want to send the same way a mail using B4J. The reason is because we have a Web Application written in B4J that should send that mail. Here is the class we implemented and use in B4J:
SendMail:
Sub Class_Globals
    Private SMTP As SMTP
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    Dim mailServer, mailServerPort, mailServerUserName, mailServerPassword, security, mailSender As String

    Try
        mailSender = Main.settings.Get("MailSender")
        mailServer = Main.settings.Get("MailServer")
        mailServerPort = Main.settings.Get("MailServerPort")
        mailServerUserName =  Main.settings.Get("MailServerUserName")
        mailServerPassword = Main.settings.Get("MailServerPassword")
        security = Main.settings.Get("Security")
    
        SMTP.Initialize(mailServer, mailServerPort, mailServerUserName, mailServerPassword, "SMTP")
        SMTP.Sender = mailSender
        
'        Select Main.settings.Get("AuthMethod")
'            Case "AUTH_PLAIN"
'                SMTP.AuthMethod = SMTP.AUTH_PLAIN
'            Case "AUTH_LOGIN"
'                SMTP.AuthMethod = SMTP.AUTH_LOGIN
'            Case "AUTH_CRAM_MD5"
'                SMTP.AuthMethod = SMTP.AUTH_CRAM_MD5
'            Case Else
'                SMTP.AuthMethod = SMTP.AUTH_PLAIN
'        End Select
'       
'        Select security.ToUpperCase
'            Case "SSL"
'                SMTP.UseSSL = True
'                SMTP.StartTLSMode = False
'            Case "TLS"
'                SMTP.StartTLSMode = True
'                SMTP.UseSSL = False
'            Case Else
'                SMTP.UseSSL = False
'                SMTP.StartTLSMode = False
'        End Select
        
        Log("mailSender: " & mailSender)
        Log("mailServerPort: " & mailServerPort)
        Log("mailServerUserName: " & mailServerUserName)
        Log("mailServerPassword: " & mailServerPassword)
        Log("UseSSL: " & SMTP.UseSSL)
        Log("StartTLSMode: " & SMTP.StartTLSMode)
    Catch
        Log("SendMail Initialize")
        Log(LastException)
    End Try
End Sub

public Sub sendMessage(recipients As List, subject As String, cc As List, bcc As List, body As String, htmlBody As Boolean)
    Try
        SMTP.Body = body
        SMTP.HtmlBody = htmlBody
        SMTP.To = recipients
        If cc.Size > 0 Then SMTP.CC = cc
        If bcc.Size > 0 Then SMTP.BCC = bcc
        SMTP.Subject = subject
    
'        Log(SMTP.To)
'        Log(SMTP.CC)
'        Log(SMTP.BCC)
'        Log(SMTP.HtmlBody)
'        Log(SMTP.Body)
    
        SMTP.Send
    Catch
'        Log("sendMessage")
        Log("SendMail sendMessage")
        Log(LastException)
    End Try
End Sub

Private Sub SMTP_MessageSent(Success As Boolean)
    Try
'        Log(Success)
        If Not(Success) Then
            Log("SendMail MessageSent Failure")
            Log(LastException.Message)
        End If
    Catch
'        Log("EventName_MessageSent")
        Log("SendMail MessageSent Error")
        Log(LastException)
    End Try
End Sub
We call it like that:
Calling SendMail Class.:
Dim testMail As SendMail
Dim recp, cc, bcc As List

recp.Initialize
cc.Initialize
bcc.Initialize

recp.Add("<[email protected]>")

Try
    testMail.Initialize
    LogDebug("sendMessage")
    testMail.sendMessage(recp, "Test mail", cc, bcc, "This is a mail test!", False)
Catch
    fx.Msgbox(Null, LastException.Message, "Error:")
    Log("ButtonTestMail_Click")
    Log(LastException)
End Try
I did many tests. I tried to set AuthMethod. I tried to set MailFrom manually, as I see this is the command related with SMTP MAIL command. I do get the following error:
1634966946385.png

Error message::
java.lang.RuntimeException: Empty writer returned: 503 5.5.2 Need mail command

        at b4j/anywheresoftware.b4a.net.SMTPWrapper$1.run(Unknown Source)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
        at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.base/java.lang.Thread.run(Unknown Source)
SendMail MessageSent Failure
java.lang.RuntimeException: Empty writer returned: 503 5.5.2 Need mail command
I know the provided code is working with yahoo mail. But we have to use that specific exchanges server through vpn to send mail.
No success until now.

So if someone has an idea what should I change to make this work it will be welcome.

Thanks
Andreas.
 

drgottjr

Expert
Licensed User
Longtime User
technicality first: there is no SMTP MAIL command.
the "mail" command referred to in the error message is from the
jnet library. it's a method in that library. (smtp has a MAIL TO
command).

503 is bad sequence, meaning smtp commands were issued
out of order, assuming one can believe the correct error was
reported. obviously, you have no control over how the commands
are issued. if you're ever talked to an smtp server, you can see
what happens when you type the commands in the wrong sequence.
the library, of course, is hard-wired to send them in the correct
order. but that doesn't mean an unexpected error cannot occur,
and a command is missed (in this case the mail() method).

the runtime exception you see occurs at a point when the library
is about to deal with preparing the message body for transmission.
it attempts to create an instance of a "reader" to handle the
message body. that creation fails if the library discovers there
has been a certain category of error since you logged in to the
server. the runtime exception about an empty reader is thrown.
it means some error occurred further up the chain of events, and
you're just learning of it when you try to create a "reader". what
that error was, is hard to say.

but i have 2 suggestions:
1) verify the correctness of your settings.map. we see your code,
but we don't see the settings. i'm specifically concerned about the
port number and the authentication method chosen (the security
setting, i presume). having the wrong port for a given authentication
method, should stop you early on, but double check. if you're jumping
back and forth in various testing modes, you may have forgotten to
changes the port number.

2) run the test in debug mode. the various "source unknown" messages
you saw are usually called by a lack of debugging references. the unknown
source might be revealed and point you to the error which triggered the
runtime exception. the library is pretty specific about when that particular
exception is thrown and why (the reader could not be instantiated due to
some error's occuring prior to that point).
 
Upvote 0

amykonio

Active Member
Licensed User
Longtime User
Hi.
First of all I want to thank you for the detailed answer you provided.

For point (1), the settings I use are ok. I know that because i do log the values. Also I do have a c# test that works with same settings.

For point (2), I do run the application using debug. Here is the log:

Waiting for debugger to connect...
Program started.
mailSender: e******e@******.gr
mailServerPort: 587
mailServerUserName: e******e
mailServerPassword: **********
UseSSL: false
StartTLSMode: false
sendMessage
org.apache.commons.net.smtp.SMTPConnectionClosedException: Connection closed without indication.
at org.apache.commons.net.smtp.SMTP.__getReply(SMTP.java:199)
at org.apache.commons.net.smtp.SMTP.__sendCommand(SMTP.java:171)
at org.apache.commons.net.smtp.SMTP.__sendCommand(SMTP.java:186)
at org.apache.commons.net.smtp.SMTP.rcpt(SMTP.java:524)
at org.apache.commons.net.smtp.SMTPClient.addRecipient(SMTPClient.java:314)
at anywheresoftware.b4a.net.SMTPWrapper$1.run(SMTPWrapper.java:298)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)


The above error occurs sometime after the execution of SMTP.Send command.
And of course Sub SMTP_MessageSent success is false.

As for the Mail command I mentioned, actually I was influenced by the following:
1635080291129.png


I did read somewhere that old versions of Exchange (ex: Exchange 2010) do not recognize that command (do not have an equivallent to set different username for an email)... If this is true, I guess that I cannot have a different username for an email account, so I'm stuck. But: a) I am not sure if this information is correct, b) I don't know the Exchange Version I try to connect to, c) still, why c# example succeeds?

Another think I'm not sure, is when my SMTP instance issues the connection to the smtp server - authenticates. It happens with the initialization or when SMTP.Send is reached? If the authentication happens with initialize, then I should be connected to the server at the moment this error occurs.

Andreas.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
regarding the word "mail": with mail command and MAIL and MAIL FROM and
MailFrom, we're talking about different things. just to clarify, "MAIL FROM:" is
part of the very simple smtp dialog. any other variations on the word "mail" are
not part of that dialog. i'm not saying "[Mm]ail" has nothing to do with email; i'm
just saying that "MAIL FROM:" is the command issued to an smtp mail server.
it must be followed by something very specific. (there is a documented
protocol.) it must be the second command issued to the server (after the
initial handshake), and if it is incorrect (based on the protocol), the server
will issue an error code, and you can't continue until you get the "MAIL FROM:"
right. how the other side (the client) responds to the error is up to how the
client is written. it might, eg, throw an exception. in contrast, if i am talking
directly to an smtp server and mistype a command, i get an error, but i
simply retype the command and move on. obviously, a library would handle
things differently.

the jnet library (the smtp part) has 2 parts: one to guide the process, and the
other to implement the smtp dialog. the log entries that you posted today are
quite different from what you posted yesterday, and they paint a slightly
different picture. i'm interested in spending the time following the flow, but
someone else may have to jump in if your experiences ring a bell.

the "guide" part of the jnet library runs a thread which steps through all the
methods in the implementation part of the library. those methods all throw
the "SMTPConnectionClosedException:" that you see in the log. if the
connection has been closed, and you continue to issue commands, they're
all going to throw the error. where the first one occurs (and why) would be the key.

edit: are you able to ssh to the box your server is on? if so you could telnet to the
server and see if you can send the message by hand. as i've repeated, the dialog is
simple, and you see where you stand immediately. (if you use authentication, then
it gets less simple as you have to format the challenge/response.) unless you're
monitoring the process with wireshark, it's pretty hard to know if there is an issue
with on the server's side or with the client.
 
Last edited:
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
first, this message: "at org.apache.commons.net.smtp.SMTP.__getReply(SMTP.java:199)"
can be misleading. by "Reply", it's referring to the smtp dialog (the reply to each command),
not to a reply to somebody's email.

every instance of "Connection closed without indication" (including at line 199 in the source)
is related to the server's attempt to process the message body. there seems to be a problem
with the message.

proposed fix:
try ending your test message with "\r\n\r\n". the library adds the required "." signalling the end
of the dialog. that is to say, the "." has to start a line. for that to happen, i think you need to
have ended a line. your test message does not do that. see what happens. it might work
with b4x's CRLF & CRLF, but you may have to actually put "\r\n\r\n" at the end.
 
Upvote 0

amykonio

Active Member
Licensed User
Longtime User
As we were not able to find a solution to our problem, we ended up calling the c# class library to do the same think. To simplify things, we created an external stored procedure (the sql server we use supports that), and we call it from b4j application with the appropriate params. And It works fine.

Many thanks to @drgottjr for the time you spent trying to help us.

Andreas.
 
Upvote 0

virpalacios

Active Member
Licensed User
Longtime User
Hi, I got the same messaje, so I have to put the sender complete mail address and issue a StartMessageLoop right After the Send Command.

Best Regards
 
Upvote 0
Top