Collect emails from the POP3 Account (Conduct a POP3 session with the designated server). The emails are each placed in thier own file.

Return TypeFunction nameArguments
hzEcodehzPop3Acc::Collect(hzVect<hzString>&,)

Declared in file: hzMailer.h
Defined in file : hzPop3.cpp

Function Logic:

0:START 1:items 2:unknown 3:items 4:Return E_NOINIT 5:rc 6:unknown 7:items 8:Return rc 9:rc 10:unknown 11:items 12:Return rc 13:rc 14:unknown 15:items 16:Return rc 17:items rc 18:unknown 19:items 20:Goto done 21:S items zi 22:unknown 23:rc items 24:Goto done 25:items items S items rc 26:unknown 27:items 28:Goto done 29:items rc 30:unknown 31:items 32:Goto done 33:S items zi 34:unknown 35:rc S items 36:Goto done 37:items items S items rc 38:unknown 39:items rc 40:Goto done 41:items rc 42:unknown 43:items 44:Goto done 45:S items zi 46:unknown 47:S items rc 48:Goto done 49:items items S items rc 50:unknown 51:items 52:Goto done 53:items 54:unknown 55:rc 56:unknown 57:items 58:Goto done 59:items zi Z zi 60:unknown 61:S items zi 62:unknown 63:rc items 64:Goto done 65:unknown 66:items 67:unknown 68:unknown 69:items 70:unknown 71:S mailId items 72:unknown 73:unknown 74:items 75:unknown 76:items 77:S items 78:unknown 79:items 80:unknown 81:unknown 82:mailId S items 83:unknown 84:mailId S items items rc 85:unknown 86:items 87:items 88:unknown 89:rc 90:unknown 91:items 92:items zi Z zi 93:unknown 94:items zi 95:unknown 96:rc S items 97:unknown 98:unknown 99:items 100:unknown 101:unknown 102:unknown 103:zi 104:unknown 105:zi 106:items / m_Repos 107:path items 108:unknown 109:items 110:items items items items items 111:items items items 112:Return rc

Function body:

