xsharp.eu • Send mail via smtp
Page 1 of 1

Send mail via smtp

Posted: Tue Sep 03, 2024 7:05 am
by dododo01
Hi,
following a migration from VO to Xsharp,
I can no longer send mail via smtp.
I use an object (Class authSMTP) that inherits from CMailAbstrat.
After entering the DNS alias in the RemoteHost property, in VO I see the IP and in XSharp there is nothing.

Could you help me?

Code: Select all

-------------------------------------------------------------------------------------
	LOCAL oCeMail AS CeMail
	LOCAL oCSmtp  AS authSMTP
	LOCAL oDB     AS DBserver
	LOCAL aFile   AS ARRAY
	LOCAL aTab    AS ARRAY
	LOCAL jj      AS INT
	LOCAL ii      AS INT
	
	Default(@lAuth, FALSE)
	
	// création du mail
	pCopieInfo := iif(IsNil(pCopieInfo), {}, pCopieInfo)
	oCeMail := CeMail{}
	oCeMail:Subject            := pObjet
	oCeMail:MailBody           := pBody
	oCeMail:DestList           := pEmailTo
	oCeMail:CCList             := pCopieInfo
	oCeMail:FromAddress        := pEmailFrom
	aFile := {}
	FOR ii:=1 TO ALen(aPiecesJointes)
		AAdd(aFile, aPiecesJointes[ii])
	NEXT ii
	oCeMail:AttachmentFileList := aFile
	// fin de création du mail

	// connection au SMTP et envois du mail
	oCsmtp := authSMTP{oCeMail, "RSGB2 dll"}
	oCsmtp:RemoteHost := psmtp
	IF lAuth
		oCSmtp:UserName := pUser
		oCsmtp:PassWord := pPasswd
		oCsmtp:Authority := TRUE
	ELSE
		oCsmtp:Authority := FALSE
	ENDIF
	
	// envois
	IF !oCsmtp:SendMail( pPortSmtp )
		RETURN FALSE
	ENDIF

Re: Send mail via smtp

Posted: Tue Sep 03, 2024 8:11 am
by wriedmann
Hi Dominique,
to see what is going wrong here we need to see the authSMTP class code.
Wolfgang

Re: Send mail via smtp

Posted: Tue Sep 03, 2024 8:15 am
by dododo01
here is the code of the authSmtp class:

Code: Select all

CLASS authSMTP INHERIT CMailAbstract
	PROTECT oEmail          	AS CEmail
	PROTECT cMailApplication    AS STRING
	//
	PROTECT lAuthority 		AS LOGIC
	PROTECT cUserName2 	AS STRING
	PROTECT cPassWord2 	AS STRING
	//

METHOD  __StartData()  AS LOGIC PASCAL     
	LOCAL cBuffer       AS STRING

	cBuffer := "DATA" + CRLF

	IF ! SELF:SendRemote(cBuffer)
		RETURN FALSE
	ENDIF

	IF ! SELF:RecvRemote()
		RETURN FALSE
	ENDIF

	IF ! SELF:CheckReply()
		SELF:nError := 214
		RETURN FALSE
	ENDIF
	RETURN TRUE


METHOD  __StopSending(lSuccess)   AS LOGIC PASCAL     
	LOCAL cTemp AS STRING
	LOCAL nTemp AS DWORD

	nTemp := SELF:nError
	cTemp := SELF:cReply

	SELF:nCurState := CLOSING_CONNECTION
	SELF:Disconnect()
	SELF:nCurState := WAITING_FOR_ACTION
	IF !lSuccess
		SELF:nError := nError
		SELF:cReply := cTemp
	ENDIF
	RETURN lSuccess


ACCESS Authority 			AS LOGIC PASCAL 
	RETURN SELF:lAuthority


ASSIGN Authority( lStatus AS LOGIC) AS VOID PASCAL 
	SELF:lAuthority := lStatus

