Thread: FoxPro Some General Questions/Get Pop Email

Get Pop Email
* Converted to VFP by William Steinford.
* Date: Feb 9, 2003
* This VFP Class definition is based on the C++ class definition
* found at http://www.codeguru.com/internet/pop3_protocol_class_wrapper.shtml
* written originally by Asif Rasheed (aasif@khi.compol.com)

#DEFINE CRLF CHR(13)+CHR(10)

* Test Code:
OX=CREATE("popemail")
OX.SERVERNAME=INPUTBOX("Gimme Your POP SERVER","Hi","pop.mail.yahoo.com")
OX.USER=INPUTBOX("Gimme Your User Name","Hi","username")
OX.PASSWORD=INPUTBOX("Gimme Your Password","Hi","password")

?"Trying to Connect..."
IF NOT OX.CONNECT()
? "Error Connecting:"+OX.ERRORMESSAGE
ELSE
?? "Connected!"
? "Stat Check..."
IF OX.STATISTICS()
  STRTOFILE(OX.SERVERRESPONSE,'ServerStat.txt')
  ? "ServerResponse: "+TRAN(OX.SERVERRESPONSE)
  ? "Number of Emails: "+TRAN(OX.NUMBEROFEMAILS-3)
  ? "Size of Email: "+TRAN(OX.TOTALMAILSIZE)
  ? "Getting Email List..."
  ? OX.LIST()
  ? "Total Messages: "+TRAN(OX.NUMBEROFEMAILS)
  IF OX.NUMBEROFEMAILS>0
   ? 'First Email:'
   FOR LNI = 1 TO OX.NUMBEROFEMAILS
    ? OX.RETRIEVE(LNI)
    LCEMAIL = OX.MSGCONTENTS
    STRTOFILE('----Email#'+TRAN(LNI)+'--------'+CRLF ;
     +LCEMAIL+CRLF,'c:\data\email\Email.txt',.T.)
   ENDFOR
* ? ox.MsgContents
  ELSE
   ? "No Emails!"
  ENDIF
ELSE
  ? "Failed STAT check!"
ENDIF
OX.DISCONNECT()
ENDIF

#DEFINE CONNECTION_CHECK 0
#DEFINE USER_CHECK 1
#DEFINE PASSWORD_CHECK 2
#DEFINE QUIT_CHECK 3
#DEFINE DELETE_CHECK 4
#DEFINE RSET_CHECK 5
#DEFINE STAT_CHECK 6
#DEFINE NOOP_CHECK 7
#DEFINE LIST_CHECK 8
#DEFINE RETR_CHECK 9
#DEFINE VBSTRING 8
#DEFINE TIME_OUT 5

*/////////////////////////////////////////////////////////////////////////////
DEFINE CLASS POPEMAIL AS CUSTOM
ERRORMESSAGE = ""
PASSWORD = ""
USER = ""

SERVERPORT = 110
SERVERNAME = ""

MSGCONTENTS = ""
TOTALMAILSIZE = 0
NUMBEROFEMAILS = 0
CONNECTED = .F.

SERVERRESPONSE = ''
OCXSOCKET = .NULL.
DIMENSION SIZEOFMSG[1]

*!* CString GetErrorMessage(); // If there is any error this will return it method
*!* CString GetPassword(); // Getting Password stored in class
*!* void SetPassword(CString& Password); // Setting Password in class
*!* CString GetUser(); // Getting user name stored in class
*!* void SetUser(CString& User); // Setting user name in class
*!* CString GetHost(); // Getting Host name (email server name) stored in class
*!* void SetHost(CString& Host); // Setting Host name (email server name) in class
*!* BOOL Connect(); // Connecting to email server
*!* int GetTotalMailSize(); // it returns the Total Mail Size
*!* int GetNumberOfMails(); // It return the number of mails
*!* CString GetMsgContents();
*!* BOOL Statistics(); // issue the STAT command on email server
*!* BOOL Retrieve(int MsgNumber); // Getting any particular mail message
*!* BOOL Reset(); // issue the reset command on email server
*!* int GetMessageSize(int MsgNumber); // Return a size of any particular mail
*!* BOOL Noop(); // issue the NOOP command on email server
*!* BOOL Disconnect(); // issue the QUIT command on email server
*!* BOOL Delete(int& MsgNumber); // Deleteing a particular message from email server
*!* BOOL Connect(CString& Host, CString& User, CString& Password);

PROCEDURE INIT
THIS.OCXSOCKET = CREATE('mswinsock.winsock')
ENDPROC