hzEcode hzPop3Acc::Collect (hzVect<hzString>& messages)
{
   //  Collect emails from the POP3 Account (Conduct a POP3 session with the designated server). The emails are each placed in thier own file.
   //  
   //  Arguments: 1) messages A vector of strings that is populated with filename of collected emails.
   //  
   //  Returns: E_NOINIT The POP3 account is not initialized
   //     E_PROTOCOL The session message not as expected
   //     E_OK  The email collection was successful
   _hzfunc("hzPop3Acc::Collect") ;
   hzMapS<int32_t,hzString>    temp ;  //  Emails available from the POP3 server
   ofstream        os ;            //  Output stream
   hzTcpClient     P ;             //  POP3 client connection
   chIter          zi ;            //  For iterating server responses
   hzChain         Z ;             //  For sending commands and receiving responses
   hzChain         word ;          //  For capturing small strings (eg mail number and mail id)
   hzChain         msg ;           //  For garnering messages
   hzString        S ;             //  For conversion of 'word' into a string
   hzString        path ;          //  For email filenames
   uint32_t        mailId ;        //  Mail number as given by server
   uint32_t        nIndex ;        //  For iterating avail emails
   hzEcode         rc ;            //  Return code
   m_Error.Clear() ;
   if (!m_Repos)
   {
       threadLog("POP3 Account not initialized\n") ;
       return E_NOINIT ;
   }
   rc = P.ConnectStd(m_Server, 110);
   if (rc != E_OK)
   {
       threadLog("Cannot connect to email server %s (error=%s)\n", *m_Server, Err2Txt(rc)) ;
       return rc ;
   }
   rc = P.SetSendTimeout(30);
   if (rc != E_OK)
   {
       threadLog("Could not set send_timeout on connection to POP3 server (error=%s)\n", Err2Txt(rc)) ;
       return rc ;
   }
   rc = P.SetRecvTimeout(30);
   if (rc != E_OK)
   {
       threadLog("Could not set recv_timeout on connection to POP3 server (error=%s)\n", Err2Txt(rc)) ;
       return rc ;
   }
   //  Expect the server to talk first with a +OK
   Z.Clear() ;
   rc = P.Recv(Z) ;
   if (rc != E_OK)
   {
       threadLog("Cannot recv server hello (error=%s)\n", Err2Txt(rc)) ;
       goto done ;
   }
   S = Z ;
   threadLog("Server: [%s]\n", *S) ;
   zi = Z ;
   if (zi != "+OK")
   {
       rc = E_PROTOCOL ;
       threadLog("Expected +OK as hello from server. (error=%s)\n", Err2Txt(rc)) ;
       goto done ;
   }
   //  Send the initial username
   Z.Clear() ;
   Z.Printf("USER %s\r\n", *m_Username) ;
   S = Z ;
   threadLog("Client: [%s]\n", *S) ;
   rc = P.Send(Z) ;
   if (rc != E_OK)
   {
       threadLog("Cannot send username to email server (error=%s)\n", Err2Txt(rc)) ;
       goto done ;
   }
   //  Recv the +OK\r\n (to the username)
   Z.Clear() ;
   rc = P.Recv(Z) ;
   if (rc != E_OK)
   {
       threadLog("Cannot recv response to username from email server (error=%s)\n", Err2Txt(rc)) ;
       goto done ;
   }
   S = Z ;
   threadLog("Server: [%s]\n", *S) ;
   zi = Z ;
   if (zi != "+OK")
   {
       rc = E_PROTOCOL ;
       S = Z ;
       threadLog("Expected +OK response to username (got=%s)\n", *S) ;
       goto done ;
   }
   //  Send the password
   Z.Clear() ;
   Z.Printf("PASS %s\r\n", *m_Password) ;
   S = Z ;
   threadLog("Client: [%s]\n", *S) ;
   rc = P.Send(Z) ;
   if (rc != E_OK)
   {
       threadLog("Cannot send password to email server (error=%s)\n", Err2Txt(rc)) ;
       rc = E_PROTOCOL ;
       goto done ;
   }
   //  Recv the +OK\r\n (to the password)
   Z.Clear() ;
   rc = P.Recv(Z) ;
   if (rc != E_OK)
   {
       threadLog("Cannot recv response to username from email server (error=%s)\n", Err2Txt(rc)) ;
       goto done ;
   }
   S = Z ;
   threadLog("Server: [%s]\n", *S) ;
   zi = Z ;
   if (zi != "+OK")
   {
       S = Z ;
       threadLog("Expected +OK to password. (got=%s)\n", *S) ;
       rc = E_PROTOCOL ;
       goto done ;
   }
   //  Send the UIDL command
   Z.Clear() ;
   Z.Printf("UIDL\r\n") ;
   S = Z ;
   threadLog("Client: [%s]\n", *S) ;
   rc = P.Send(Z) ;
   if (rc != E_OK)
   {
       threadLog("Cannot send UIDL command to email server (error=%s)\n", Err2Txt(rc)) ;
       goto done ;
   }
   //  Recv the +OK\r\n (to the UIDL command)
   Z.Clear() ;
   for (;;)    //  nIndex = 0 ; nIndex < 3 ; nIndex++)
   {
       rc = P.Recv(Z) ;
       if (rc != E_OK)
       {
           threadLog("Cannot recv response to UIDL from email server (error=%s)\n", Err2Txt(rc)) ;
           goto done ;
       }
       threadLog("Server - Response to UIDL of %d bytes\n", Z.Size()) ;
       //  Test for the \r\n.\r\n
       zi = Z ;
       zi += (Z.Size() - 5);
       if (zi == "\r\n.\r\n")
           break ;
   }
   S = Z ;
   threadLog("Server: [%s]\n", *S) ;
   zi = Z ;
   if (zi != "+OK")
   {
       rc = E_PROTOCOL ;
       threadLog("Expected +OK response to UIDL (error=%s)\n", Err2Txt(rc)) ;
       goto done ;
   }
   //  Recieve the list of available messages and place them in the temporary map
   for (; !zi.eof() && *zi != CHAR_NL ; zi++) ;
   zi++ ;
   for (; !zi.eof() ; zi++)
   {
       for (; !zi.eof() && IsDigit(*zi) ; zi++)
           word.AddByte(*zi) ;
       if (!word.Size())
           break ;
       //  zi.Skipwhite() ;
       S = word ;
       mailId = atoi(*S) ;
       word.Clear() ;
       for (zi++ ; !zi.eof() ; zi++)
       {
           if (*zi == CHAR_CR)
               zi++ ;
           if (*zi == CHAR_NL)
               break ;
           word.AddByte(*zi) ;
       }
       S = word ;
       word.Clear() ;
       if (!m_Already.Exists(S))
           temp.Insert(mailId, S) ;
       if (zi.eof())
           break ;
   }
   for (nIndex = 0; nIndex < temp.Count() ; nIndex++)
   {
       mailId = temp.GetKey(nIndex) ;
       S = temp.GetObj(nIndex) ;
       threadLog("Mailbox has %d %d (%s)\n", nIndex, mailId, *S) ;
   }
   //  Recv the email list. Some of these we may already have
   for (nIndex = 0; rc == E_OK && nIndex < temp.Count() ; nIndex++)
   {
       mailId = temp.GetKey(nIndex) ;
       S = temp.GetObj(nIndex) ;
       //  Send the RETR command
       Z.Clear() ;
       Z.Printf("RETR %d\r\n", mailId) ;
       rc = P.Send(Z) ;
       if (rc != E_OK)
           { threadLog("Cannot send RETR command to email server\n") ; break ; }
       //  Recv the +OK (to the RETR command). This involves repeated calls to Recv until the chain ends with a \r\n.\r\n sequence.
       Z.Clear() ;
       for (;;)
       {
           rc = P.Recv(Z) ;
           if (rc != E_OK)
               { threadLog("Cannot recv response to RETR command\n") ; break ; }
           threadLog("Server - Message of %d bytes\n", Z.Size()) ;
           //  Test for the \r\n.\r\n
           zi = Z ;
           zi += (Z.Size() - 5);
           if (zi == "\r\n.\r\n")
               break ;
       }
       //  Go to end of line, then message body, the the CR/NL period CR/NL sequence
       msg.Clear() ;
       zi = Z ;
       if (zi != "+OK")
       {
           rc = E_OK ;
           S = Z ;
           threadLog("Expected +OK in response to RETR command (got=%s)\n", *S) ;
           continue ;
       }
       for (zi += 3; !zi.eof() && *zi != CHAR_NL ; zi++) ;
       if (*zi != CHAR_NL)
       {
           threadLog("Malformed +OK response to RETR command\n") ;
           continue ;
       }
       for (zi++ ; !zi.eof() ; zi++)
       {
           if (*zi == CHAR_CR)
           {
               if (zi == "\r\n.\r\n")
               {
                   zi += 5;
                   if (zi.eof())
                       break ;
                   zi -= 5;
               }
           }
           msg.AddByte(*zi) ;
       }
       path = m_Repos + "/" + S ;
       os.open(*path) ;
       if (os.fail())
           threadLog("Cannot open file %s for writting\n", *path) ;
       else
       {
           threadLog("Writing message file %s\n", *path) ;
           os << msg ;
           os.close() ;
           os.clear() ;
           messages.Add(S) ;
       }
   }
   os.close() ;
done:
   P.Close() ;
   return rc ;
}