METHOD  CheckReply() AS LOGIC PASCAL    

	LOCAL c AS STRING

	c := SELF:cReply
	c := SubStr3(c, 1, 1)

	SELF:nReply := Val( SubStr3(SELF:cReply, 1, 4) )

	IF c == "1"  .OR. c == "2"  .OR. c == "3"
		SELF:nError := 0
		RETURN TRUE
	ENDIF

	IF c == "4"  .OR. c == "5"
		SELF:nError := SELF:nReply
		RETURN FALSE
	ELSE
		RETURN TRUE
	ENDIF


METHOD connect(cIP, n)   AS LOGIC PASCAL  

	LOCAL cBuffer   	AS STRING
	LOCAL nPort    	AS WORD
	LOCAL lSuccess   	AS LOGIC

	BEGIN SEQUENCE
		IF IsNumeric(n)
			nPort := n
		ELSE
			nPort := SELF:wHostPort
		ENDIF
		//
		IF ! SELF:Open()
			BREAK
		ENDIF
		//
		IF !oSocket:connect(cIP, nPort)
			SELF:nError := oSocket:Error
			BREAK
		ENDIF
		//
		IF ! SELF:RecvRemote()
			BREAK
		ENDIF
		cBuffer := iif( SELF:lAuthority, "EHLO ","HELO " )+ SELF:cDomainName + CRLF
		//
		IF ! SELF:SendRemote(cBuffer)
			BREAK
		ENDIF
		//
		IF ! SELF:RecvRemote()
			BREAK
		ENDIF
		//
		IF ! SELF:CheckReply()
			SELF:nError := 213
			BREAK
		ENDIF
		lSuccess := TRUE
	END SEQUENCE
	//
	RETURN lSuccess


METHOD Disconnect() 		AS LOGIC PASCAL 
	LOCAL cBuffer     AS STRING
	LOCAL lRet          AS LOGIC

	lRet := TRUE

	IF SELF:lSocketOpen
		cBuffer := CRLF + "." + CRLF

		lRet := SELF:SendRemote(cBuffer)

		IF lRet
			lRet := SELF:RecvRemote()
		ENDIF

		IF lRet
			lRet := SELF:CheckReply()
			IF !lRet
				SELF:nError := 215
			ENDIF
		ENDIF

		cBuffer := "QUIT" + CRLF

		IF lRet
			lRet := SELF:SendRemote(cBuffer)
		ENDIF

		IF lRet
			lRet := SELF:RecvRemote()
		ENDIF

		IF lRet
			lRet := SELF:CheckReply()
			IF !lRet
				SELF:nError := 216
			ENDIF
		ENDIF

		SUPER:Close()
	ENDIF

	RETURN lRet


ACCESS  Email()     AS cEMAIL PASCAL   
	RETURN SELF:oEmail

