using wxSocket for a simple SMTP e-mail client Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

using wxSocket for a simple SMTP e-mail client

Post by ciammarica » Tue Jul 04, 2006 7:54 am

Hi all!
I'm new here... i've just begun programming with wxWidgets, i'm trying to develop a simple SMTP client, for sending e-mail by SMTP, of course :)
i create the GUI, and i've associated to the wxButton "Send" the event of connecting to the SMTP server and beginning to exchange messages with the server. Everything is ok until the first command sent to the server (HELO), the server answers correctly (message 250), but when the program sends the second command, the server replies with error 421 and closes connection. Where's the error? :(
I'm new to wxWidgets and socket programming, so the code is surely full of mistakes... for now the SMTP server is not chosen by the user (it's a Yahoo server). Please I need help!
Sorry for my bad English, i'm a stranger :)
I post the full code, so you could compile it and see by yourself what happens...
If you please can help me finding where the error is... :) Thanks!

Code: Select all

#include "wx/wxprec.h"

#include <math.h>
#include <wx/notebook.h>
#include <wx/textfile.h>
#include <wx/textctrl.h>
#include <wx/socket.h>

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#define PORT 25

// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------

class MyApp : public wxApp
{
 public:

    virtual bool OnInit();
};


class MyFrame : public wxFrame
{
 public:
 
    MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
            long style = wxDEFAULT_FRAME_STYLE);
 
    void OnClose(wxCommandEvent &event);
    void OnClear(wxCommandEvent &event);
    void OnSend(wxCommandEvent &event); 
    void OnQuit(wxCommandEvent &event);
    void OnIdle(wxIdleEvent &event);
    void OnAbout(wxCommandEvent &event);
    void OnSocketEvent(wxSocketEvent &event);

private:
    
    wxToolBar* mainToolBar;
   
    wxTextCtrl* serverInput;
    wxTextCtrl* mailFromInput;
    wxTextCtrl* rcptToInput;
    wxTextCtrl* dataInput;
    wxTextCtrl* statusInput;
    
    wxButton* sendButton;
    wxButton* cancelButton;
    wxButton* clearButton;
        
    wxMenu* menuFile;
    
    wxPanel* panel;
    
    DECLARE_EVENT_TABLE()
};

// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

enum
{
 Minimal_Quit = 1,
 Minimal_About = wxID_ABOUT,
 
 ID_ServerInput = 2,
 ID_MailFromInput = 3,
 ID_RcptToInput = 4,
 ID_DataInput = 5,
 
 ID_SendButton = 6,
 ID_CancelButton = 7,
 ID_ClearButton = 8,
 
 SOCKET_ID = 10,
};

// ----------------------------------------------------------------------------
// event tables and other macros for wxWindows
// ----------------------------------------------------------------------------

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    
    EVT_MENU(Minimal_Quit,  MyFrame::OnQuit)
    EVT_MENU(Minimal_About, MyFrame::OnAbout)
    
    EVT_BUTTON(ID_CancelButton, MyFrame::OnClose)
    EVT_BUTTON(ID_SendButton, MyFrame::OnSend)
    EVT_BUTTON(ID_ClearButton, MyFrame::OnClear)
    
    EVT_SOCKET(SOCKET_ID, MyFrame::OnSocketEvent)
    
    EVT_IDLE(MyFrame::OnIdle)

END_EVENT_TABLE()

IMPLEMENT_APP(MyApp)


