Solved

whats wrong with this Socket Based SMTP function under linux?

Posted on 2006-10-25
8
180 Views
Last Modified: 2010-03-31
Hello,
I have a function I have written which simply delivers an smtp based message to a remote server. This function works perfectly under windows, delivering messages fast and reliably. However, under linux it cannot seem to deliver even 1 message. My thought is that it must have something to do with the network buffers, as it seems to write the data, loop back around and be hanging for a response, the thread blocks because it is waiting for a response from the server. But the server (I have tested this in a dummy program I wrote) doesnt ever receive the command I send it, telling me that the write is not effective or complete. How do I fix this code so that it operates correctly under any OS? Here is the code... the hanging occurs immediately upon the loop after smtpStep == 1...

NOTE: I have already tried simply calling out.flush() to flush the buffers, but it didnt make any difference.

Worth 500 points.

  envelope deliverMessage(envelope e)
    {
      //deliver the message via smtp to the remote mail server
      boolean delivered = false;
      int error = 0;
     
      //if this is a new connection send the HELO line
      if(smtpStep == 0)
      {
          out.println("HELO " + cfg.getValue("server1hostname"));
          smtpStep = 1;
      }
     
      while((!delivered) && (error == 0))
      {
            try
            {
                cfg.writeLog("Get Response - Step: " + smtpStep);
                //wait for the server response
                String response = in.readLine();
               
                cfg.writeLog("Break the response code");
                //break the response into pieces
                String resp[] = response.split(" ");
               
                //if(numdelivered > 1900)
                cfg.writeLog("SMTP: " + response + " ");
               
                //check the response
                int rCode = new Integer(resp[0]).intValue();
               
                if ((200 <= rCode) && (rCode < 300))
                {
                    cfg.writeLog("Good response response code");
                    //good response so continue to the next step
                    if (smtpStep == 1)
                    {
                        //response to helo received, send the mail from command
                        out.println("MAIL FROM: <" + e.from + ">");
                        cfg.writeLog("MAIL FROM: <" + e.from + ">");
                        smtpStep = 2;
                    }
                    else if (smtpStep == 2)
                    {
                        out.println("RCPT TO: <" + e.recipient + ">");
                        cfg.writeLog("To");
                        smtpStep = 3;
                    }
                    else if (smtpStep == 3)
                    {
                        cfg.writeLog("data");
                        out.println("DATA");
                        smtpStep = 4;
                    }
                    else if (smtpStep == 4)
                    {
                        cfg.writeLog("rset");
                        out.println("RSET");
                        smtpStep = 1;
                        delivered = true;
                        ++msgCount;
                    }
                }
                else if (rCode == 354)
                {
                    //send the data
                    cfg.writeLog("send data");
                    out.println(e.message);
                }
                else if (rCode >= 400)
                {   //some sort of bounce
                    cfg.writeLog("bounce");
                    error = rCode;
                    out.println("RSET");
                }
                 
            }
            catch (IOException ex)
            {
                cfg.writeLog("SMTP: Server " + (index+1) + " - " + ex.toString());
            }
         
      }
     
      e.deliveryStatus = error;
      return e;
    }


Thanks,
Rick
0
Comment
Question by:richardsimnett
  • 5
  • 3
8 Comments
 
LVL 14

Expert Comment

by:hoomanv
ID: 17809782
After receiving the 354 response you start writing the message and you ought to end it with <CRLF>.<CRLF>
But I cant see this in your code
0
 
LVL 14

Expert Comment

by:hoomanv
ID: 17809798
OK I assume e.message contains all the required things
0
 
LVL 14

Expert Comment

by:hoomanv
ID: 17809812
Perhaps the PrintStream is not auto-flush
Try out.flush after each println
0
 

Author Comment

by:richardsimnett
ID: 17809935
hoomany,
No 354 isnt the issue, as I said the code delivers mail fine under windows, the issue is that it does not work under linux. You cannot see the <crlf>.<crlf> because the <crlf>.<crlf> is already embedded in the message body.

I have already tried out.flush() after every println already... it does nothing.


Rick
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:richardsimnett
ID: 17809945
Here is a modified version of my code.. I have adjusted two things.. first I moved the HELO line to its appropriate position in the protocol, it wasnt correct in the original code I posted. Also I have plugged in the out.flush() after each println(). Still doesnt work. :\

for some reason I think that the linefeed is not being sent to the remote server, or possibly the whole string. Again I do not know why this doesnt work... its such a trivial issue to have.

New Code:

