B4J Question SMTP - Connection closed / Access denied - Invalid HELO name

aaronk

Well-Known Member
Licensed User
Longtime User
Hi,

I am using B4J to connect to my SMTP server to send emails, but I am finding it's not 100% working correctly with my new server I recently setup.

Using Outlook on the same PC as my B4J app it works fine using Outlook. I then tried on another computer (Mac) and it works fine using the Apple Mail app on the Mac.

If I used Roundcube on the same server as the mail server it also works fine.

Soon as I enter the same SMTP connection settings as I used in the above (Outlook and the mail app on the Mac) in my B4J app it fails to send the email.

I then tried Gmail, and my other site shared hosting provider SMTP server to test and confirm if it works, and it seems to work fine.

While using my new server SMTP it shows the following error:

Program started.
SMTP Initialize Done
SendEmail
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.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
eMail Failed to send - To: xxxxx@xxxxxx.xxx Subject: subject test1
org.apache.commons.net.smtp.SMTPConnectionClosedException: Connection closed without indication.
(removed email and password while posting on the forum)

Here is the code I am using:
B4X:
Sub Process_Globals
    Dim smtp As SMTP
End Sub

Sub AppStart (Args() As String)

    RunSMTPTest

    StartMessageLoop
End Sub

Sub RunSMTPTest
 
    Dim smtpServer As String = "mail.xxxxxxxxxx.xxx"
    Dim smtpPort As Int = 587
    Dim user As String = "xxxxx@xxxxxxxxxx.xxx"
    Dim email_password As String = "xxxxxxxxxxxx"

    smtp.Initialize(smtpServer, smtpPort, user, email_password, "smtp")
    smtp.StartTLSMode = True
    smtp.UseSSL = False

    Log("SMTP Initialize Done")
 
    SendEmail("xxxxx@xxxxxx.xxx", user, "subject test1", "body test 1")
 
End Sub

Public Sub SendEmail(ToEmail As String, from As String, Subject As String, body As String)
    Log("SendEmail")
    Try
        smtp.To.Add(ToEmail)
        smtp.Sender = from
        smtp.Body = body
        smtp.Subject = Subject
        smtp.Send
    Catch
        Log("Error: SendEmail To - " & ToEmail & " Subject: " & Subject)
        Log(LastException.Message)
    End Try
 
    wait for SMTP_MessageSent(Success As Boolean)
    ' this is triggered once the email has been sent or failed to be sent
    If Success Then
        Log("eMail Sent OK - To: " & ToEmail & " Subject: " & Subject)
    Else
        Log("eMail Failed to send - To: " & ToEmail & " Subject: " & Subject)
        Log(LastException.Message)
    End If
End Sub

The email server I am using is on a VPS and is Exim4. I also have full control over this server.
I also have Vesta Control Panel installed on the server, which is managing the email accounts etc.

Screen Shot 2021-04-02 at 4.19.12 pm.png


In the log file for Exim4 it shows:
Access denied - Invalid HELO name (See RFC2821 4.1.3)

I did a quick Google search and found that, If I edit the file:
vi /etc/exim4/exim4.conf.template

and then comment the lines:
# drop condition = ${if isip{$sender_helo_name}}
# message = Access denied - Invalid HELO name (See RFC2821 4.1.3)

Then restart Exim:
/etc/init.d/exim4 restart

It nows allows me to send emails using my B4J code as above.

By commenting the above lines in the Exim does that mean there is an a new way in sending emails that the B4J jNET library don't know about ?

Just trying to work out why it works fine in Outlook on my Windows 10 PC, and the Apple Mail app on my MAC fine, but not in B4J until I comment the above lines.

Is it safe to leave the above lines commented out or will it cause issues? Is there anything in my B4J app I can do so I don't need to comment the 2 lines ?
 

aaronk

Well-Known Member
Licensed User
Longtime User
I tried to use the different AuthMethod but seem to have the same result.

It's strange how Outlook on my Win10 PC, and the Mail App on the Mac work fine (on different computes) but in B4J it fails even knowing I am using the exact same details.
 
Upvote 0

aaronk

Well-Known Member
Licensed User
Longtime User
I have done some further testing, and I think there maybe an issue in the jNet Library from what I can see when sending the email.

My Mail server seems to fail with the code as post 1, unless I made the changes to the mail server as per post 1.

Without making any changes to the mail server I seem to get it working with the following inline Java code in B4J..

B4X:
#AdditionalJar: javax.mail-1.6.2.jar. ' file from: https://maven.java.net/content/repositories/releases/com/sun/mail/javax.mail/1.6.2/javax.mail-1.6.2.jar


Sub SendEmailMessage
    Dim jo As JavaObject = Me
    jo.RunMethod("sendemail", Null)
End Sub

#if Java
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

   public static void sendemail() {
      // Recipient's email ID needs to be mentioned.
      String to = "email@tosend.to";

      // Sender's email ID needs to be mentioned
      String from = "email@from.here";
      final String username = "me@myemail.here"; //change accordingly
      final String password = "password_here"; //change accordingly

      // SMTP Address
      String host = "mail.my.site";

      Properties props = new Properties();
      props.put("mail.smtp.auth", "true");
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.host", host);
      props.put("mail.smtp.port", "587");

      // Get the Session object.
      Session session = Session.getInstance(props,
         new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
               return new PasswordAuthentication(username, password);
       }
         });

      try {
       // Create a default MimeMessage object.
       Message message = new MimeMessage(session);
   
       // Set From: header field of the header.
       message.setFrom(new InternetAddress(from));
   
       // Set To: header field of the header.
       message.setRecipients(Message.RecipientType.TO,
               InternetAddress.parse(to));
   
       // Set Subject: header field
       message.setSubject("Testing Subject");
   
       // Now set the actual message
       message.setText("Hello, this is sample for to check send email using JavaMailAPI");

       // Send message
       Transport.send(message);

       System.out.println("Sent message successfully....");
   
      } catch (MessagingException e) {
         throw new RuntimeException(e);
      }
   }

#end if

Since the above is working, I would have thought the following would be the correct way in connecting. Or am I missing a step in the following code ?

B4X:
Sub RunSMTPTest

    Dim smtpServer As String = "mail.xxxxxxxxxx.xxx"
    Dim smtpPort As Int = 587
    Dim user As String = "xxxxx@xxxxxxxxxx.xxx"
    Dim email_password As String = "xxxxxxxxxxxx"

    smtp.Initialize(smtpServer, smtpPort, user, email_password, "smtp")
    smtp.StartTLSMode = True
    smtp.UseSSL = False

    Log("SMTP Initialize Done")

    SendEmail("xxxxx@xxxxxx.xxx", user, "subject test1", "body test 1")

End Sub

Public Sub SendEmail(ToEmail As String, from As String, Subject As String, body As String)
    Log("SendEmail")
    Try
        smtp.To.Add(ToEmail)
        smtp.Sender = from
        smtp.Body = body
        smtp.Subject = Subject
        smtp.Send
    Catch
        Log("Error: SendEmail To - " & ToEmail & " Subject: " & Subject)
        Log(LastException.Message)
    End Try

    wait for SMTP_MessageSent(Success As Boolean)
    ' this is triggered once the email has been sent or failed to be sent
    If Success Then
        Log("eMail Sent OK - To: " & ToEmail & " Subject: " & Subject)
    Else
        Log("eMail Failed to send - To: " & ToEmail & " Subject: " & Subject)
        Log(LastException.Message)
    End If
End Sub
 
Upvote 0
Top