bool MyApp::OnInit()
{
 MyFrame *frame = new MyFrame(_T("SMTP Client"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & (wxCAPTION | wxRESIZE_BOX | wxMAXIMIZE_BOX));
                                 
 frame->Centre(wxBOTH);                             
                                 
 frame->Show(TRUE);

 return TRUE;
}

// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
       : wxFrame(NULL, -1, title, pos, size, style)
{
 #if wxUSE_MENUS

 menuFile = new wxMenu;

 wxMenu *helpMenu = new wxMenu;
 helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));

 menuFile->Append(wxID_OPEN, _T("&Open\tAlt-O"), _T("Open an input text file"));
 menuFile->Append(wxID_SAVE, _T("&Save\tAlt-S"), _T("Save output on a text file"));
 menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
    
 menuFile->Enable(wxID_SAVE, FALSE);

 wxMenuBar *menuBar = new wxMenuBar();
 menuBar->Append(menuFile, _T("&File"));
 menuBar->Append(helpMenu, _T("&Help"));

 SetMenuBar(menuBar);
    
 #endif // wxUSE_MENUS
  
 panel = new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize);
 
 serverInput = new wxTextCtrl(panel, ID_ServerInput, "", wxDefaultPosition, wxSize(200, 20));
 wxStaticText* serverLabel = new wxStaticText(panel, -1, "SMTP Server:", wxDefaultPosition, wxDefaultSize);
 
 mailFromInput = new wxTextCtrl(panel, ID_MailFromInput, "", wxDefaultPosition, wxSize(200, 20));
 wxStaticText* mailFromLabel = new wxStaticText(panel, -1, "Mail From:      ", wxDefaultPosition, wxDefaultSize);
 
 rcptToInput = new wxTextCtrl(panel, ID_RcptToInput, "", wxDefaultPosition, wxSize(200, 20));
 wxStaticText* rcptToLabel = new wxStaticText(panel, -1, "Rcpt To:        ", wxDefaultPosition, wxDefaultSize);
 
 dataInput = new wxTextCtrl(panel, ID_DataInput, "", wxDefaultPosition, wxSize(200, 100), wxTE_MULTILINE);
 wxStaticText* dataLabel = new wxStaticText(panel, -1, "E-mail Text:    ", wxDefaultPosition, wxDefaultSize);
 
 statusInput = new wxTextCtrl(panel, -1, "Not connected yet.\nPress \"Send\" when ready...", wxDefaultPosition, wxSize(200, 70), wxTE_MULTILINE);
 statusInput->SetEditable(FALSE);
 
 sendButton = new wxButton(panel, ID_SendButton, "Send", wxDefaultPosition, wxDefaultSize);
 cancelButton = new wxButton(panel, ID_CancelButton, "Exit", wxDefaultPosition, wxDefaultSize);
 clearButton = new wxButton(panel, ID_ClearButton, "Clear All", wxDefaultPosition, wxDefaultSize);
 
 wxFlexGridSizer* frameSizer = new wxFlexGridSizer(3, 1, 20, 20);
 
 wxFlexGridSizer* commandsSizer = new wxFlexGridSizer(6, 1, 10, 10);
 
 wxBoxSizer* serverSizer = new wxBoxSizer(wxHORIZONTAL);
 
 serverSizer->Add(10, 10);
 serverSizer->Add(serverLabel, 0, wxALIGN_CENTER);
 serverSizer->Add(10, 10);
 serverSizer->Add(serverInput, 0, wxALIGN_CENTER);
 serverSizer->Add(10, 10);
 
 wxBoxSizer* mailFromSizer = new wxBoxSizer(wxHORIZONTAL);
 
 mailFromSizer->Add(10, 10);
 mailFromSizer->Add(mailFromLabel, 0, wxALIGN_CENTER);
 mailFromSizer->Add(10, 10);
 mailFromSizer->Add(mailFromInput, 0, wxALIGN_CENTER);
 mailFromSizer->Add(10, 10);
 
 wxBoxSizer* rcptToSizer = new wxBoxSizer(wxHORIZONTAL);
 
 rcptToSizer->Add(10, 10);
 rcptToSizer->Add(rcptToLabel, 0, wxALIGN_CENTER);
 rcptToSizer->Add(10, 10);
 rcptToSizer->Add(rcptToInput, 0, wxALIGN_CENTER);
 rcptToSizer->Add(10, 10);
 
 wxBoxSizer* dataSizer = new wxBoxSizer(wxHORIZONTAL);
 
 dataSizer->Add(10, 10);
 dataSizer->Add(dataLabel, 0, wxALIGN_CENTER);
 dataSizer->Add(10, 10);
 dataSizer->Add(dataInput, 0, wxALIGN_CENTER);
 dataSizer->Add(10, 10);
 
 wxStaticBox* statusBox = new wxStaticBox(panel, -1, "Status", wxDefaultPosition, wxDefaultSize);
 
 wxStaticBoxSizer* statusBoxSizer = new wxStaticBoxSizer(statusBox, wxHORIZONTAL);
 
 wxBoxSizer* statusSizer = new wxBoxSizer(wxHORIZONTAL);
 
 statusSizer->Add(10, 10);
 statusSizer->Add(statusInput, 1, wxGROW | wxALIGN_CENTER);
 statusSizer->Add(10, 10);
 
 statusBoxSizer->Add(statusSizer, 1, wxALIGN_CENTER);
 
 commandsSizer->Add(10, 10);
 commandsSizer->Add(serverSizer, 1, wxGROW | wxALIGN_CENTER);
 commandsSizer->Add(mailFromSizer, 1, wxGROW | wxALIGN_CENTER);
 commandsSizer->Add(rcptToSizer, 1, wxGROW | wxALIGN_CENTER);
 commandsSizer->Add(dataSizer, 1, wxGROW | wxALIGN_CENTER);
 commandsSizer->Add(statusBoxSizer, 1, wxGROW | wxALIGN_CENTER);
 
 wxBoxSizer* buttonsSizer = new wxBoxSizer(wxHORIZONTAL);
 
 buttonsSizer->Add(cancelButton, 0, wxALIGN_CENTER);
 buttonsSizer->Add(clearButton, 0, wxALIGN_CENTER);
 buttonsSizer->Add(sendButton, 0, wxALIGN_CENTER);
 
 frameSizer->Add(commandsSizer, 1, wxGROW | wxALIGN_CENTER);
 frameSizer->Add(buttonsSizer, 0, wxALIGN_CENTER);
 frameSizer->Add(10, 10);
 
 frameSizer->Fit(this);
 
 CenterOnParent(wxBOTH);
 
 SetSizer(frameSizer);
 SetAutoLayout(TRUE);
 Layout();
 
 SetSize(300, 430);

 #if wxUSE_STATUSBAR
 
 CreateStatusBar(2);
 SetStatusText(_T("Ready..."));
    
 #endif
}


void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
 Close(TRUE);
}


void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
    wxString msg;
    msg.Printf(_T("\"SMTP Client\"\n\n")
               _T("- Author: Stefano Pace\n\n")
               _T("- Compiled with:\n\n")
               _T("Dev-C++ v.4.9.9.2\n\n")
               _T("- GUI toolkit:\n\n")
               _T("%s"), wxVERSION_STRING);

    wxMessageBox(msg, _T("About SMTP Client"), wxOK | wxICON_INFORMATION, this);
}



void MyFrame::OnIdle(wxIdleEvent &event)
{
 //SetStatusText("Ready...");
}     