envelope deliverMessage(envelope e)
    {
      //deliver the message via smtp to the remote mail server
      boolean delivered = false;
      int error = 0;
     
      //if this is a new connection send the HELO line
     
      while((!delivered) && (error == 0))
      {
            try
            {
                cfg.writeLog("Get Response - Step: " + smtpStep);
                //wait for the server response
                String response = in.readLine();
               
                cfg.writeLog("Break the response code");
                //break the response into pieces
                String resp[] = response.split(" ");
               
                //if(numdelivered > 1900)
                cfg.writeLog("SMTP: " + response + " ");
               
                //check the response
                int rCode = new Integer(resp[0]).intValue();
               
                if ((200 <= rCode) && (rCode < 300))
                {
                    cfg.writeLog("Good response response code");
                    //good response so continue to the next step
                    if(smtpStep == 0)
                    {
                        cfg.writeLog("HELO");
                        out.println("HELO " + cfg.getValue("server1hostname"));
                        out.flush();
                        smtpStep = 1;
                    }
                    else if (smtpStep == 1)
                    {
                        //response to helo received, send the mail from command
                        out.println("MAIL FROM: <" + e.from + ">");
                        out.flush();
                        cfg.writeLog("MAIL FROM: <" + e.from + ">");
                        smtpStep = 2;
                    }
                    else if (smtpStep == 2)
                    {
                        out.println("RCPT TO: <" + e.recipient + ">");
                        out.flush();
                        cfg.writeLog("To");
                        smtpStep = 3;
                    }
                    else if (smtpStep == 3)
                    {
                        cfg.writeLog("data");
                        out.flush();
                        out.println("DATA");
                        smtpStep = 4;
                    }
                    else if (smtpStep == 4)
                    {
                        cfg.writeLog("rset");
                       
                        out.println("RSET");
                        out.flush();
                        smtpStep = 1;
                        delivered = true;
                        ++msgCount;
                    }
                }
                else if (rCode == 354)
                {
                    //send the data
                    cfg.writeLog("send data");
                    out.println(e.message);
                    out.flush();
                }
                else if (rCode >= 400)
                {   //some sort of bounce
                    cfg.writeLog("bounce");
                    error = rCode;
                    out.println("RSET");
                    out.flush();
                }
                 
            }
            catch (IOException ex)
            {
                cfg.writeLog("SMTP: Server " + (index+1) + " - " + ex.toString());
            }
         
      }
     
      e.deliveryStatus = error;
      return e;
    }
0
 
LVL 14

Accepted Solution

by:
hoomanv earned 500 total points
ID: 17809954
Try manually entering CRLF at the end of each command
use print instead of println
out.print("\r\n");
0
 

Author Comment

by:richardsimnett
ID: 17810021
hoomanv,

Well that last suggestion sure worked. So strange that the println command under windows does not behave the same way under linux but it works now so what the heck right?

I changed the code a bit, made a function called smtpWrite() which condensed repititious lines of code. Here is the final code to look at:

envelope deliverMessage(envelope e)
    {
      //deliver the message via smtp to the remote mail server
      boolean delivered = false;
      int error = 0;
     
      while((!delivered) && (error == 0))
      {
            try
            {
                //cfg.writeLog("Get Response - Step: " + smtpStep);
                //wait for the server response
                String response = in.readLine();
               
                //cfg.writeLog("Break the response code");
                //break the response into pieces
                String resp[] = response.split(" ");
               
                //if(numdelivered > 1900)
                //cfg.writeLog("SMTP: " + response + " ");
               
                //check the response
                int rCode = new Integer(resp[0]).intValue();
               
                if ((200 <= rCode) && (rCode < 300))
                {
                    //cfg.writeLog("Good response response code");
                    //good response so continue to the next step
                    if(smtpStep == 0)
                    {
                        smtpWrite("HELO " + cfg.getValue("server1hostname"));
                        smtpStep = 1;
                    }
                    else if (smtpStep == 1)
                    {
                        //response to helo received, send the mail from command
                        smtpWrite("MAIL FROM: <" + e.from + ">");
                        smtpStep = 2;
                    }
                    else if (smtpStep == 2)
                    {
                        smtpWrite("RCPT TO: <" + e.recipient + ">");
                        smtpStep = 3;
                    }
                    else if (smtpStep == 3)
                    {
                        smtpWrite("DATA");
                        smtpStep = 4;
                    }
                    else if (smtpStep == 4)
                    {
                        smtpWrite("RSET");
                        smtpStep = 1;
                        delivered = true;
                        ++msgCount;
                    }
                }
                else if (rCode == 354)
                {
                    //send the data
                    //cfg.writeLog("send data");
                    smtpWrite(e.message);
                }
                else if (rCode >= 400)
                {   //some sort of bounce
                    cfg.writeLog("bounce");
                    error = rCode;
                    smtpWrite("RSET");
                }
                 
            }
            catch (IOException ex)
            {
                cfg.writeLog("SMTP: Server " + (index+1) + " - " + ex.toString());
            }
         
      }
     
      e.deliveryStatus = error;
      return e;
    }
   
    void smtpWrite(String output)
    {
        //cfg.writeLog("SMTP: " + output);
        out.print(output);
        out.print("\r\n");
        out.flush();
    }


Thanks for the help!

Rick
0
 
LVL 14

Expert Comment

by:hoomanv
ID: 17810039
New line in windows is determined by CRLF
In linux only a LF is used
And in MAC a CR
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
base64 decode encode 12 122
github account with ecipse 1 42
HSSFWorkbook cannot be resolved error 10 50
hibernate insert example 13 14
An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

895 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now