FUNCTION CONNECT(SERVERNAME, PCUSER, PCPASSWORD) && Boolean
LOCAL LCSERVERNAME,LCUSER,LCPASSWORD,LNTIME
LCSERVERNAME = ALLTRIM( IIF( VARTYPE(PCSERVERNAME)='C', PCSERVERNAME, THIS.SERVERNAME ) )
LCUSER = ALLTRIM( IIF( VARTYPE(PCUSER)='C', PCUSER, THIS.USER ) )
LCPASSWORD = IIF( VARTYPE(PCPASSWORD)='C', PCPASSWORD, THIS.PASSWORD )

THIS.OCXSOCKET.CONNECT(LCSERVERNAME,THIS.SERVERPORT) && 110 Pop3 Port
LNTIME = SECONDS()
DO WHILE THIS.OCXSOCKET.STATE <> 7
* ?"Waiting to connect..."
  INKEY(0.01)
* ?"state="+tran(THIS.ocxSocket.State)
  IF SECONDS() - LNTIME > TIME_OUT
   THIS.ERRORMESSAGE = "Server cannot be connected"
   RETURN .F.
  ENDIF
ENDDO
CONNECTED = .T.
* ?"State="+tran(THIS.ocxSocket.State)
IF NOT THIS.CHECKRESPONSE(CONNECTION_CHECK)
  RETURN .F.
ENDIF

IF NOT THIS.SENDMESSAGEOK( "USER "+LCUSER, USER_CHECK )
  RETURN .F.
ENDIF
IF NOT THIS.SENDMESSAGEOK( "PASS "+LCPASSWORD, PASSWORD_CHECK )
  RETURN .F.
ENDIF
RETURN .T.
ENDFUNC

FUNCTION DELETE(PNMSGNUMBER)
IF NOT THIS.SENDMESSAGEOK( "DELE "+TRAN(PCMSGNUMBER), DELETE_CHECK )
  RETURN .F.
ENDIF
RETURN .T.
ENDFUNC

FUNCTION NOOP
IF NOT THIS.SENDMESSAGEOK( "NOOP ", NOOP_CHECK )
  RETURN .F.
ENDIF
RETURN .T.
ENDFUNC

*// Return the Msg Size for given msg number
FUNCTION GETMESSAGESIZE(PNMSGNUMBER)
IF ALEN(THIS.SIZEOFMSG) <= PNMSGNUMBER
  RETURN 0
ENDIF
RETURN THIS.SIZEOFMSG[MsgNumber+1]
ENDFUNC

FUNCTION RESET()
IF NOT THIS.SENDMESSAGEOK( "RSET ", RSET_CHECK )
  RETURN .F.
ENDIF
RETURN .T.
ENDFUNC

*// MsgContents will hold the msg body
FUNCTION RETRIEVE(PNMSGNUMBER)
IF NOT THIS.SENDMESSAGEOK( "RETR "+TRAN(PNMSGNUMBER), RETR_CHECK )
  RETURN .F.
ENDIF
RETURN .T.
ENDFUNC

FUNCTION STATISTICS()
IF NOT THIS.SENDMESSAGEOK( "STAT ", STAT_CHECK )
  RETURN .F.
ENDIF
RETURN .T.
ENDFUNC

FUNCTION LIST
IF NOT THIS.SENDMESSAGEOK( "LIST ", LIST_CHECK )
  RETURN .F.
ENDIF
RETURN .T.
ENDFUNC

FUNCTION DISCONNECT()
* ?"Trying to Disconnect..."
IF NOT THIS.SENDMESSAGEOK( "QUIT ", QUIT_CHECK )
  RETURN .F.
ENDIF
* ??" Disconnected."
RETURN .T.
ENDFUNC

FUNCTION SENDMESSAGEOK( PCMSG, PNTYPE )
* wsprintf (buf, "USER %s\r\n", (LPCSTR) User)
* ?"(out) "+pcMsg
THIS.OCXSOCKET.SENDDATA(PCMSG+CRLF)
IF NOT THIS.CHECKRESPONSE(PNTYPE)
  RETURN .F.
ENDIF
RETURN .T.
ENDFUNC

FUNCTION CHECKRESPONSE(RESPONSETYPE)
LOCAL BUF
BUF =THIS.READDATA()
THIS.SERVERRESPONSE =BUF
*?buf
DO CASE
CASE RESPONSETYPE=CONNECTION_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE ="Bad Connection"
   RETURN .F.
  ENDIF
CASE RESPONSETYPE=USER_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE ="Bad User Name"
   RETURN .F.
  ENDIF
CASE RESPONSETYPE=PASSWORD_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE ="Bad Password"
   RETURN .F.
  ENDIF
CASE RESPONSETYPE=QUIT_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE ="Error occured during QUIT"
   RETURN .F.
  ENDIF
CASE RESPONSETYPE=DELETE_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE ="Error occured during DELE"
   RETURN .F.
  ENDIF