void MyFrame::OnClose(wxCommandEvent &event)
{
 this->Destroy();
}     


void MyFrame::OnClear(wxCommandEvent &event)
{
 serverInput->SetValue("");
 mailFromInput->SetValue("");
 rcptToInput->SetValue("");
 dataInput->SetValue("");
 statusInput->SetValue("Not connected yet.\nPress \"Send\" when ready...");
 
 statusInput->Enable(FALSE);
 menuFile->Enable(wxID_SAVE, FALSE);
}    


void MyFrame::OnSend(wxCommandEvent& event)
{    
 wxIPV4address addr;
 addr.Hostname(wxT("mx2.mail.yahoo.com"));
 addr.Service(PORT);

 // Create the socket
 wxSocketClient* Socket = new wxSocketClient();

 // Set up the event handler and subscribe to most events
 Socket->SetEventHandler(*this, SOCKET_ID);
 Socket->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG | wxSOCKET_OUTPUT_FLAG);
 Socket->Notify(TRUE);

 // Wait for the connection event
 Socket->Connect(addr, FALSE);
 //Socket->WaitOnConnect(10);
 
 /*if (Socket->IsConnected())
         {          
          
         } 
 else
         {
          Socket->Close();
         }*/
}


void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
 // The socket that had the event
 wxSocketBase* sock = event.GetSocket();
 
 // Common buffer shared by the events
 char buf[100] = "";
 
 switch(event.GetSocketEvent())
          {
           case wxSOCKET_CONNECTION:
                   {                                         
                    SetStatusText("Connected to SMTP server...");
                    statusInput->AppendText("\n\nConnected to SMTP server...");

                    break;
                   }
                   
           case wxSOCKET_INPUT:
                   {                               
                    char nextMessage[50] = "";
                    
                    static int count = 0;
                               
                    sock->Read(buf, sizeof(buf));
                    
                    statusInput->AppendText("\n");
                    statusInput->AppendText(buf);
                    
                    const wxChar* temp;
                    
                    // next command choice...
                    switch(count)
                              {
                               case 0:
                                      {
                                                  
                                       strcpy(nextMessage, "HELO SMTP Client v1.0\n");
                                       
                                       sock->Write(nextMessage, sizeof(nextMessage));
                                       
                                       
                                       break;
                                      }
                                      
                               case 1:
                                      {                                       
                                       temp = mailFromInput->GetValue();
                                       
                                       sprintf(nextMessage, "MAIL FROM:<%s>\n", temp);
                                       
                                       sock->Write(nextMessage, sizeof(nextMessage));
                                      
                                      
                                       break;                   
                                      }
                                      
                               case 2:
                                      {
                                       temp = rcptToInput->GetValue();
                                       
                                       sprintf(nextMessage, "RCPT TO:<%s>\n", temp);
                                                                             
                                       sock->Write(nextMessage, sizeof(nextMessage));
                                      
                                      
                                       break;
                                      }
                                      
                               case 3:
                                      {                                      
                                       temp = dataInput->GetValue();
                                       
                                       sprintf(nextMessage, "DATA\n%s\n.\n", temp);
                                      
                                       sock->Write(nextMessage, sizeof(nextMessage));
                                                                                                
                                       break;
                                      }
                                      
                               case 4:
                                      {
                                       strcpy(nextMessage, "QUIT\n");
                                       sock->Write(nextMessage, sizeof(nextMessage));
                                       
                                    
                                       break;
                                      }
                              }
                                                  
                    statusInput->AppendText("\n");
                    statusInput->AppendText(nextMessage);
                    
                    count++;
                    
                    break;
                   }
                   
           // The server hangs up after sending the data

           case wxSOCKET_LOST:
                   {
                    sock->Destroy();
                    
                    statusInput->AppendText("\nConnection lost.");
                    SetStatusText("Connection lost...");
                                        
                    wxString msg;
                    msg.Printf(_T("Connection lost!"));
                    wxMessageBox(msg, _T("Error"), wxOK | wxICON_ERROR);
                    
                    break;
                   }
                   
           case wxSOCKET_OUTPUT:
                   {                                
                    break;
                   }
          }
}

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Tue Jul 04, 2006 9:35 am

Now i've changed the source code in a better way, but the problem persists :(
That's the code:

Code: Select all

#include "wx/wxprec.h"

#include <math.h>
#include <wx/notebook.h>
#include <wx/textfile.h>
#include <wx/textctrl.h>
#include <wx/socket.h>

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#define PORT 25

// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------

class MyApp : public wxApp
{
 public:

    virtual bool OnInit();
};


class MyFrame : public wxFrame
{
 public:
 
    MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
            long style = wxDEFAULT_FRAME_STYLE);
 
    void OnClose(wxCommandEvent &event);
    void OnClear(wxCommandEvent &event);
    void OnSend(wxCommandEvent &event); 
    void OnQuit(wxCommandEvent &event);
    void OnIdle(wxIdleEvent &event);
    void OnAbout(wxCommandEvent &event);
    void OnSocketEvent(wxSocketEvent &event);

private:
    
    wxToolBar* mainToolBar;
   
    wxTextCtrl* serverInput;
    wxTextCtrl* mailFromInput;
    wxTextCtrl* rcptToInput;
    wxTextCtrl* dataInput;
    wxTextCtrl* statusInput;
    
    wxButton* sendButton;
    wxButton* cancelButton;
    wxButton* clearButton;
        
    wxMenu* menuFile;
    
    wxPanel* panel;
    
    DECLARE_EVENT_TABLE()
};

// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

enum
{
 Minimal_Quit = 1,
 Minimal_About = wxID_ABOUT,
 
 ID_ServerInput = 2,
 ID_MailFromInput = 3,
 ID_RcptToInput = 4,
 ID_DataInput = 5,
 
 ID_SendButton = 6,
 ID_CancelButton = 7,
 ID_ClearButton = 8,
 
 SOCKET_ID = 10,
};

// ----------------------------------------------------------------------------
// event tables and other macros for wxWindows
// ----------------------------------------------------------------------------

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    
    EVT_MENU(Minimal_Quit,  MyFrame::OnQuit)
    EVT_MENU(Minimal_About, MyFrame::OnAbout)
    
    EVT_BUTTON(ID_CancelButton, MyFrame::OnClose)
    EVT_BUTTON(ID_SendButton, MyFrame::OnSend)
    EVT_BUTTON(ID_ClearButton, MyFrame::OnClear)
    
    EVT_SOCKET(SOCKET_ID, MyFrame::OnSocketEvent)
    
    EVT_IDLE(MyFrame::OnIdle)

END_EVENT_TABLE()

IMPLEMENT_APP(MyApp)


bool MyApp::OnInit()
{
 MyFrame *frame = new MyFrame(_T("SMTP Client"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & (wxCAPTION | wxRESIZE_BOX | wxMAXIMIZE_BOX));
                                 
 frame->Centre(wxBOTH);                             
                                 
 frame->Show(TRUE);

 return TRUE;
}

// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
       : wxFrame(NULL, -1, title, pos, size, style)
{
 #if wxUSE_MENUS

 menuFile = new wxMenu;

 wxMenu *helpMenu = new wxMenu;
 helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));

 menuFile->Append(wxID_OPEN, _T("&Open\tAlt-O"), _T("Open an input text file"));
 menuFile->Append(wxID_SAVE, _T("&Save\tAlt-S"), _T("Save output on a text file"));
 menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
    
 menuFile->Enable(wxID_SAVE, FALSE);

 wxMenuBar *menuBar = new wxMenuBar();
 menuBar->Append(menuFile, _T("&File"));
 menuBar->Append(helpMenu, _T("&Help"));

 SetMenuBar(menuBar);
    
 #endif // wxUSE_MENUS
  
 panel = new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize);
 
 serverInput = new wxTextCtrl(panel, ID_ServerInput, "", wxDefaultPosition, wxSize(200, 20));
 wxStaticText* serverLabel = new wxStaticText(panel, -1, "SMTP Server:", wxDefaultPosition, wxDefaultSize);
 
 mailFromInput = new wxTextCtrl(panel, ID_MailFromInput, "", wxDefaultPosition, wxSize(200, 20));
 wxStaticText* mailFromLabel = new wxStaticText(panel, -1, "Mail From:      ", wxDefaultPosition, wxDefaultSize);
 
 rcptToInput = new wxTextCtrl(panel, ID_RcptToInput, "", wxDefaultPosition, wxSize(200, 20));
 wxStaticText* rcptToLabel = new wxStaticText(panel, -1, "Rcpt To:        ", wxDefaultPosition, wxDefaultSize);
 
 dataInput = new wxTextCtrl(panel, ID_DataInput, "", wxDefaultPosition, wxSize(200, 100), wxTE_MULTILINE);
 wxStaticText* dataLabel = new wxStaticText(panel, -1, "E-mail Text:    ", wxDefaultPosition, wxDefaultSize);
 
 statusInput = new wxTextCtrl(panel, -1, "Not connected yet.\nPress \"Send\" when ready...", wxDefaultPosition, wxSize(200, 70), wxTE_MULTILINE);
 statusInput->SetEditable(FALSE);
 
 sendButton = new wxButton(panel, ID_SendButton, "Send", wxDefaultPosition, wxDefaultSize);
 cancelButton = new wxButton(panel, ID_CancelButton, "Exit", wxDefaultPosition, wxDefaultSize);
 clearButton = new wxButton(panel, ID_ClearButton, "Clear All", wxDefaultPosition, wxDefaultSize);
 
 wxFlexGridSizer* frameSizer = new wxFlexGridSizer(3, 1, 20, 20);
 
 wxFlexGridSizer* commandsSizer = new wxFlexGridSizer(6, 1, 10, 10);
 
 wxBoxSizer* serverSizer = new wxBoxSizer(wxHORIZONTAL);
 
 serverSizer->Add(10, 10);
 serverSizer->Add(serverLabel, 0, wxALIGN_CENTER);
 serverSizer->Add(10, 10);
 serverSizer->Add(serverInput, 0, wxALIGN_CENTER);
 serverSizer->Add(10, 10);
 
 wxBoxSizer* mailFromSizer = new wxBoxSizer(wxHORIZONTAL);
 
 mailFromSizer->Add(10, 10);
 mailFromSizer->Add(mailFromLabel, 0, wxALIGN_CENTER);
 mailFromSizer->Add(10, 10);
 mailFromSizer->Add(mailFromInput, 0, wxALIGN_CENTER);
 mailFromSizer->Add(10, 10);
 
 wxBoxSizer* rcptToSizer = new wxBoxSizer(wxHORIZONTAL);
 
 rcptToSizer->Add(10, 10);
 rcptToSizer->Add(rcptToLabel, 0, wxALIGN_CENTER);
 rcptToSizer->Add(10, 10);
 rcptToSizer->Add(rcptToInput, 0, wxALIGN_CENTER);
 rcptToSizer->Add(10, 10);
 
 wxBoxSizer* dataSizer = new wxBoxSizer(wxHORIZONTAL);
 
 dataSizer->Add(10, 10);
 dataSizer->Add(dataLabel, 0, wxALIGN_CENTER);
 dataSizer->Add(10, 10);
 dataSizer->Add(dataInput, 0, wxALIGN_CENTER);
 dataSizer->Add(10, 10);
 
 wxStaticBox* statusBox = new wxStaticBox(panel, -1, "Status", wxDefaultPosition, wxDefaultSize);
 
 wxStaticBoxSizer* statusBoxSizer = new wxStaticBoxSizer(statusBox, wxHORIZONTAL);
 
 wxBoxSizer* statusSizer = new wxBoxSizer(wxHORIZONTAL);
 
 statusSizer->Add(10, 10);
 statusSizer->Add(statusInput, 1, wxGROW | wxALIGN_CENTER);
 statusSizer->Add(10, 10);
 
 statusBoxSizer->Add(statusSizer, 1, wxALIGN_CENTER);
 
 commandsSizer->Add(10, 10);
 commandsSizer->Add(serverSizer, 1, wxGROW | wxALIGN_CENTER);
 commandsSizer->Add(mailFromSizer, 1, wxGROW | wxALIGN_CENTER);
 commandsSizer->Add(rcptToSizer, 1, wxGROW | wxALIGN_CENTER);
 commandsSizer->Add(dataSizer, 1, wxGROW | wxALIGN_CENTER);
 commandsSizer->Add(statusBoxSizer, 1, wxGROW | wxALIGN_CENTER);
 
 wxBoxSizer* buttonsSizer = new wxBoxSizer(wxHORIZONTAL);
 
 buttonsSizer->Add(cancelButton, 0, wxALIGN_CENTER);
 buttonsSizer->Add(clearButton, 0, wxALIGN_CENTER);
 buttonsSizer->Add(sendButton, 0, wxALIGN_CENTER);
 
 frameSizer->Add(commandsSizer, 1, wxGROW | wxALIGN_CENTER);
 frameSizer->Add(buttonsSizer, 0, wxALIGN_CENTER);
 frameSizer->Add(10, 10);
 
 frameSizer->Fit(this);
 
 CenterOnParent(wxBOTH);
 
 SetSizer(frameSizer);
 SetAutoLayout(TRUE);
 Layout();
 
 SetSize(300, 430);

 #if wxUSE_STATUSBAR
 
 CreateStatusBar(2);
 SetStatusText(_T("Ready..."));
    
 #endif
}


