SMTPS - sending emails via gmail using SSL/TLS
-
- User
- Posts: 43
- Joined: Tue Jul 10, 2007 8:09 pm
SMTPS - sending emails via gmail using SSL/TLS
I have just finished a project that required me to send an email from an appplication using googles gmail
smtp.gmail.com
Writing the SMTP dialog with error handling can be time consuming, but not too much trouble to implement on port 25. Google however only accepts SMTP email on port 465 over an SSL encrypted connection. This is a large popthole, because the implementation of SLL requires intimate knowledge off all kinds of things most of us could care less about.
After a great deal of searching I found socket tools www.catalys.com and an open source library, cryptlib that provides this functionality.
I have detailed how to use cryptlib and provided headers and source code examples here
http://www.coastrd.com
I would appreciate it if someone could make the simple conversion from powerbasic to purebasic so I can offer the code for this excellent compiler.
smtp.gmail.com
Writing the SMTP dialog with error handling can be time consuming, but not too much trouble to implement on port 25. Google however only accepts SMTP email on port 465 over an SSL encrypted connection. This is a large popthole, because the implementation of SLL requires intimate knowledge off all kinds of things most of us could care less about.
After a great deal of searching I found socket tools www.catalys.com and an open source library, cryptlib that provides this functionality.
I have detailed how to use cryptlib and provided headers and source code examples here
http://www.coastrd.com
I would appreciate it if someone could make the simple conversion from powerbasic to purebasic so I can offer the code for this excellent compiler.
Re: SMTPS - sending emails via gmail using SSL/TLS
Just start the conversion yourself and if you don't success, post the code part where you are locked.
Re: SMTPS - sending emails via gmail using SSL/TLS
Mike, I agree with fred. I successfully translated a rather big project from powerbasic to purebasic without any problems. It will be difficult at first but it get easier when you get used to the syntax.
-
- User
- Posts: 43
- Joined: Tue Jul 10, 2007 8:09 pm
Re: SMTPS - sending emails via gmail using SSL/TLS
Be happy to, but I don't have a purebasic compiler. Perhaps I should have a good stab at it and then post the code for comments?
Re: SMTPS - sending emails via gmail using SSL/TLS
... you want to work on doing code translations without using the compiler?
If you want to use PureBasic, then by all means do so, but buy it.
If you just want to provide generic libraries for coders, I'd suggest creating C libraries that can then be interfaced with anything.
If you want to use PureBasic, then by all means do so, but buy it.
If you just want to provide generic libraries for coders, I'd suggest creating C libraries that can then be interfaced with anything.
-
- User
- Posts: 43
- Joined: Tue Jul 10, 2007 8:09 pm
Re: SMTPS - sending emails via gmail using SSL/TLS
Yes did that. I was offering to support this language over powerbasic if you guys are willing to give a few minutes of your time
Re: SMTPS - sending emails via gmail using SSL/TLS
Just use the demo version.
-
- User
- Posts: 43
- Joined: Tue Jul 10, 2007 8:09 pm
Re: SMTPS - sending emails via gmail using SSL/TLS
A DEMO! holy smoke, you mean there is a demo for this language!
In ten years, powerbasic could not come up with one, so I just assumed it was a physical impossability...
Demo installed.
FIrst problem: converting function prototypes:
C (http://www.coastrd.com/cryptlib-h)
BASIC (http://www.coastrd.com/smtps/cryptlib/c ... header-inc)
second problem:
Calling functions in a statically linked dll (http://www.coastrd.com/smtps/cryptlib/basic-smtps)
Third problem:
Sleep() without calling windows API (restricted in demo version)
In ten years, powerbasic could not come up with one, so I just assumed it was a physical impossability...
Demo installed.
FIrst problem: converting function prototypes:
C (http://www.coastrd.com/cryptlib-h)
BASIC (http://www.coastrd.com/smtps/cryptlib/c ... header-inc)
Code: Select all
DECLARE FUNCTION cryptInit STDCALL LIB "cl32.dll" ALIAS "cryptInit"() AS LONG
DECLARE FUNCTION cryptCreateSession STDCALL LIB "cl32.dll" ALIAS "cryptCreateSession" (_
BYVAL pSession AS LONG PTR,_
BYVAL cryptUser AS LONG,_
BYVAL SessionType AS LONG ) AS LONG
DECLARE FUNCTION cryptSetAttributeString STDCALL LIB "cl32.dll" ALIAS "cryptSetAttributeString" (_
BYVAL hCrypt AS LONG,_
BYVAL CryptAttType AS LONG,_
BYVAL pBuff AS DWORD,_
BYVAL StrLen AS LONG ) AS LONG
Calling functions in a statically linked dll (http://www.coastrd.com/smtps/cryptlib/basic-smtps)
Code: Select all
RetVal = CryptCreateSession( VARPTR(hSess), %CRYPT_UNUSED, %CRYPT_SESSION_SSL )
RetVal = CryptSetAttributeString( hSess, CRYPT_SESSINFO_SERVER_NAME, STRPTR(sSrvr), LEN(sSrvr) )
Sleep() without calling windows API (restricted in demo version)
Code: Select all
'- Recover response
sReply = ""
WHILE PARSECOUNT(sReply, $CRLF)-1 < nRetLn
Totms = 0
DO
SLEEP 20 ' Wait for a response
Totms = Totms + 20 '
IF Totms > %SMTP_RESPONSE_TIMEOUT THEN
sErr = "Response timeout >" + STR$(%SMTP_RESPONSE_TIMEOUT) + "m/s"
FUNCTION = -28 : EXIT FUNCTION
END IF '
PRINT #hDbg, STR$(Totms) + "m/s" ', LEN(sReply)=" +STR$(LEN(sReply))
RetVal = CryptPopData( hCrypt, STRPTR(sBuff), LEN(sBuff), VARPTR(BytesReply) )
IF RetVal <> %CRYPT_OK THEN
sErr = "CryptPopData ERROR: "+Err2Str(RetVal)+" - "+ErrExStr(hCrypt)
FUNCTION = -29 : EXIT FUNCTION
ELSEIF BytesReply > 0 THEN
sReply = sReply + LEFT$(sBuff, BytesReply) '
Last = LEN(sReply) '
PRINT #hDbg, "Rply:" + STR$(BytesReply) + " Bytes: " + $CRLF + LEFT$(sBuff, BytesReply)
pByte = STRPTR(sReply) ' Check last line for SMTP code follwed by space
IF Last > 5 AND @pByte[Last-1] = 10 AND @pByte[Last-2] = 13 THEN ' CRLF
FOR k = 3 TO Last ' PRINT #hDbg, "CharNum=" + STR$(Last-k+1) + ", " + CHR$(@pByte[Last-k])
IF @pByte[Last-k] = 10 AND @pByte[Last-k+4] = 32 THEN EXIT DO ' Space not a hyphen "-", Response complete
IF k = last AND @pByte[Last-k+3] = 32 THEN EXIT DO ' Space not a hyphen "-", Response complete
NEXT
END IF
END IF
LOOP ' PRINT #hDbg, BytesToHexPtr( STRPTR(sBuff), BytesReply )
WEND
Re: SMTPS - sending emails via gmail using SSL/TLS
Use the native Delay().Mike Trader wrote:Third problem:
Sleep() without calling windows API (restricted in demo version)
Here's a rough workover of your function as well (just for kicks)

Code: Select all
;- Recover response
sReply.s = ""
While PARSECOUNT(sReply, #CRLF$)-1 < nRetLn
Totms = 0
;Do
Repeat
;SLEEP 20 ; Wait for a response
Delay(20) ; Wait for a response
Totms = Totms + 20 ;
If Totms > #SMTP_RESPONSE_TIMEOUT
sErr = "Response timeout >" + Str(#SMTP_RESPONSE_TIMEOUT) + "m/s"
;function = -28 : EXIT function
ProcedureReturn -28
EndIf ;
PRINT #hDbg, Str(Totms) + "m/s" ;, LEN(sReply)=" +str(LEN(sReply))
RetVal = CryptPopData( hCrypt, STRPTR(sBuff), Len(sBuff), VARPTR(BytesReply) )
If RetVal <> #CRYPT_OK THEN
sErr = "CryptPopData ERROR: "+Err2Str(RetVal)+" - "+ErrExStr(hCrypt)
;function = -29 : EXIT function
ProcedureReturn -29
ElseIf BytesReply > 0
sReply = sReply + Left (sBuff, BytesReply) ;
last = Len(sReply) ;
PRINT #hDbg, "Rply:" + Str(BytesReply) + " Bytes: " + #CRLF$ + Left (sBuff, BytesReply)
*pByte = @sReply ; Check last line for SMTP code follwed by space
If last > 5 And PeekC(*pByte + last-1) = 10 And PeekC(*pByte + last-2) = 13 ; CRLF
For k = 3 To last ; PRINT #hDbg, "CharNum=" + str(Last-k+1) + ", " + chr(@pByte[Last-k])
If PeekC(*pByte + last-k) = 10 And PeekC(*pByte +last-k+4) = 32
;EXIT DO ; Space not a hyphen "-", Response complete
Break ;exit Repeat:ForEver
EndIf
If k = last And PeekC(*pByte + last-k+3) = 32
;EXIT DO ; Space not a hyphen "-", Response complete
Break ;exit Repeat:ForEver
EndIf
Next
EndIf
EndIf
;loop
ForEver ; PRINT #hDbg, BytesToHexPtr( STRPTR(sBuff), BytesReply )
Wend
-
- User
- Posts: 43
- Joined: Tue Jul 10, 2007 8:09 pm
Re: SMTPS - sending emails via gmail using SSL/TLS
oh thank you for that 
So now I just need to know how PureBasic would call a function in a .dll.

So now I just need to know how PureBasic would call a function in a .dll.
Re: SMTPS - sending emails via gmail using SSL/TLS
Please take a look to the doc, it was a pain to write
http://www.purebasic.com/documentation/
For the DLL:
http://www.purebasic.com/documentation/ ... index.html

http://www.purebasic.com/documentation/
For the DLL:
http://www.purebasic.com/documentation/ ... index.html
-
- User
- Posts: 43
- Joined: Tue Jul 10, 2007 8:09 pm
Re: SMTPS - sending emails via gmail using SSL/TLS
Ah. I downloaded the .pdf manual and looked in there, then looked at all the installed examples but missed the online manual...
Dynamic linking is fine, but is Static linking possible?
So using the form:
Result = CallFunctionFast(*FunctionPointer [,Parameter1 [, Parameter2...]])
(posted here as a reference)
Dynamic linking is fine, but is Static linking possible?
So using the form:
Result = CallFunctionFast(*FunctionPointer [,Parameter1 [, Parameter2...]])
Code: Select all
If OpenLibrary(0, "cl32.dll")
*pCreateSession= GetFunction(0, "cryptCreateSession")
If *pCreateSession
RetVal = CallFunctionFast(*pCreateSession, *hSess, CRYPT_UNUSED, CRYPT_SESSION_SSL )
EndIf
; other library calls
CloseLibrary(0)
EndIf
Re: SMTPS - sending emails via gmail using SSL/TLS
If you have an import library for the dll then use Import for load time linking of the dll.
I may look like a mule, but I'm not a complete ass.
-
- User
- Posts: 43
- Joined: Tue Jul 10, 2007 8:09 pm
Re: SMTPS - sending emails via gmail using SSL/TLS
Ah great. Yes there is a .lib file for the project. I will need to include it with the source
So then I can use
Import "cl32.dll"
RetVal = cryptCreateSession( *hSess, CRYPT_UNUSED, CRYPT_SESSION_SSL )
.
.
.
This is all the remains to be translated:
So then I can use
Import "cl32.dll"
RetVal = cryptCreateSession( *hSess, CRYPT_UNUSED, CRYPT_SESSION_SSL )
.
.
.
This is all the remains to be translated:
Code: Select all
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION SMTPTLS( sSrvr AS STRING,_
sUser AS STRING,_
sPass AS STRING,_
sFrom AS STRING,_
sTo AS STRING,_
sBody AS STRING,_
sErr AS STRING ) AS LONG
LOCAL RetVal, hSess, BytesReply, nRetLn AS LONG
LOCAL sBuff, sReply, sEnc AS STRING
'- Initialize the Library
RetVal = CryptInit()
IF RetVal <> %CRYPT_OK THEN sErr = "CryptInit ERROR: "+Err2Str(RetVal) : FUNCTION = -2 : EXIT FUNCTION
DO
'- Create the session
RetVal = CryptCreateSession( VARPTR(hSess), %CRYPT_UNUSED, %CRYPT_SESSION_SSL )
IF RetVal <> %CRYPT_OK THEN sErr = "CryptCreateSession ERROR: "+Err2Str(RetVal) : FUNCTION = -4 : EXIT DO
'- Add the server name "smtp.gmail.com"
RetVal = CryptSetAttributeString( hSess, %CRYPT_SESSINFO_SERVER_NAME, STRPTR(sSrvr), LEN(sSrvr) )
IF RetVal <> %CRYPT_OK THEN sErr = "SERVER_NAME ERROR: "+Err2Str(RetVal)+" "+ErrExStr(hSess) : FUNCTION = -6 : EXIT DO
'- Specify the Port
RetVal = CryptSetAttribute( hSess, %CRYPT_SESSINFO_SERVER_PORT, %TCP_PORT )
IF RetVal <> %CRYPT_OK THEN sErr = "SERVER_PORT ERROR: "+Err2Str(RetVal)+" "+ErrExStr(hSess) : FUNCTION = -8 : EXIT DO
'- Activate the session
RetVal = CryptSetAttribute( hSess, %CRYPT_SESSINFO_ACTIVE, 1 )
IF RetVal <> %CRYPT_OK THEN sErr = "SESSINFO_ACTIVE ERROR: "+Err2Str(RetVal)+" "+ErrExStr(hSess) : FUNCTION = -12 : EXIT DO
'- Discard initial response created by connecting
sBuff = NUL$(255)
RetVal = CryptPopData( hSess, STRPTR(sBuff), LEN(sBuff), VARPTR(BytesReply) )
IF RetVal <> %CRYPT_OK THEN sErr = "CryptPopData1 ERROR: "+Err2Str(RetVal)+" "+ErrExStr(hSess) : FUNCTION = -27 : EXIT DO
'- MIME dialog
RetVal = TLSPushPop(hSess, sErr, sReply, 1, "EHLO " + $CRLF) '
IF RetVal < 0 THEN FUNCTION = RetVal : EXIT DO
IF RetVal <> 250 THEN sErr = "EHLO Failed: "+sErr : FUNCTION = -31 : EXIT DO
RetVal = TLSPushPop(hSess, sErr, sReply, 1, "AUTH LOGIN " + $CRLF) '
IF RetVal <> 334 THEN sErr = "AUTH Failed: "+sErr : FUNCTION = -16 : EXIT DO
RetVal = TLSPushPop(hSess, sErr, sReply, 1, MimeEncode(sUser) + $CRLF) ' Username
IF RetVal <> 334 THEN sErr = "user Failed: "+sErr : FUNCTION = -18 : EXIT DO
RetVal = TLSPushPop(hSess, sErr, sReply, 1, MimeEncode(sPass) + $CRLF) ' Password
IF RetVal <> 235 THEN sErr = "pass Failed: "+sErr : FUNCTION = -20 : EXIT DO
RetVal = TLSPushPop(hSess, sErr, sReply, 1, "MAIL FROM: <" + sFrom + ">" + $CRLF) ' Sender
IF RetVal <> 250 THEN sErr = "MAIL FROM Failed: "+sErr : FUNCTION = -22 : EXIT DO
RetVal = TLSPushPop(hSess, sErr, sReply, 1, "RCPT TO: <" + sTo + ">" + $CRLF) ' Recipient
IF RetVal <> 250 THEN sErr = "RCPT TO Failed: "+sErr : FUNCTION = -24 : EXIT DO
RetVal = TLSPushPop(hSess, sErr, sReply, 1, "DATA " + $CRLF) ' Body begins
IF RetVal <> 354 THEN sErr = "DATA Failed: "+sErr : FUNCTION = -26 : EXIT DO
RetVal = TLSPushPop(hSess, sErr, sReply, 1, sBody + $CRLF + "." + $CRLF) ' Body
IF RetVal <> 250 THEN sErr = "body Failed: "+sErr : FUNCTION = -28 : EXIT DO
sErr = "Email Sent OK" : FUNCTION = 1 ' 250 2.0.0 OK - Message sent
RetVal = TLSPushPop(hSess, sErr, sReply, 1, "QUIT " + $CRLF) ' Terminate MIME
IF RetVal < 0 THEN FUNCTION = RetVal : EXIT DO
IF RetVal <> 221 THEN sErr = "QUIT Failed: "+sErr : FUNCTION = -39 : EXIT DO
EXIT LOOP ' done
LOOP '
IF hSess THEN CALL CryptDestroySession(hSess) ' Close the session
CALL CryptEnd() ' Close the Library
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION PBMAIN()
LOCAL RetVal AS LONG
LOCAL sBody, sErr AS STRING
hDbg = FREEFILE : OPEN $DEBUG_FILE FOR OUTPUT LOCK SHARED AS hDbg '
sBody = ""
sBody = sBody + "Date: " + MailDate() + $CRLF
sBody = sBody + "From: " + $MailFrom + $CRLF
sBody = sBody + "To: " + $MailTo + $CRLF
sBody = sBody + "Subject: " + "Gmail Test using TLS Encryption" + $CRLF + $CRLF
sBody = sBody + "Looks like this has worked!"
RetVal = SMTPTLS( $MailHost, $UserName, $Password, $MailFrom, $MailTo, sBody, sErr )
IF RetVal < 0 THEN PRINT #hDbg, "ERROR: "+sErr
CLOSE #hDbg
END FUNCTION
Re: SMTPS - sending emails via gmail using SSL/TLS
No. You import the import library for the dll, not the dll itself. You need to use Import "cl32.lib". Within the Import/EndImport statements you then list the function declarations of those functions (or symbols) you wish to import (but look out for any function decoration / name mangling etc.) At compile time the import library will then be statically linked into your exe and then you simply include the dll with your completed application.Ah great. Yes there is a .lib file for the project. I will need to include it with the source
So then I can use
Import "cl32.dll"
I may look like a mule, but I'm not a complete ass.