FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Modificación TSMTP.prg
Posts: 1446
Joined: Mon Oct 10, 2005 02:38 PM

Modificación TSMTP.prg

Posted: Tue Apr 29, 2014 10:11 PM
Hola a todos,

Os dejo la clase TSMTP que he modificado un poco para casos en los que la función GetHostByAddress() no devuelve el nombre del dominio.
Cuando tienes un dominio que comparte servidor con otros dominios, parece ser (esto es lo que me cuenta mi servidor de hosting) que si se consulta por IP, no se obtiene el nombre del dominio.
Para ver la modificación buscar por 'lcHostFromIP'.

Antonio, naturalmente si lo consideras necesario y lo añades en la siguiente versión me ahorraré adaptar código.

Code (fw): Select all Collapse
// FiveWin Internet outgoing mail Class
// Modified by Luis Krause July 5, 2001; February 26, 2002; October 7, 2002; November 5, 2002;
//                         October 9, 2003; June 1, 2005, March 26, 2008
//    with code from Alex Shaft, Byron Hopp, Andrew Ross (PipleLine Solutions),
//    Frank Demont, Peter Kohler, Rafael Gaona, Joaquim Ferrer,
//    Jos‚ Lal¡n, Ray Alich (IBTC), Ignacio Vizca¡no Tapia and others
// Special thanks to Jorge Mason for the fix to GetHostByAddress() that was GPFing on some servers

// Simple Authentication and Security Layer [SASL]
// This class only supports LOGIN type for authentication.
// TODO: Add PLAIN and MD5 methods.
//       PLAIN is the same as LOGIN but it doesn't use base64, i.e.:
//       AUTH LOGIN -> USER cMimeEnc( ::cUser )
//       AUTH PLAIN -> USER ::cUser
// See rfc2554.txt for more details about ESMTP
// [jlalin]
/* cgp C.Gelabert 09/04/2014
   Añadida DATA lcHostFromIP para indicar si a partir del nombre del dominio se ha obtenido la IP.
   Hay dominios que comparten servidor que no devuelven valor para GetHostByAddress(); con
   lcHostFromIP se gestiona esta situación.
*/

#include "FiveWin.ch"

#ifndef __CLIPPER__
#xtranslate Memory(<n>) =>                       // only needed with Clipper, not [x]Harbour
#endif

// different session status
#define ST_INIT       0
#define ST_CONNECTED  1
#define ST_RESET      2
#define ST_MAILFROM   3
#define ST_RCPTTO     4
#define ST_DATA       5
#define ST_SENT       6
#define ST_QUIT       7
#define ST_DONE       8
#define ST_ERROR      9

// Authentication states
#define ST_AUTH0      10        // IBTC
#define ST_AUTH       11        // [jlalin]
#define ST_USER       12        // [jlalin]
#define ST_PASS       13        // [jlalin]
// Last defined state
#define ST_LAST       ST_PASS   // [jlalin]

#define MSG_CAPTION   "SMTP Services"

//----------------------------------------------------------------------------//