void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
 Close(TRUE);
}


void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
    wxString msg;
    msg.Printf(_T("\"SMTP Client\"\n\n")
               _T("- Author: Stefano Pace\n\n")
               _T("- Compiled with:\n\n")
               _T("Dev-C++ v.4.9.9.2\n\n")
               _T("- GUI toolkit:\n\n")
               _T("%s"), wxVERSION_STRING);

    wxMessageBox(msg, _T("About SMTP Client"), wxOK | wxICON_INFORMATION, this);
}


void MyFrame::OnIdle(wxIdleEvent &event)
{
 //SetStatusText("Ready...");
}     


void MyFrame::OnClose(wxCommandEvent &event)
{
 this->Destroy();
}     


void MyFrame::OnClear(wxCommandEvent &event)
{
 serverInput->SetValue("");
 mailFromInput->SetValue("");
 rcptToInput->SetValue("");
 dataInput->SetValue("");
 statusInput->SetValue("Not connected yet.\nPress \"Send\" when ready...");
 
 menuFile->Enable(wxID_SAVE, FALSE);
}    


void MyFrame::OnSend(wxCommandEvent& event)
{    
 wxIPV4address addr;
 addr.Hostname(wxT("max2.mail.yahoo.com"));
 addr.Service(PORT);

 // Create the socket
 wxSocketClient* Socket = new wxSocketClient();

 // Set up the event handler and subscribe to most events
 Socket->SetEventHandler(*this, SOCKET_ID);
 Socket->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG | wxSOCKET_OUTPUT_FLAG);
 Socket->Notify(TRUE);

 // Wait for the connection event
 Socket->Connect(addr, FALSE);
 Socket->WaitOnConnect(10);
 
 if (Socket->IsConnected())
         {          
          Socket->Write("HELO SMTP Client v1.0 beta\n", 28);
          
          Socket->WaitForRead(2);
          
          //Socket->Write("MAIL FROM:<[email protected]>\n", 33);
          
          //Socket->WaitForRead(2);
          
          //Socket->Write("RCPT TO:<[email protected]>\n", 33);
          
          //Socket->WaitForRead(2);
         } 
 else
         {
          wxString msg;
          msg.Printf(_T("closing socket"));
          wxMessageBox(msg, _T("Error"), wxOK | wxICON_ERROR);
                                  
          Socket->Close();
         }
}