CASE RESPONSETYPE=RSET_CHECK
   IF BUF="-ERR"
    THIS.ERRORMESSAGE ="Error occured during RSET"
    RETURN .F.
  ENDIF
CASE RESPONSETYPE=STAT_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE ="Error occured during STAT"
   RETURN .F.
  ELSE
   EMAILNUMBER =.T.
   LNI =1
   LCSAMP =SUBSTR(BUF,LNI,1)
   DO WHILE LCSAMP#CHR(0) AND LNI<1000 && '\0'
    IF (LCSAMP=CHR(9) OR LCSAMP=' ') && *p == '\t' || *p == ' ')
     IF (EMAILNUMBER == .T.)
      THIS.NUMBEROFEMAILS = Val(SubStr(BUF, LNI)) && New
      EMAILNUMBER = .F.
     ELSE
      THIS.TOTALMAILSIZE = Val(SubStr(BUF, LNI)) && New
      RETURN .T.
     ENDIF
    ENDIF
    LNI = LNI + 1
    LCSAMP = SUBSTR(BUF,LNI,1)
   ENDDO
  ENDIF
CASE RESPONSETYPE=NOOP_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE = "Error occured during NOOP"
   RETURN .F.
  ENDIF
CASE RESPONSETYPE=LIST_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE = "Error occured during LIST"
   RETURN .F.
  ELSE
* Buf = THIS.ReadData()
   LNI = 1
   LCSAMP = SUBSTR(BUF,LNI,1)
   LNLINE = 1
   DO WHILE LNI <= Len(BUF) &&LCSAMP#'.' AND LNI<1000 && '\0' && New: no check for . (RFC STD53)
    IF LCSAMP=CHR(13)
     LNLINE = LNLINE + 1
    ENDIF
    IF LNLINE > 1
     IF (LCSAMP=CHR(9) OR LCSAMP=' ') && *p == '\t' || *p == ' ')
      DIMENSION THIS.SIZEOFMSG[ alen(THIS.SizeOfMsg)+1 ]
      THIS.SIZEOFMSG[alen(THIS.SizeOfMsg)] = VAL(SUBSTR(BUF,LNI))
*? " Email #"+tran(alen(THIS.SizeOfMsg)-1)+" size="+tran(THIS.SizeOfMsg[alen(THIS.SizeOfMsg)])
     ENDIF
    ENDIF
    LNI = LNI + 1
    LCSAMP = SUBSTR(BUF,LNI,1)
   ENDDO
   THIS.NUMBEROFEMAILS = ALEN(THIS.SIZEOFMSG)-1
  ENDIF
CASE RESPONSETYPE=RETR_CHECK
  IF BUF="-ERR"
   THIS.ERRORMESSAGE = "Error occured during RETR"
   RETURN .F.
  ELSE
   THIS.MSGCONTENTS = BUF+THIS.READDATA()
  ENDIF
ENDCASE
RETURN .T.
ENDFUNC

FUNCTION READDATA
LOCAL CMSGIN, LNTIME
LNTIME = SECONDS()
DO WHILE THIS.OCXSOCKET.BYTESRECEIVED = 0
* ?"Waiting to Receive data..."
  INKEY(0.2)
  IF SECONDS() - LNTIME > TIME_OUT
* ?"Timed Out"
   RETURN ''
  ENDIF
ENDDO
***CMSGIN = REPL(CHR(0),10000) && chr(0),10000)

* ?"(in) Bytes Received: "+tran(THIS.ocxSocket.BytesReceived)
* THIS.ocxSocket.Receive(buf, len(buf))

* Fixed a bug with messages longer than the buffer size

***IF THIS.OCXSOCKET.STATE=7
*** THIS.OCXSOCKET.GETDATA(@CMSGIN,VBSTRING)
***ENDIF

   DOEVENTS

   lcBuffer = REPL(CHR(0),10000)
   lcMsgIn = ""
   IF THIS.oSocket.State = 7
      DO WHILE THIS.oSocket.BytesReceived > 0
         THIS.oSocket.GETDATA(@lcBuffer,vbString)
         lcMsgIn = lcMsgIn + lcBuffer
         INKEY(0.1)
      ENDDO
   ENDIF

* cMsgIn = LEFT( cMsgIn, AT(chr(0),cMsgIn) )
* ?"(in) Data Read: ("+tran(len(cMsgIn))+","+tran(THIS.ocxSocket.BytesReceived)+" bytes) "+cMsgIn
RETURN CMSGIN
ENDFUNC

PROCEDURE DESTROY
DODEFAULT()
IF THIS.CONNECTED
  THIS.DISCONNECT()
ENDIF
ENDPROC
ENDDEFINE