CLASS TSmtp

   DATA   oSocket        AS OBJECT               // socket used during the mail session
   DATA   cIPServer      AS String               // IP of the mail server
   DATA   lcHostFromIP   AS LOGICAL INIT .F.     // .T. indicará que a partir de la IP del dominio se ha obtenido el nombre.

   DATA   cFrom          AS String               // Sender email address
   DATA   aTo            AS ARRAY INIT NIL       // Array of strings for each recipient email address
   DATA   aCC            AS ARRAY INIT NIL
   DATA   aBCC           AS ARRAY INIT NIL
   DATA   cReplyTo       AS String               // added by LKM Sep/28/2002
   DATA   lReceipt       AS LOGICAL              // added by LKM Sep/25/2002

   DATA   nStatus        AS NUMERIC              // Temporary session status
   DATA   nTo            AS NUMERIC              // Temporary recipient index into aTo recipients array
   DATA   nCC            AS NUMERIC
   DATA   nBCC           AS NUMERIC
   DATA   cMsg           AS String               // Msg Text to send
   DATA   cHTML          // AS String               // Html Text to Send - added by RRG 29.05.2002
   DATA   cSubject       AS String               // msg subject
   DATA   dDate          // AS String               // msg date
   DATA   cTime          AS String               // msg time
   DATA   nGMT           AS NUMERIC              // GMT deviation
   DATA   cPriority      AS String               // msg priority: normal, high, low
   DATA   aFiles         AS ARRAY INIT NIL       // Attached files

   DATA   bConnecting    AS CODEBLOCK INIT NIL   // Action to perform while trying to connect
   DATA   bConnected     AS CODEBLOCK INIT NIL   // Action to perform when already connected
   DATA   bDone          AS CODEBLOCK INIT NIL   // Action to perform when Msg has been already sent
   DATA   bFailure       AS CODEBLOCK INIT NIL

   DATA   lTxtAsAttach   AS LOGICAL              // .T. to force Txt files as Attachments; .F. to force as Inline

   DATA   cReceived      AS String INIT ""       // added by AS
   DATA   acReply        AS ARRAY  INIT {}       // added by AS
   DATA   cError         AS String INIT ""       // added by AS

   DATA   cMailer                                // Mailer Name added by Pipeline
   DATA   cClient                                // Mail Client Name added by Pipeline

   DATA   nDelay         AS NUMERIC INIT 0       // added by LKM Sep/28/2002, based on RG's idea (see mods to TSocket class)

   DATA   cUser          AS String INIT ""       // [jlalin]
   DATA   cPassword      AS String INIT ""       // [jlalin]
   // We can only log in one time per session
   DATA   lAuth          AS LOGICAL              // [jlalin]
   DATA   lDoAuth        AS LOGICAL              // IBTC

   METHOD New( cIPServer, nPort, lAuth, cUser, cPassword ) CONSTRUCTOR

   METHOD End()  INLINE ;                        // added by LKM
      If( ::oSocket # Nil, ::oSocket:End(), Nil )

   METHOD OnRead( oSocket, nWSAError )
   METHOD OnConnect( oSocket, nWSAError )        // added by LKM see TSocket class

   METHOD SendMail( cFrom, aTo, cMsg, cSubject, aFiles, aCC, aBCC, lReceipt, cHTML )  // added CC, BCC and Return Receipt capability LKM; cHTML added by RRG

   METHOD Priority()

   METHOD Failure( oSocket, nWSAError, cReply ) HIDDEN  // called from OnRead when failure occurs

ENDCLASS

//----------------------------------------------------------------------------//

METHOD New( cIPServer, nPort, lAuth, cUser, cPassword ) CLASS TSmtp

   Default nPort := 25, ;
           lAuth := .F., ;                       // IBTC
           cUser := "", ;                        // [jlalin]
           cPassword := ""                       // [jlalin]

   If Empty( cIPServer )                         // nil or ""
      cIPServer := "0.0.0.0"
   Endif

   ::lAuth      := .F.                           // IBTC
   ::lDoAuth    := lAuth                         // IBTC
   ::cUser      := AllTrim( cUser )              // [jlalin]
   ::cPassword  := AllTrim( cPassword )          // [jlalin]

   ::oSocket := TSocket():New( nPort )

   ::oSocket:bRead    := {|o,n| ::OnRead( o, n ) }
   ::oSocket:bConnect := {|o,n| ::OnConnect( o, n ) }  // lkm - see adjustment to TSocket class

   // by lkm now you can provide either the IPAddress or the server name (friendly name)
   ::cIPServer  := If( IsAlpha( cIPServer ), GetHostByName( AllTrim( cIPServer ) ), cIPServer )
   ::nStatus    := ST_INIT
   
   //Traza( 1, "::cIPServer=", ::cIPServer )
   
   // cgp 09/04/2014
   ::lcHostFromIP := (.Not. Empty(GetHostByAddress( ::cIPServer )) )
   //Traza( 1, "::lcHostFrom,IP=", ::lcHostFromIP )


   // predefined events actions
   ::bDone := {|| MsgInfo( ;
      "Message successfully sent through " + ::cIPServer + CRLF + ;
      GetHostByAddress( ::cIPServer ), MSG_CAPTION ) }
   ::bFailure := {|| ;
      MsgStop( "Session did not complete successfully" + CRLF + CRLF + ::cError, MSG_CAPTION ) }

   ::lTxtAsAttach := .T.                         // force text files as attachments, not inline

Return Self

//----------------------------------------------------------------------------//

METHOD OnRead( oSocket, nWSAError ) CLASS TSmtp

   Local cData
   Local nI
   Local nPos := 0, cReply, cExt, cAns
   Local bReply := {|| AScan( ::acReply, {|cTxt| Left( cTxt, 3 ) == cAns } ) > 0 }
   Local cTmpFile

   If oSocket == Nil                             // random error with [x]Harbour
      ::Failure()
      Return Nil                                 // avoid r/t error
   Endif

   cData := oSocket:GetData()
   // Buffer received data
   ::cReceived += cData

   // Pull out full lines received
   Do While ( nPos := At( CRLF, ::cReceived ) ) > 0
      AAdd( ::acReply, Left( ::cReceived, nPos - 1 ) )
      ::cReceived := SubStr( ::cReceived, nPos + 2 )
   Enddo

   // Has closing line been received?
   If ATail( ::acReply ) == Nil .or. ;           // rare, but s**t happens
         ! SubStr( ATail( ::acReply ), 4, 1 ) == " "
      If( ATail( ::acReply ) == Nil, ::acReply := {}, Nil )
      Return Nil
   Endif

   cReply := Left( ATail( ::acReply ), 3 )

   Do Case
      Case ::nStatus == ST_INIT                  // Socket Connection being established
         If cReply == "220"                      // SMTP Server Ready and waiting
            oSocket:SendData( "HELO " + ::cClient + CRLF )  // ::cFrom has "@" which some servers don't like Andrew W. Ross <awr@jps.net>
            If ! ::lDoAuth                       // IBTC
               ::nStatus := ST_CONNECTED
            Endif
            If ::bConnected != nil
               Eval( ::bConnected )
            Endif

            If ::lDoAuth                         // IBTC
               // [jlalin]
               // If we pass User and Password we ask the server for authenticacion
               // if cReply == "530"
               If ! Empty( ::cUser ) .and. ! Empty( ::cPassword )
                  If ! ::lAuth                   // We are not authenticated yet
                     oSocket:SendData( "AUTH LOGIN" + CRLF )
                     ::nStatus := ST_AUTH0
                  Endif
               Endif
               //endif
            Endif
         Else
            ::Failure( oSocket, nWSAError, cReply )
         Endif

      // IBTC
      Case ::nStatus == ST_AUTH0
         If SubStr( cData, 1, 3 ) == "250" .or. Eval( bReply, cAns := "334" )
            ::nStatus := ST_AUTH
         Else
            ::nStatus := ST_QUIT
         Endif

      // [jlalin]
      Case ::nStatus == ST_AUTH
         If SubStr( cData, 1, 3 ) == "334"
            // User and Pass must be encoded in base64
            oSocket:SendData( cMimeEnc( ::cUser ) + CRLF )
            ::nStatus := ST_USER
         Else
            ::nStatus := ST_QUIT
         Endif

      // [jlalin]
      Case ::nStatus == ST_USER
         If SubStr( cData, 1, 3 ) == "334"
            oSocket:SendData( cMimeEnc( ::cPassword ) + CRLF )
            ::nStatus := ST_PASS
         Else
            ::nStatus := ST_QUIT
         Endif

      // [jlalin]
      Case ::nStatus == ST_PASS
         If SubStr( cData, 1, 3 ) == "235"       // // Allright. Server supports authentication
            ::nStatus := ST_CONNECTED
            ::lAuth   := .T.                     // We are authenticate, proceed with connection.
            oSocket:SendData( CRLF )
         Else //if SubStr( cData, 1, 3 ) == "535" // Auth failure
            ::Failure( oSocket, nWSAError, cReply )
         Endif

//      case ::nStatus == ST_CONNECTED
//           oSocket:SendData( "RSET" + CRLF )
//           ::nStatus := ST_RESET

      Case ::nStatus == ST_CONNECTED .or. ::nStatus == ST_RESET
         If cReply == "250"                      // Server happy with our repsonse. Start mail send.
            oSocket:SendData( StrTran( "MAIL FROM:<%>", "%", CleanEMail( ::cFrom ) ) + CRLF )
            ::nStatus := ST_MAILFROM
            ::nTo     := 1    // First recipient index to send mail to
            ::nCC     := 1
            ::nBCC    := 1
         Elseif Val( cReply ) > 400 .and. ::nStatus == ST_CONNECTED
            ::nStatus := ST_RESET
            oSocket:SendData( "EHLO " + ::cClient + CRLF )  // don't use ::cFrom (see note above)
         Else
            ::Failure( oSocket, nWSAError, cReply )
         Endif

      Case ::nStatus == ST_MAILFROM .or. ::nStatus == ST_RCPTTO
         If cReply == "250" .or. cReply == "251"  // Server happy with our repsonse
            If ::nTo <= Len( ::aTo )
               oSocket:SendData( StrTran( "RCPT TO:<%>", "%", CleanEMail( ::aTo[ ::nTo ] ) ) + ;
                                 CRLF )
               ::nStatus := ST_RCPTTO
               ::nTo++
            Elseif ::nCC <= Len( ::aCC )
               oSocket:SendData( StrTran( "RCPT TO:<%>", "%", CleanEMail( ::aCC[ ::nCC ] ) ) + ;
                                 CRLF )
               ::nStatus := ST_RCPTTO
               ::nCC++
            Elseif ::nBCC <= Len( ::aBCC )
               oSocket:SendData( StrTran( "RCPT TO:<%>", "%", CleanEMail( ::aBCC[ ::nBCC ] ) ) + ;
                                 CRLF )
               ::nStatus := ST_RCPTTO
               ::nBCC++
            Else
               ::nStatus := ST_DATA
               oSocket:SendData( "DATA" + CRLF )
            Endif
         Else
          
            ::Failure( oSocket, nWSAError, cReply )
         Endif

      Case ::nStatus == ST_DATA
         If cReply == "354"                      // Ready to accept data
            Default ::cMsg := "", ::cSubject := "[no subject]", ::cHTML := "", ;
                    ::dDate := Date(), ::cTime := Time(), ;
                    ::nGMT := 0, ::cPriority := "Normal"

// dfl - treat text message as alternate if there is an HTML message instead of mixing them - text and HTML in the email
// dfl - create duplicate text and HTML messages with text as alternate message, not both text and HTML as was done originally

// dfl - NextPart was not working well at all - made adjustments
// dfl - at times part of an email was converted into an attachment

            oSocket:SendData( "From: " + ::cFrom + CRLF + ;
                              If( ! Empty( ::cReplyTo ), ;
                                 "Reply-To: " + CleanEMail( ::cReplyTo ) + CRLF, "" ) + ;
                              AToStr( ::aTo, "To: " ) + ;
                              AToStr( ::aCC, "CC: " ) + ;
                              /*AToStr( ::aBCC, "BCC: " ) +*/ ;  // or it wouldn't be a blind carbon copy at all <g>
                              "Subject: " + ::cSubject + CRLF + ;
                              "Date: " + DTtoEDT( ::dDate, ::cTime, ::nGMT ) + CRLF + ;
                              "MIME-Version: 1.0" + CRLF + ;
                              If( ::lReceipt, ;
                                 "Disposition-Notification-To: " + ::cFrom + CRLF, "" ) + ;
                              "X-MSMail-Priority: " + ::cPriority + CRLF + ;
                              "X-Priority: " + LTrim( Str( ::Priority() ) ) + CRLF + ;
                              "X-Mailer: " + ::cMailer + CRLF + ;
                              If( ! Empty( ::aFiles ) .or. ! Empty( ::cHTML ), ;
                                  "Content-Type: multipart/mixed; " + ;
                                     'boundary="NextPart_000"' + CRLF + CRLF + ;
                                  "This is a multi-part message in MIME format." + CRLF + CRLF + ;
                                  "--NextPart_000" + CRLF, "" ) + ;
                                  "Content-Type: multipart/alternative; " + ;
                                     'boundary="NextPart_001"' + CRLF + CRLF + ;
                                  "--NextPart_001" + CRLF + ;
                                  "Content-Type: text/plain; " + ;
                                    CharsetIso8859() + CRLF + ;
                                 "Content-Transfer-Encoding: quoted-printable" + CRLF + CRLF + ;
                                 ::cMsg + CRLF + If ( Empty( ::cHTML ), "--NextPart_001--", "") + CRLF )
            If ! Empty( ::cHTML )  // RRG 29.05.2002 Send as HTML sytle email (Cambios para enviar correo como html)
               oSocket:SendData( CRLF + "--NextPart_001" + CRLF + ;
                                 "Content-Type: text/html; " +  ;
                                   CharsetIso8859() + CRLF + ;
                                 "Content-Transfer-Encoding: quoted-printable" + CRLF + CRLF + ;
                                 FormHtml( ::cHTML, ::cSubject, ::cMailer ) + ;
                                 CRLF + If ( Empty ( ::aFiles ), "", "--NextPart_001--" ) + CRLF )
            Endif

// dfl - file path was not being removed in the 'name=' and the upper case conversion was removed so the
// dfl - actual file name case was preserved

            For nI := 1 To Len( ::aFiles )
               If File( ::aFiles[ nI ] )
                  cExt := Upper( cFileExt( ::aFiles[ nI ] ) )
                  If ( cExt == "TXT" .or. cExt == "LOG" .or. cExt == "HTM" ) .and. ! ::lTxtAsAttach
                     oSocket:SendData( CRLF + "--NextPart_000" + CRLF + ;
                                       "Content-Type: " + DocType( cExt ) + ;
                                          'name="' + cFileNoPathSmtp( ::aFiles[ nI ] ) + '"' + CRLF + ; // dfl - get the file name without the path and don't convert to upper case
                                       "Content-Transfer-Encoding: " + If( cExt == "HTM", "7bit", "quoted-printable" ) + CRLF + ;
                                       "Content-Disposition: inline; " + ;  // LKM was attachment
                                          'filename="' + cFileNoPathSmtp( ::aFiles[ nI ] ) + '"' + CRLF + CRLF )  // dfl - don't convert file name to upper case
                     oSocket:SendFile( ::aFiles[ nI ],, ::nDelay )
                  Else
                     oSocket:SendData( CRLF + "--NextPart_000" + CRLF + ;
                                       "Content-Type: " + DocType( cExt ) + ;
                                          'name="' + cFileNoPathSmtp( ::aFiles[ nI ] ) + '"' + CRLF + ; // dfl - get the file name without the path and don't convert to upper case
                                       "Content-Transfer-Encoding: base64" + CRLF + ;
                                       "Content-Disposition: attachment; " + ; // LKM was inline
                                          'filename="' + cFileNoPathSmtp( ::aFiles[ nI ] ) + '"' + CRLF + CRLF )  // dfl - don't convert file name to upper case
                     cTmpFile := TmpFile()       // ivt (based on his fix)
                     FMimeEnc( ::aFiles[ nI ], cTmpFile )
                     oSocket:SendFile( cTmpFile,, ::nDelay )
                     FErase( cTmpFile )
                  Endif
               Endif
            Next

// dfl - NextPart has to be terminated

            oSocket:SendData( CRLF + ;
                             If( ! Empty( ::aFiles ), "--NextPart_000--" + CRLF + CRLF, "" ) + ;
                              CRLF + "." + CRLF )  // the dot signals the server the mail ends here (leave the CRLF before the dot!)
            ::nStatus := ST_SENT

            // the following to avoid a huge delay (5 minutes or more if the server times out!)
            If oSocket:nRetCode == -1            // most likely the attachment(s) choked the server; increment ::nDelay by one until it works
               AAdd( ::acReply, "421 4.4.2 Timeout while waiting for command. Increase ::nDelay" )
               ::Failure( oSocket, 10060, "421" )  // i.e. WSAETIMEDOUT
            Endif
         Else
            ::Failure( oSocket, nWSAError, cReply )
         Endif

      Case ::nStatus == ST_SENT
         If cReply == "250" .or. Eval( bReply, cAns := "250" )  // Server happy with our repsonse (sometimes ::acReply has two elements: "250" and "500", so we can safely asume everything is ok)
            ::nStatus := ST_QUIT                 // swapped with next line (Peter Kohler)
            oSocket:SendData( "QUIT" + CRLF )
         Else
            ::Failure( oSocket, nWSAError, cReply )
         Endif

      Case ::nStatus == ST_QUIT
         If cReply == "221" .or. cReply == "500" .or. cReply == "502" .or. cReply == "550"  // 500/550 is "unknown command" and doesn't really matter at this stage
            ::nStatus := ST_DONE
            If ::bDone != nil
               Eval( ::bDone )
            Endif
            ::oSocket:End()
         Else
            ::Failure( oSocket, nWSAError, cReply )
         Endif

   EndCase

   ::acReply := {}

Return Nil

//----------------------------------------------------------------------------//

METHOD OnConnect( oSocket, nWSAError )

   Local cHost

   If nWSAError # 0
      cHost := GetHostByAddress( ::cIPServer )
      AAdd( ::acReply, "Could not establish connection to " + If( Empty( cHost ), ::cIPServer, cHost ) )
      ::Failure( oSocket, nWSAError )
   Endif

Return Nil

//----------------------------------------------------------------------------//

METHOD SendMail( cFrom, aTo, cMsg, cSubject, aFiles, aCC, aBCC, lReceipt, cHTML ) CLASS TSmtp

   Default aTo := {}, aCC := {}, aBCC := {}, aFiles := {}, lReceipt := .F.
   Default ::cClient := "smtp-client"
   Default ::cMailer := "FiveWin Mailer"

   ::cFrom    := AllTrim( cFrom )
   ::aTo      := aTo
   ::cMsg     := cMsg
   ::cSubject := cSubject
   ::aFiles   := aFiles
   ::aCC      := aCC
   ::aBCC     := aBCC
   ::lReceipt := lReceipt
   ::cHTML    := cHTML                           //RRG 29.05.2002 send HTML style email (envio de email tipo html)

   If Empty( cFrom )

      If( ::oSocket # Nil, ::oSocket:End(), Nil )
      MsgStop( "No sender was specified" + CRLF + ;
         "Message won't be sent", MSG_CAPTION )

   Elseif Empty( aTo ) .and. Empty( aCC ) .and. Empty( aBCC )

      If( ::oSocket # Nil, ::oSocket:End(), Nil )
      MsgStop( "No recipients were specified" + CRLF + ;
         "Message won't be sent", MSG_CAPTION )

   //Elseif ::cIPServer == "0.0.0.0" .or. Empty( GetHostByAddress( ::cIPServer ) )
   // cgp 09/04/2014
   Elseif ::cIPServer == "0.0.0.0" .or. ( ::lcHostFromIP .and. Empty( GetHostByAddress( ::cIPServer ) ) )

      If( ::oSocket # Nil, ::oSocket:End(), Nil )
      MsgStop( "The IP address " + ::cIPServer + " could not be resolved" + CRLF + ;
         "Make sure you're connected to the internet and" + CRLF + ;
         "check the firewall settings if applicable", MSG_CAPTION )

   Else

      If ::bConnecting != nil
         Eval( ::bConnecting )
      Endif

      ::nStatus   := ST_INIT
      ::acReply   := {}
      ::cReceived := ""
      Memory(-1)                                 // cleanup memory when sending one after another
      If ::oSocket # Nil
         ::oSocket:Connect( ::cIPServer )
      Else
         ::Failure()
      Endif

   Endif

Return Nil

//----------------------------------------------------------------------------//

METHOD Priority() CLASS TSmtp

   Local nType

   Do Case
   Case Upper( ::cPriority ) == "HIGH"
      nType := 1
   Case Upper( ::cPriority ) == "LOW"
      nType := 5
   Otherwise
      nType := 3
   EndCase

Return nType

//----------------------------------------------------------------------------//

METHOD Failure( oSocket, nWSAError, cReply ) CLASS TSmtp

   Local aStage := { "ST_INIT", ;
                     "ST_CONNECTED", ;
                     "ST_RESET", ;
                     "ST_MAILFROM", ;
                     "ST_RCPTTO", ;
                     "ST_DATA", ;
                     "ST_SENT", ;
                     "ST_QUIT", ;
                     "ST_DONE", ;
                     "ST_ERROR", ;
                     "ST_AUTH0", ;
                     "ST_AUTH", ;
                     "ST_USER", ;
                     "ST_PASS" }

   Default oSocket := ::oSocket, nWSAError := WSAGetLastError(), cReply := ""

   If ::nStatus >= ST_INIT .and. ::nStatus <= ST_LAST
      ::cError := "Stage: " + aStage[ ::nStatus + 1 ] + CRLF
   Else
      ::cError := ""
   Endif
   ::nStatus := ST_ERROR
   ::cError += "IP Address: " + ::cIPServer + CRLF + CRLF
   AEval( ::acReply, {|cReply| ::cError += cReply + CRLF } )
   If nWSAError # 0
      ::cError += "WSA Error Code: " + AllTrim( Str( nWSAError ) )
   Endif

   /*
   If ::bFailure # Nil
      Eval( ::bFailure )
   Endif
   If( oSocket # Nil, oSocket:End(), Nil )
   */

   // Antonio suggested change here ...

   If ::bFailure != nil
      Eval( ::bFailure, oSocket, nWSAError, cReply )
   Endif
   oSocket:ENd()

Return Self

//----------------------------------------------------------------------------//

Static Function DTtoEDT( dDate, cTime, nGMT )

// Local aWeek  := { "Sun", "Mon", "Tue", "Wed", "Thu", "Fry", "Sat" } 
   Local aWeek  := { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }  // 30.03.2010
   Local aMonth := { "Jan", "Feb", "Mar", "Apr", "May", "Jun", ;
                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }
   Local cGMT

   If nGMT != 0
      cGMT := " " + If( nGMT > 0, "+" , "-" ) + StrZero( Abs( nGMT ), 2 ) + "00"
   Else
      // cGMT := ""
      cGMT := " -0000"   // 30.03.2010
   Endif

Return aWeek[ Dow( dDate ) ]    + ", " + LTrim( Str( Day( dDate ) ) )  + " " + ;
       aMonth[ Month( dDate ) ] + " "  + LTrim( Str( Year( dDate ) ) ) + " " + ;
       cTime + cGMT

//----------------------------------------------------------------------------//

Static Function Today( nGMT )
   Local dDate := Date(), cGMT
   If nGMT != 0
      cGMT := " " + If( nGMT > 0, "+" , "-" ) + StrZero( Abs( nGMT ), 2 ) + "00"
   Else
      cGMT := ""
   Endif
Return SubStr( CDoW( dDate ), 1, 3 )   + ", " + ;
       LTrim( Str( Day( dDate ), 2 ) ) + " " + ;
       SubStr( CMonth( dDate ), 1, 3 ) + " " + ;
       Str( Year( dDate ), 4 )         + " " + ;
       Time() + cGMT

//----------------------------------------------------------------------------//

Static Function AToStr( aArray, cPrefix )

   Local cStr := "", nI, nLen := Len( aArray )

   Default cPrefix := ""

   If nLen > 0
      cStr := cPrefix
   Endif

   For nI := 1 To nLen
      cStr += AllTrim( aArray[nI] ) + If( nI < nLen, ", ", "" )
   Next

   cStr += If( ! Empty( cStr ), CRLF, "" )

Return cStr

//----------------------------------------------------------------------------//

Static Function DocType( cExt )

   Local cType

   If cExt $ "EXE*COM*OBJ*LIB*DLL*VBX*OCX*HLP*CHM"
      cType := "application/octet-stream; "
   Elseif cExt $ "ZIP*ARC*ZOO*TAR"
      cType := "application/x-zip-compressed; "
   Elseif cExt $ "HTM*HTML*SHT*SHTML*MHT*MHTML"
      cType := "text/html; "
   Elseif cExt == "CSS"
      cType := "text/css; "
   Elseif cExt $ "XML*XSL"
      cType := "text/xml; "
   Elseif cExt $ "TXT*TEXT*LOG*BAT"
      cType := "text/plain; "
   Elseif cExt == "PDF"
      cType := "application/pdf; "
   Elseif cExt $ "BMP*DIB"
      cType := "application/bmp; "
   Elseif cExt == "GIF"
      cType := "image/gif; "
   Elseif cExt $ "JPG*JPE**JPEG*JFI*JFIF*PJP"
      cType := "image/jpeg; "
   Elseif cExt $ "XLS*XLT*XLA*XLB*XLC*XLL*XLM*XLW"
      cType := "application/x-msexcel; "
   Elseif cExt $ "PPT*PPS*POT*PWZ"
      cType := "application/x-mspowerpoint; "
   Elseif cExt $ "MPG*MPE*MPEG*M1S*M1A*MP2*MPM*MPA"
      cType := "video/mpeg; "
   Elseif cExt $ "PIC*PICT*PCT"
      cType := "image/pict; "
   Elseif cExt == "PNG"
      cType := "image/png; "
   Elseif cExt $ "MOV*QT*QTL*QTS*QTX*QTI*QTI*QTIF*QDA*QDAT*QPX*QTP"
      cType := "video/quicktime; "
   Elseif cExt $ "TIF*TIFF"
      cType := "image/tiff; "
   Elseif cExt $ "AVI*VFW"
      cType := "video/avi; "
   Elseif cExt $ "DOC*RTF*WBK*DOT*WIZ"
      cType := "application/msword; "
   Elseif cExt $ "RMI*MID*WAV*CDA*MIDI*MP2*MP3*WMA*MJF*MP1*VOC*IT*XM*S3M*STM*MOD*ULT*MTM*HMI*XMI*CMF*MUS*MIZ*HMZ*MSS*GMD*MIDS*HMP"
      cType := "audio/mid; "
   Else
      cType := "application/x-unknown-content-type; "
   Endif

Return cType

//----------------------------------------------------------------------------//

Static Function FormHtml( cHTML, cSubject, cMailer )
Local cOpen := "", cClose := ""

If At( "<html>", Lower( cHTML ) ) == 0
   cOpen := ;
      '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"' + CRLF + ;
      '                      "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">' + CRLF + ;
      '<html>' + CRLF + ;
      '<head>' + CRLF + ;
      '   <title>' + cSubject + '</title>' + CRLF + ;
      '   <meta http-equiv="Content-Type"' + CRLF + ;
      '         content="text/html; charset=iso-8859-1">' + CRLF + ;
      '   <meta name="generator"' + CRLF + ;
      '         content="' + cMailer + '">' + CRLF + ;
      '</head>' + CRLF + ;
      '<body>' + CRLF

   cClose := ;
      CRLF + ;
      '</body>' + CRLF + ;
      '</html>'

Endif

Return cOpen + cHTML + cClose

//----------------------------------------------------------------------------//
// IBTC: Convert "Your Name <your@email.com>" into "your@email.com"
Static Function CleanEMail( cEMail )
Local nLeft, nRight

If ( nLeft := At( "<", cEMail ) ) > 0
   If ( nRight := At( ">", cEMail ) ) > 0
      cEMail := SubStr( cEMail, nLeft + 1, nRight - nLeft - 1 )
   Else
      cEMail := SubStr( cEMail, nLeft + 1 )
   Endif
Endif

Return AllTrim( cEMail )

//----------------------------------------------------------------------------//

Static Function TmpFile()
Local cTmpDir := GetEnv( "TEMP" ) + "\"          // LK Mar/26/2008 added path to avoid file being created in _SET_DEFAULT directory
Local cTmpName := "__temp"

Do While File( cTmpName := cTmpDir + "__" + StrZero( nRandom( 99999 ), 5 ) + ".tmp" )
Enddo
FClose( FCreate( cTmpName ) )

Return cTmpName

//----------------------------------------------------------------------------//

static Function CharsetIso8859()

   local c := "charset="
   
   c += "iso"
   c += "-"
   c += "8859"
   c += "-"
   c += "1"

return c


//---------------------------------------------------------------------------//

// dfl - Return the file name without converting it to upper case.

function cFileNoPathSmtp( cPathMask )  // returns just the filename no path

    local n := RAt( "\", cPathMask )

return ( If( n > 0 .and. n < Len( cPathMask ),;
                  Right( cPathMask, Len( cPathMask ) - n ),;
                  If( ( n := At( ":", cPathMask ) ) > 0,;
                      Right( cPathMask, Len( cPathMask ) - n ),;
                      cPathMask ) ) )

//---------------------------------------------------------------------------//

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Posts: 8523
Joined: Tue Dec 20, 2005 07:36 PM

Re: Modificación TSMTP.prg

Posted: Wed Apr 30, 2014 02:12 PM

Hola, tienes un ejemplo sencillo de cómo utilizar esta clase?

Muchas gracias

Salu2.

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 1446
Joined: Mon Oct 10, 2005 02:38 PM

Re: Modificación TSMTP.prg

Posted: Wed Apr 30, 2014 10:03 PM
karinha wrote:Hola, tienes un ejemplo sencillo de cómo utilizar esta clase?

Muchas gracias

Salu2.

Sinceramente no.
No tengo el código suficientemente aislado para que funcione.

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Continue the discussion