SMTP / SMTPS‎ > ‎

BASIC Windows Sockets

This example creates a connection with gmail using port 587
It demonstrates how to use the Windows Sockets API in clients for SMTP, TCP or HTTP.


#COMPILE EXE
                   
#INCLUDE "WIN32API.inc"    
#INCLUDE "WinTLS.inc" ' WSA declarations etc

$DEBUG_FILE = "Sock_dbg.txt"  

$MailHost   = "smtp.gmail.com"

GLOBAL hDbg AS LONG
      

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION SockSend( hSoc AS LONG, sToSend AS STRING ) AS LONG
         
  LOCAL RetVal, WSAErr AS LONG
 
    RetVal = ssend( hSoc, STRPTR(sToSend), LEN(sToSend), BYVAL 0)
    IF RetVal = %SOCKET_ERROR THEN
      WSAErr = WSAGetLastError() '
      PRINT #hDbg, "**** Error:" + STR$(WSAErr) + " sending"
      FUNCTION = -11 : EXIT FUNCTION
    END IF '
PRINT #hDbg, "Sending: " + sToSend 
                 
END FUNCTION 

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION SockRecv( hSoc AS LONG, sReply AS STRING ) AS LONG
          
  LOCAL cbData, WSAErr AS LONG

    sReply = NUL$(512)
    cbData = rrecv( hSoc, STRPTR(sReply), LEN(sReply), 0)
    IF cbData = %SOCKET_ERROR THEN
      WSAErr = WSAGetLastError() '
      PRINT #hDbg, "**** Error:" + STR$(WSAErr) + " Receiving"
      FUNCTION = -12 : EXIT FUNCTION
    END IF '
PRINT #hDbg, "Received" + STR$(cbData) + " bytes of data" + $CRLF + "Response: " + LEFT$(sReply, cbData)

END FUNCTION


'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION SockConnect( BYVAL wPort AS LONG, sAddr AS STRING ) AS LONG
                   
  LOCAL RetVal, hSoc, ns, pid, hLst, cbData, WSAErr AS LONG
  LOCAL sTemp  AS STRING
  LOCAL wDat      AS WSAdata
  LOCAL SockInfo  AS Sockaddr_in
  LOCAL zBuff     AS ASCIIZ * 512
  LOCAL HostInfo  AS hostent 
  LOCAL pHostInfo AS hostent PTR    ' struct

                  
          
    DO

      '- Initialize the WinSock subsystem.
      RetVal = WSAStartup( &H101, wDat )
      IF RetVal = %SOCKET_ERROR THEN '
        PRINT #hDbg, "Error" +STR$(GetLastError())+ " returned by WSAStartup"
        FUNCTION = -1 : EXIT LOOP
      END IF ' PRINT #hDbg, "----- WinSock Initialized"
      '=================
 
           
      '- get a socket handle      
      hSoc = socket( %PF_INET, %SOCK_STREAM, 0 )
      IF hSoc = %INVALID_SOCKET THEN '
        WSAErr = WSAGetLastError() '
        PRINT #hDbg, "**** Error:" + STR$(WSAErr) + " creating socket" + ""
        FUNCTION = -2 : EXIT LOOP
      END IF
      '=================
                         
  
      zBuff = sAddr
      pHostInfo = gethostbyname(zBuff)  
      IF pHostInfo = 0 THEN '
        WSAErr = WSAGetLastError() '
        PRINT #hDbg, "**** Error returned by gethostbyname" + ""
        SELECT CASE WSAErr      
          CASE %WSAHOST_NOT_FOUND : PRINT #hDbg, "Host not found."
          CASE %WSATRY_AGAIN      : PRINT #hDbg, "Nonauthoritative host not found or serverfail"
          CASE %WSANO_RECOVERY    : PRINT #hDbg, "Non-recoverable errors, formerr, refused, notimp."
          CASE %WSANO_DATA        : PRINT #hDbg, "Valid name, no data record of requested type."
        END SELECT
        FUNCTION = -4 : EXIT LOOP
      END IF
      '=================
                
             
      '- Check the host info
      CopyMemory BYVAL VARPTR(hostinfo), BYVAL pHostinfo, LEN(hostinfo) ' Copy Structure locally
      IF hostinfo.h_addr <> %AF_INET THEN '
        PRINT #hDbg, "**** Error: gethostbyname failed"
        FUNCTION = -5 : EXIT LOOP
      END IF
      '=================
               
     
      '- set the socket information 
      hLst = hostinfo.h_list
      hLst = CVL(PEEK$(hLst,4))
      SockInfo.sin_addr.s_addr = CVL(PEEK$(hLst, 4)) ' PRINT #hDbg, "**** addr" + SockInfo.sin_addr.s
      SockInfo.sin_family = %AF_INET
      SockInfo.sin_port   = htons(wPort) ' Convert to network ordering  
      sockinfo.sin_zero   = STRING$(8, $NUL) ' lpaddr.s_addr 
'     LOCAL b AS BYTE PTR
'     b = VARPTR(SockInfo.sin_addr.s_addr) 'return IP address of connection
'     PRINT #hDbg, "ipAddress=" + USING$("#_.#_.#_.#", @b, @b[1], @b[2], @b[3])
      '=================


      RetVal = cconnect( hSoc, SockInfo, SIZEOF(SockInfo) )
      IF RetVal <> 0 THEN
        WSAErr = WSAGetLastError() '
        PRINT #hDbg, "**** Error:" + STR$(WSAErr) + " connecting to " + TRIM$(zBuff) + ""
        FUNCTION = -6 : EXIT LOOP
      END IF
      '=================
               
                     
      IF SockRecv( hSoc, sTemp ) < 0 THEN EXIT LOOP ' recover connection response
      '================= 


      sTemp = "EHLO MyDomain.com" + $CRLF
      IF SockSend( hSoc, sTemp ) < 0 THEN FUNCTION = -7 : EXIT LOOP
      SLEEP 1000 ' allow time for response    220 mx.google.com ESMTP n29sm29320276wae.4
      IF SockRecv( hSoc, sTemp ) < 0 THEN FUNCTION = -8 : EXIT LOOP
      '=================        
             

      sTemp = "AUTH LOGIN " + $CRLF '
      IF SockSend( hSoc, sTemp ) < 0 THEN FUNCTION = -9 : EXIT LOOP
      SLEEP 1000 ' allow time for response
      IF SockRecv( hSoc, sTemp ) < 0 THEN FUNCTION = -10 : EXIT LOOP
      '=================


      '..........

      '..........

      '..........


      EXIT LOOP
    LOOP
        
         

    '- stop winsock
    closesocket hSoc
    wsaCleanup
    '=================
           

END FUNCTION


'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION WINMAIN() AS LONG
                 
  LOCAL RetVal, hDlg AS LONG
   
    hDbg = FREEFILE : OPEN $DEBUG_FILE FOR OUTPUT LOCK WRITE AS hDbg '

    RetVal = SockConnect( 587, $MailHost )

  MSGBOX "All Done",64,"RetVal="+STR$(RetVal)

END FUNCTION

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

example in powerbasic