ASSIGN  Email(oMail AS cEMAIL)  AS cEMAIL PASCAL  
	IF IsInstanceOf(oMail, #CEmail)
		SELF:oEmail := oMail
	ENDIF
	RETURN SELF:oEmail

CONSTRUCTOR(oMail, cAppName)             

	SUPER(IPPORT_SMTP)
	//
	IF SELF:nError = 0
		SELF:TimeOut := 2000			// Default of 1000 is far to low.. get connection failures..
	ENDIF
	//
	IF IsString(cAppName)
		SELF:cMailApplication := cAppName
	ELSE
		SELF:cMailApplication := "Sherlock Software SMTP Mailer Version 1.00"
	ENDIF
	//
	IF IsInstanceOf(oMail, #CEmail)
		SELF:oEmail := oMail
	ELSE
		SELF:oEmail := CEmail{}
	ENDIF
	RETURN SELF


ACCESS PassWord 
// ACCESS PassWord AS STRING PASCAL CLASS authSMTP
	RETURN SELF:cPassWord2

ASSIGN PassWord(uVal) 
// ASSIGN PassWord(uVal) AS STRING PASCAL CLASS authSMTP
	SELF:cPassWord2 := uVal

METHOD RecvRemote() 
// METHOD RecvRemote()  AS LOGIC   CLASS authSMTP

	LOCAL lRet      	AS LOGIC
	LOCAL nSize    AS DWORD
	LOCAL cRet		AS STRING

	SELF:cReply := SELF:oSocket:GetLine()

	nSize := SLen(SELF:cReply)

	IF nSize = 0
		lRet := TRUE
	ELSE
		cRet := SELF:cReply
		SELF:nReply := Val( SubStr3(cRet, 1, 4) )
		IF SELF:nReply > 0
			lRet := TRUE
			SELF:nError := 0
		ELSE
			cRet := AllTrim(Upper(cRet))
			IF cRet = "(EST)"
				SELF:nReply := 250
				lRet := TRUE
				SELF:nError := 0
			ENDIF
		ENDIF
	ENDIF

	RETURN lRet


METHOD SendAttachedFile(cFile)  AS LOGIC PASCAL   
	LOCAL lRet      AS LOGIC
	LOCAL cBuffer   AS STRING

	cBuffer := ATTACH_BEGIN + SELF:oEmail:Boundary + CRLF
	cBuffer += B64EncFile(cFile)

	lRet := SELF:SendRaw(cBuffer)

	IF ! lRet
		SELF:oEmail:AttachmentFileList := {}
	ENDIF
	RETURN lRet


METHOD SendHeader(lFiles)	AS USUAL PASCAL   

	LOCAL  cBuffer     AS STRING
	LOCAL  cTemp      AS STRING

	Default(@lFiles, FALSE)

	SELF:nCurState := SENDING_HEADER

	SELF:oEmail:SetMailTime()

	cBuffer := "Date: " + SELF:oEmail:TimeStamp
	cBuffer += CRLF
    	//
	cBuffer += "From: "
	IF SLen(SELF:oEmail:FromName) > 0
		cBuffer += '"' + SELF:oEmail:FromName + '" '
	ENDIF
   	//
	cBuffer += "<" + SELF:oEmail:FromAddress + ">"
	cBuffer += CRLF
   	//
	cTemp := __Array2StrList(SELF:oEmail:DestList)
	cBuffer += "To: " + cTemp + CRLF
   	//
	cBuffer += "Subject: " + SELF:oEmail:Subject
	cBuffer += CRLF
   	//
	cTemp := __Array2StrList(SELF:oEmail:CCList)
	IF SLen(cTemp) > 0
		cBuffer += "Cc: " + cTemp + CRLF
	ENDIF
	//
	cTemp := __Array2StrList(SELF:oEmail:BCCList)
	IF SLen(cTemp) > 0
		cBuffer += "Bcc: " + cTemp + CRLF
	ENDIF
     //	
	cTemp := SELF:oEmail:ReplyTo
	IF SLen(cTemp) > 0
		cBuffer += "Reply-To: " + cTemp + CRLF
	ENDIF
   	//
	IF SLen(SELF:oEmail:ReturnReceipt) > 0
		cBuffer += TEMP_RETURN_RECEIPT + " " + SELF:oEmail:ReturnReceipt
		cBuffer += CRLF
	ENDIF
   	//
	IF SLen(SELF:oEmail:Cargo) > 0
		cBuffer += SELF:oEmail:Cargo + CRLF
	ENDIF
	//
	IF lFiles
		cBuffer += "Mime-Version: 1.0" + CRLF
		cBuffer += 'Content-Type: multipart/mixed;'
		cBuffer += 'boundary="'
		cBuffer += SELF:oEmail:Boundary + '"' + CRLF
	ENDIF
	//
	cBuffer += CRLF
   	//
	RETURN SELF:SendRaw(cBuffer)


METHOD SendHeaderInfo(cFrom, xTo, xCC)  AS LOGIC PASCAL    

	LOCAL i             	AS DWORD
	LOCAL nLen          AS DWORD
	LOCAL cBuffer      AS STRING
	LOCAL aTo, aCC   AS ARRAY
	LOCAL lSuccess	AS LOGIC

	BEGIN SEQUENCE
		IF IsArray(xTo)
			aTo := xTo
		ELSEIF IsString(xTo)  .AND. SLen(xTo) > 0
			aTo := {xTo}
		ELSE
			BREAK
		ENDIF
		//	
		IF IsArray(xCC)
			aCC := xCC
		ELSEIF IsString(xCC)
			IF SLen(xCC) = 0
				aCC := {}
			ELSE
				aCC := {xCC}
			ENDIF
		ELSE
			BREAK
		ENDIF
		//
		cBuffer := "MAIL FROM:<" + cFrom + ">" + CRLF
		//
		IF ! SELF:SendRemote(cBuffer)
			BREAK
		ENDIF
		//
		IF ! SELF:RecvRemote()
			BREAK
		ENDIF
		//
		IF ! SELF:CheckReply()
			SELF:nError := 211
			BREAK
		ENDIF
		//
		nLen := ALen(aTo)
		//
		FOR i := 1 TO nLen
			cBuffer := "RCPT TO:<"
			cBuffer += __GetToken(aTo[i],"<", ">", .T.)
			//
			cBuffer += ">" + CRLF
			//
			IF !SELF:SendRemote(cBuffer)
				BREAK
			ENDIF
			//
			IF ! SELF:RecvRemote()
				BREAK
			ENDIF
			//
			IF ! SELF:CheckReply()
				SELF:nError := 212
				BREAK
			ENDIF
		NEXT
		//	
		nLen := ALen(aCC)
		//
		FOR i := 1 TO nLen
			cBuffer := "RCPT TO:<"

			cBuffer += __GetToken(aCC[i],"<", ">", TRUE)

			cBuffer += ">" + CRLF
			//
			IF ! SELF:SendRemote(cBuffer)
				BREAK
			ENDIF
			//
			IF ! SELF:RecvRemote()
				BREAK
			ENDIF
			//
			IF ! SELF:CheckReply()
				SELF:nError := 212
				BREAK
			ENDIF
		NEXT
	END SEQUENCE
	lSuccess := TRUE
	RETURN lSuccess


METHOD SendMail( pPortSmtp ) 			AS LOGIC PASCAL 

	LOCAL lRet        	AS LOGIC
	LOCAL cBuffer    	AS STRING
	LOCAL aFiles		AS ARRAY
	LOCAL xx			AS DWORD
	LOCAL lFiles      	AS LOGIC
*	LOCAL lResult		AS LOGIC
	LOCAL lconnect		AS LOGIC
	LOCAL SMachine      AS STRING
*	LOCAL lResult		AS LOGIC

	SELF:nCurState := CONNECTING
	SELF:nError := 0
	
	SMachine := GetEnv("COMPUTERNAME")
	IF !IsNil(pPortSmtp)
		lconnect := SELF:connect( SELF:cHostAddress, Val(pPortSmtp) )
	ELSE
		lconnect := SELF:connect( SELF:cHostAddress, "" )
	ENDIF
	//
	IF lConnect
	//  IF SELF:connect( SELF:cHostAddress, cPort )
		IF SELF:lAuthority
			SELF:SMTPLogin()								
		ENDIF
		//
		SELF:nCurState := ESTABLISHING_SESSION
		//
		IF !SELF:SendHeaderInfo(SELF:oEmail:FromAddress, SELF:oEmail:DestList, SELF:oEmail:CCList )
			RETURN SELF:__StopSending(FALSE)
		ENDIF
		//
		IF !SELF:__StartData()
			RETURN SELF:__StopSending(FALSE)
		ENDIF
		//
		aFiles := SELF:oEmail:AttachmentFileList
		IF ALen(aFiles) > 0
			lFiles := TRUE
		ENDIF
		//	
		IF ! SELF:SendHeader(lFiles)
			RETURN SELF:__StopSending(FALSE)
		ENDIF
		//
		IF lFiles
			IF ! SELF:SendMailBody(TRUE)
				RETURN SELF:__StopSending(FALSE)
			ENDIF
			//
			FOR xx := 1 TO ALen(aFiles)
				lRet := SELF:SendAttachedFile(aFiles[xx])
			NEXT
			cBuffer := ATTACH_BEGIN + SELF:oEmail:Boundary + ATTACH_BEGIN
			IF ! SELF:SendData(cBuffer)
				RETURN SELF:__StopSending(FALSE)
			ENDIF
		ELSE
			lRet := SELF:SendMailBody(FALSE)
		ENDIF
	ELSE
		SELF:Close()
		RETURN FALSE
	ENDIF
	//
	RETURN SELF:__StopSending(lRet)

METHOD SendMailBody(lAttach)  AS LOGIC PASCAL  

	LOCAL cBuffer   AS STRING
	LOCAL lRet      AS LOGIC

	IF !IsLogic(lAttach)
		lAttach := FALSE
	ENDIF

	IF lAttach
		cBuffer := ATTACH_BEGIN + SELF:oEmail:Boundary + CRLF
		cBuffer += 'Content-Type: text/plain; '
		cBuffer += 'charset="us-ascii"' + CRLF + CRLF
		cBuffer += SELF:oEmail:MailBody
		cBuffer += CRLF + CRLF
		lRet := SELF:SendRaw(cBuffer)
	ELSE
		cBuffer := SELF:oEmail:MailBody
		lRet := SELF:SendRaw(cBuffer + CRLF)
	ENDIF
	RETURN lRet


METHOD SMTPLogin() AS LOGIC PASCAL 

	LOCAL cBuffer  	AS STRING
	LOCAL cUserID 	AS STRING
	LOCAL cPassW 	AS STRING
	LOCAL lSuccess	AS LOGIC

	cUserID := b64Enc( AllTrim( SELF:cUserName2 ) )
	cPassW := b64Enc( AllTrim( SELF:cPassWord2 ) )
	//
	BEGIN SEQUENCE
		// SELF:oDlg:odcfixedtext2:Caption := "Authenticating user " +	AllTrim( SELF:cUserName )
		cBuffer := "AUTH LOGIN " + cUserID
		cBuffer += CRLF
		IF ! SELF:SendRemote(cBuffer)
			BREAK	
		ENDIF
		//
		IF ! SELF:RecvRemote()
			BREAK	
		ENDIF
		//
		IF Left(Upper(b64Dec(SubStr( SELF:cReply,5 ))),8 ) == "PASSWORD"
			//
			IF ! SELF:CheckReply()
				SELF:nError := 213
				BREAK	
			ENDIF
			//
			cBuffer := cPassW
			cBuffer += CRLF
			IF ! SELF:SendRemote(cBuffer)
				BREAK
			ENDIF

			IF ! SELF:RecvRemote()
				BREAK	
			ENDIF

			IF ! SELF:CheckReply()
				SELF:nError := 213
				BREAK	
			ENDIF
		ENDIF
		lSuccess := TRUE
	END SEQUENCE
	RETURN lSuccess


ACCESS UserName 
// ACCESS UserName AS STRING PASCAL CLASS authSMTP
	RETURN SELF:cUserName2


ASSIGN UserName(uVal) 
// ASSIGN UserName(uVal) AS STRING PASCAL CLASS authSMTP
	RETURN SELF:cUserName2 := uVal
	

Re: Send mail via smtp

Posted: Wed Sep 25, 2024 3:58 pm
by Cyril
Hi

Thank you for your investigations.
We found a solution, we use the standard method SMTPSendMail

Cyril