void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
 // The socket that had the event
 wxSocketBase* sock = event.GetSocket();
 
 // Common buffer shared by the events
 char buf[100] = "";
 
 switch(event.GetSocketEvent())
          {
           case wxSOCKET_CONNECTION:
                   {                    
                    wxString msg;
                    msg.Printf(_T("connected to server"));
                    wxMessageBox(msg, _T("Error"), wxOK | wxICON_ERROR);
                                        
                    SetStatusText("Connected to SMTP server...");
                    statusInput->AppendText("\n\nConnected to SMTP server...");

                    break;
                   }
                   
           case wxSOCKET_INPUT:
                   {         
                    sock->Read(buf, sizeof(buf));
                    
                    wxString msg;
                    msg.Printf(_T("receiving %s from server"), buf);
                    wxMessageBox(msg, _T("Error"), wxOK | wxICON_ERROR);
                    
                    statusInput->AppendText("\n");
                    statusInput->AppendText(buf);
                    
                    break;
                   }
                   
           // The server hangs up after sending the data

           case wxSOCKET_LOST:
                   {
                    sock->Destroy();
                    
                    statusInput->AppendText("\nConnection lost.");
                    SetStatusText("Connection lost...");
                                        
                    wxString msg;
                    msg.Printf(_T("Connection lost!"));
                    wxMessageBox(msg, _T("Error"), wxOK | wxICON_ERROR);
                    
                    break;
                   }
                   
           case wxSOCKET_OUTPUT:
                   {            
                    break;
                   }
          }
}
if i de-comment the instructions

//Socket->Write("MAIL FROM:<[email protected]>\n", 33);
//Socket->WaitForRead(2);
//Socket->Write("RCPT TO:<[email protected]>\n", 33);
//Socket->WaitForRead(2);

the server replies with an error, while if i leave just the first command (the one with the HELO message) everything is ok.
I've no idea about the source of the problem!

phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 » Tue Jul 04, 2006 10:49 am

I think there is already a wxSMTP. Search the forum or the check the wxCode page.

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Tue Jul 04, 2006 12:12 pm

yes, i've already searched the forum, but i don't want to use wxSMTP or wxEmail or other high level classes.
I need to use sockets, and i just wanted to understand why my method isn't working...

jb_coder
Super wx Problem Solver
Super wx Problem Solver
Posts: 267
Joined: Mon Oct 18, 2004 10:55 am

Post by jb_coder » Tue Jul 04, 2006 3:19 pm

Even if you don't use the wxSTMP or wxEmail classes, looking at the code to those classes might help you understand how you might be able to avoid this problem. They probably use wxSocket in the code as well and may have also had to fix this problem in those classes.

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Tue Jul 04, 2006 6:36 pm

however i've already read all posts about this argument, nothing useful found :(

User avatar
AcidLacedPenguiN
Knows some wx things
Knows some wx things
Posts: 35
Joined: Wed May 17, 2006 4:41 pm
Location: Sunny Canada

Post by AcidLacedPenguiN » Tue Jul 04, 2006 6:47 pm

although I don't have any useful input :_( I'd just like to say that your code is formatted beautifully, if my higher ups coded like you, my job would be so much easier :P
cheers.

Ian

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Wed Jul 05, 2006 6:49 am

AcidLacedPenguiN wrote:although I don't have any useful input :_( I'd just like to say that your code is formatted beautifully, if my higher ups coded like you, my job would be so much easier :P
Thank you very much! :) :) :)

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Wed Jul 05, 2006 7:38 am

I've implemented a simple, little server with "echo" function, so that everything is sent to the server by a client is printed on the server and then is sent back to the client.
I've discovered that all messages arrive correctly to the server, and are sent back correctly to the client! :(
So where is the problem? why SMTP servers don't recognize these commands or give me strange errors? :( :shock: :cry:
Here follows the server source code...
Of course, to use the client's code with this server you must change the #define PORT 25 to #define PORT 3457 (same as server) and the address to "localhost"! (so the correct instrucion will be addr.Hostname(wxT("localhost")); )

Code: Select all

#include "wx/wxprec.h"

#include <math.h>
#include <wx/notebook.h>
#include <wx/textfile.h>
#include <wx/textctrl.h>
#include <wx/socket.h>

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#define PORT 3457

// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------

class MyApp : public wxApp
{
 public:

    virtual bool OnInit();
};


class MyFrame : public wxFrame
{
 public:
 
    MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
            long style = wxDEFAULT_FRAME_STYLE);
 
    void OnClose(wxCommandEvent &event);
    void OnClear(wxCommandEvent &event);
    void OnStart(wxCommandEvent &event); 
    void OnQuit(wxCommandEvent &event);
    void OnIdle(wxIdleEvent &event);
    void OnAbout(wxCommandEvent &event);
    void OnSocketEvent(wxSocketEvent &event);
    void OnServerEvent(wxSocketEvent &event);

private:
    
    wxTextCtrl* statusInput;
    
    wxButton* startButton;
    wxButton* cancelButton;
    wxButton* clearButton;
        
    wxMenu* menuFile;
    
    wxPanel* panel;
    
    wxSocketServer* serverSock;
    
    DECLARE_EVENT_TABLE()
};

// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

enum
{
 Minimal_Quit = 1,
 Minimal_About = wxID_ABOUT,
 
 ID_StartButton = 3,
 ID_CancelButton = 4,
 ID_ClearButton = 5,
 
 SOCKET_ID = 6,
 SERVER_ID = 7,
};

