khong Duc
khong Duc

Reputation: 21

How can i tell the client to wait until it received all the data?

this is my first post. i am currently taking a networking class and i am required to write a client program that can download all emails from imap.gmail.com:993 to text files. i am required to write this program using winsock and openssl. I was able to connect to the server and fetch the emails. For emails with small data, i had no problem receiving it. But for emails with large data such as an images that is base64-decoded, i was able to download only a part of it.

so my question is How can i tell the client to wait until it received all the data from the server?

Here is what i have done so far:

void fetchMail(SSL *sslConnection,int lowerLimit, int UpperLimit)
 {
     SYSTEMTIME lt;
    ofstream outfile;
     GetLocalTime(&lt);
    char szFile[MAX_PATH + 1];
    char szPath[MAX_PATH+1];
    char message[BUFSIZE];
    char result[BUFSIZE];
    ::GetModuleFileName( NULL, szPath,  MAX_PATH );

    // Change file name to current full path
  LPCTSTR psz = strchr( szPath, '\\');
    if( psz != NULL )
    {
        szPath[psz-szPath] = '\0';
    }
    char szMailBox[MAX_PATH+1];
    memset( szMailBox, 0, sizeof(szMailBox));
    wsprintf( szMailBox, "%s\\inbox", szPath );

    // Create a folder to store emails
    ::CreateDirectory( szMailBox, NULL );
   for(int i = lowerLimit; i < UpperLimit; ++i)
   {
    // Create a folder to store emails

       memset( szFile, 0, sizeof(szFile));
       memset( result, 0, sizeof(result));
       memset( message, 0, sizeof(message));
       ::sprintf(szFile,"%s\\%d%d%d%d%d%d.txt", szMailBox, lt.wHour, lt.wMinute,lt.wMinute,lt.wSecond, lt.wMilliseconds,i);



    string Result;//string which will contain the result

    stringstream convert; // stringstream used for the conversion
    const char * num;
    convert << i;//add the value of Number to the characters in the stream

    Result = convert.str();//set Result to the content of the stream
    num = Result.c_str();


    strcpy(result, "tag FETCH ");
    strcat(result,  num);
    strcat(result, " (BODY[TEXT])\r\n");

    int n = 0;

    cout << "\nFETCHING : \n";

    SSL_write(sslConnection, result, strlen(result));
    outfile.open(szFile );

    SSL_read(sslConnection, message, sizeof(message)-1);

    outfile <<message ;


    outfile.close();

   }
 }

Upvotes: 2

Views: 487

Answers (1)

Arne Mertz
Arne Mertz

Reputation: 24626

First of all some points on your code:

  • You use strcpy, strcat and all those unchecked, unsafe C functions. You might easily get buffer overflows and other kinds of errors. Consider to use C++ strings, vectors, arrays.
  • You do a lot of different things in that function, on different levels of abstraction. AFAICS only the two SSL_* function calls are really about fetching that mail. Consider to break out some functions to improve readability.

Now to your problem: Googling a bit about SSL_read, you will see that it returns an int, denoting how many bytes were actually read. You should use that return value - not only for this issue but also for error handling. If the mail data is longer than your buffer, the function will read until the buffer is filled and return its size. You should continue to call the function until all bytes have been read.

Upvotes: 1

Related Questions