// ----------------------------------------------------------------------------
// event tables and other macros for wxWindows
// ----------------------------------------------------------------------------

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    
    EVT_MENU(Minimal_Quit,  MyFrame::OnQuit)
    EVT_MENU(Minimal_About, MyFrame::OnAbout)
    
    EVT_BUTTON(ID_CancelButton, MyFrame::OnClose)
    EVT_BUTTON(ID_StartButton, MyFrame::OnStart)
    EVT_BUTTON(ID_ClearButton, MyFrame::OnClear)
    
    EVT_SOCKET(SOCKET_ID, MyFrame::OnSocketEvent)
    EVT_SOCKET(SERVER_ID, MyFrame::OnServerEvent)
    
    EVT_IDLE(MyFrame::OnIdle)

END_EVENT_TABLE()

IMPLEMENT_APP(MyApp)

// ============================================================================
// implementation
// ============================================================================

bool MyApp::OnInit()
{
 MyFrame *frame = new MyFrame(_T("Simple Echo Server"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & (wxCAPTION | wxRESIZE_BOX | wxMAXIMIZE_BOX));
                                 
 frame->Centre(wxBOTH);                             
                                 
 frame->Show(TRUE);

 return TRUE;
}

// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
       : wxFrame(NULL, -1, title, pos, size, style)
{
 #if wxUSE_MENUS

 menuFile = new wxMenu;

 wxMenu *helpMenu = new wxMenu;
 helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));

 menuFile->Append(wxID_OPEN, _T("&Open\tAlt-O"), _T("Open an input text file"));
 menuFile->Append(wxID_SAVE, _T("&Save\tAlt-S"), _T("Save output on a text file"));
 menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
    
 menuFile->Enable(wxID_SAVE, FALSE);

 wxMenuBar *menuBar = new wxMenuBar();
 menuBar->Append(menuFile, _T("&File"));
 menuBar->Append(helpMenu, _T("&Help"));

 SetMenuBar(menuBar);
    
 #endif // wxUSE_MENUS
  
 panel = new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize);
 
 statusInput = new wxTextCtrl(panel, -1, "Hi, I'm the Server!", wxDefaultPosition, wxSize(200, 70), wxTE_MULTILINE);
 statusInput->SetEditable(FALSE);
 
 startButton = new wxButton(panel, ID_StartButton, "Start", wxDefaultPosition, wxDefaultSize);
 cancelButton = new wxButton(panel, ID_CancelButton, "Exit", wxDefaultPosition, wxDefaultSize);
 clearButton = new wxButton(panel, ID_ClearButton, "Clear All", wxDefaultPosition, wxDefaultSize);
 
 wxFlexGridSizer* frameSizer = new wxFlexGridSizer(3, 1, 20, 20);
 
 wxFlexGridSizer* commandsSizer = new wxFlexGridSizer(2, 1, 10, 10);
  
 wxStaticBox* statusBox = new wxStaticBox(panel, -1, "Status", wxDefaultPosition, wxDefaultSize);
 
 wxStaticBoxSizer* statusBoxSizer = new wxStaticBoxSizer(statusBox, wxHORIZONTAL);
 
 wxBoxSizer* statusSizer = new wxBoxSizer(wxHORIZONTAL);
 
 statusSizer->Add(10, 10);
 statusSizer->Add(statusInput, 1, wxGROW | wxALIGN_CENTER);
 statusSizer->Add(10, 10);
 
 statusBoxSizer->Add(statusSizer, 1, wxALIGN_CENTER);
 
 commandsSizer->Add(10, 10);
 commandsSizer->Add(statusBoxSizer, 1, wxGROW | wxALIGN_CENTER);
 
 wxBoxSizer* buttonsSizer = new wxBoxSizer(wxHORIZONTAL);
 
 buttonsSizer->Add(cancelButton, 0, wxALIGN_CENTER);
 buttonsSizer->Add(clearButton, 0, wxALIGN_CENTER);
 buttonsSizer->Add(startButton, 0, wxALIGN_CENTER);
 
 frameSizer->Add(commandsSizer, 1, wxGROW | wxALIGN_CENTER);
 frameSizer->Add(buttonsSizer, 0, wxALIGN_CENTER);
 frameSizer->Add(10, 10);
 
 frameSizer->Fit(this);
 
 CenterOnParent(wxBOTH);
 
 SetSizer(frameSizer);
 SetAutoLayout(TRUE);
 Layout();
 
 SetSize(235, 230);

 #if wxUSE_STATUSBAR
 
 CreateStatusBar(2);
 SetStatusText(_T("Server is Off."));
    
 #endif
}


void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
 Close(TRUE);
}


void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
    wxString msg;
    msg.Printf(_T("\"Simple Echo Server\"\n\n")
               _T("- Author: Stefano Pace\n\n")
               _T("- Compiled with:\n\n")
               _T("Dev-C++ v.4.9.9.2\n\n")
               _T("- GUI toolkit:\n\n")
               _T("%s"), wxVERSION_STRING);

    wxMessageBox(msg, _T("About Simple Echo Server"), wxOK | wxICON_INFORMATION, this);
}


void MyFrame::OnIdle(wxIdleEvent &event)
{
 //SetStatusText("Ready...");
}     


void MyFrame::OnClose(wxCommandEvent &event)
{
 this->Destroy();
}     


void MyFrame::OnClear(wxCommandEvent &event)
{
 statusInput->SetValue("");
 
 menuFile->Enable(wxID_SAVE, FALSE);
}    


void MyFrame::OnStart(wxCommandEvent& event)
{
 // Create the address - defaults to localhost:0 initially
 wxIPV4address addr;
 addr.Service(PORT);
 
 // Create the socket
 serverSock = new wxSocketServer(addr);

 // We use Ok() here to see if the server is really listening
 if (!serverSock->Ok())
         {
          statusInput->AppendText("\nFailed!\nMaybe port already in use.\n");
                       
          return;
         }
         
 // Set up the event handler and subscribe to connection events
 serverSock->SetEventHandler(*this, SERVER_ID);
 serverSock->SetNotify(wxSOCKET_CONNECTION_FLAG);
 serverSock->Notify(true);
 
 SetStatusText(_T("Server running..."));
 statusInput->AppendText("\nServer running...\n");
}


void MyFrame::OnServerEvent(wxSocketEvent& WXUNUSED(event))
{     
 // Accept the new connection and get the socket pointer
 wxSocketBase* sock = serverSock->Accept(false);

 // Tell the new socket how and where to process its events
 sock->SetEventHandler(*this, SOCKET_ID);
 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
 sock->Notify(true);
 
 SetStatusText("New client connected");
 statusInput->AppendText("\nNew client connected");
}


void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
 wxSocketBase *sock = event.GetSocket();
 
 // Process the event
 switch(event.GetSocketEvent())
         {
          case wxSOCKET_INPUT:
                  {
                   char buf[50];
                   
                   // Read the data
                   sock->Read(buf, sizeof(buf));
                   
                   // Write it back
                   sock->Write(buf, sizeof(buf));
                   
                   statusInput->AppendText("\n");
                   statusInput->AppendText(buf);
                   
                   break;
                  }
                  
          case wxSOCKET_LOST:
                  {
                   sock->Destroy();
                   
                   SetStatusText("Connection lost!");
                   statusInput->AppendText("\n\nConnection lost!");
                   
                   wxString msg;
                   msg.Printf(_T("Connection lost!"));
                   wxMessageBox(msg, _T("Error"), wxOK | wxICON_ERROR);

                   break;
                  }
         }
}


phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 » Wed Jul 05, 2006 8:06 am

Hm, while processing input events, you shouldn't receive any of them.
Code from my app:

Code: Select all

if(socket->IsConnected())
	{
		socket->SetNotify(wxSOCKET_LOST_FLAG);//only socket lost events areprocessed during this
		if(control->Getprotocol().Reset())// Do some stuff...
		{
			control->Getprotocol().StatusAll();
		}
		socket->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);//now we also wanna process input events again
		gridpanel->Update();
		Refresh();
	}
phlox

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Wed Jul 05, 2006 8:14 am

Hi, thanks for answering!
Please, could you explain me better what should I add to my code and why?
What's "control" variable type?
I haven't understood this piece of code:

Code: Select all

if(control->Getprotocol().Reset())// Do some stuff... 
                   { 
                     control->Getprotocol().StatusAll(); 
                   } 
could you explain it to me? or it is not important for what i have to do?

phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 » Wed Jul 05, 2006 8:38 am

No, thats just some abstraction code which does the communication with the server for my app.
Its wrapped inside a Protocol class, which is held by a singelton (control).

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Wed Jul 05, 2006 8:44 am

So what's the change to be made in my code?

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Wed Jul 05, 2006 9:27 am

I've downloaded and installed on my PC a free SMTP server, to try if on localhost my program worked, but nothing to do :(
Always the same errors: 421 or 500 unrecognized command :(
Maybe i must code the strings that i send to the server in some way?
is there a function to do this? Or the SMTP server wants just a simple string? :shock:

ciammarica
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Jul 04, 2006 6:49 am

Post by ciammarica » Wed Jul 05, 2006 10:05 am

Another little step is done!
Now the server anwers good to the command "MAIL FROM:" :)
I've just added \r before \n at the end of the string sent to the server.
That's because in RFC821 I've read that CRLF must be typed after each command, but \n is just LF (Line Feed), Carriage Return was missing...
So I've added it! But it works just for another command, not for all following others :(
Here is the modified piece of code

Code: Select all

...

if (Socket->IsConnected())
         {
          char toSend[50];
          const wxChar* inputContent;
                                     
          Socket->Write("HELO SMTP Client v1.0 beta\r\n", 28);
          
          Socket->WaitForRead(2);
          
          inputContent = mailFromInput->GetValue();
          
          sprintf(toSend, "MAIL FROM:<%s>\r\n", inputContent);
          
          Socket->Write(toSend, sizeof(toSend));
          
          Socket->WaitForRead(2);
          
          inputContent = rcptToInput->GetValue();
          
          sprintf(toSend, "RCPT TO:<%s>\r\n", inputContent);
          
          Socket->Write(toSend, sizeof(toSend));
          
          Socket->WaitForRead(2);
          
          Socket->Write("DATA\r\n", 6);
          
          Socket->WaitForRead(2);
          
          inputContent = dataInput->GetValue();
          
          sprintf(toSend, "%s\r\n.\r\n", inputContent);
          
          Socket->Write(toSend, sizeof(toSend));
          
          Socket->WaitForRead(2);
          
          Socket->Write("QUIT\r\n", 6);
          
          Socket->WaitForRead(2);
          
          Socket->Close();
         }

...
This shows that the commands are ok, but i must find a way to send CRLF in a way the server always accepts!
The ASCII code for CR is 13 and the ASCII code for LF is 10...
What if I declare two chars, one with the ascii code for CR and the other one with ASCII code for LF, and then I append them to the command, instead of using "\r\n" ?
How could i do this? How can i assign to a char an ASCII code?
Thanks!!! Maybe i see the light over the tunnel!!! :)

Post Reply