Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

SMTP - Send simple email

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PBWin/PBCC SMTP - Send simple email

    SMTP (Simple Mail Transfer Protocol) is the most common, basic protocol for sending an email on the Internet. Having its roots in 1982, it is still at the heart of email sending today in 2014, although many email servers these days lean towards ESMTP - Enhanced SMTP. ESMTP provides, amongst other things, authentication (username & password).

    Discussion here.

    The ESMTP PB version of this demo also supports plain SMTP (as do all ESMTP clients), so I recommend using that instead of this, but I think it's important to have a pure-SMTP demo to learn from (ESMTP does afterall still use SMTP at its heart), which is why I leave this demo here.

    Code:
    #COMPILE EXE
     
    $SMTP_SERV = "mail.myisp.com"
    %SMTP_PORT = 25
     
    FUNCTION SendEmail (sEmailTo AS STRING, sEmailFrom AS STRING, sSubject AS STRING, sMessage AS STRING) AS LONG  '// Returns 0 if successful, or errorcode
        LOCAL hTCP AS DWORD, sLocalHost AS STRING, sBuf AS STRING
    
        hTCP = FREEFILE
        TCP OPEN PORT %SMTP_PORT AT $SMTP_SERV AS hTCP
        IF ERR THEN FUNCTION = -1: GOTO ErrSMTP
    
        TCP RECV hTCP, 4096, sBuf
        IF LEFT$(sBuf, 3) <> "220" THEN FUNCTION = -2: GOTO ErrSMTP
    
        HOST NAME TO sLocalHost
    
        TCP PRINT hTCP, "HELO " & sLocalHost
        TCP RECV hTCP, 4096, sBuf
        IF LEFT$(sBuf, 3) <> "250" THEN FUNCTION = -3: GOTO ErrSMTP
    
        TCP PRINT hTCP, "MAIL FROM:" & sEmailFrom
        TCP RECV hTCP, 4096, sBuf
        IF LEFT$(sBuf, 3) <> "250" THEN FUNCTION = -4: GOTO ErrSMTP
    
        TCP PRINT hTCP, "RCPT TO: " & sEmailTo
        TCP RECV hTCP, 4096, sBuf
        IF LEFT$(sBuf, 3) <> "250" THEN FUNCTION = -5: GOTO ErrSMTP
    
        TCP PRINT hTCP, "DATA"
        TCP RECV hTCP, 4096, sBuf
        IF LEFT$(sBuf, 3) <> "354" THEN FUNCTION = -6: GOTO ErrSMTP
    
        TCP PRINT hTCP, "Date: "    + DATE$
        TCP PRINT hTCP, "From: "    + sEmailFrom
        TCP PRINT hTCP, "To: "      + sEmailTo
        'TCP PRINT hTCP, "Cc: " '// use this field if you want to change a BCC'd email into a CC'd email
        TCP PRINT hTCP, "Subject: " + sSubject
        TCP PRINT hTCP, "X-Mailer: PB SMTP client demo"
        TCP PRINT hTCP, ""
    
        TCP PRINT hTCP, sMessage
        TCP PRINT hTCP, ""
    
        TCP PRINT hTCP, "."
        TCP RECV hTCP, 4096, sBuf
        IF LEFT$(sBuf, 3) <> "250" THEN FUNCTION = -7: GOTO ErrSMTP
    
        TCP PRINT hTCP, "QUIT"
        TCP RECV hTCP, 4096, sBuf
        IF LEFT$(sBuf, 3) <> "221" THEN FUNCTION = -8: GOTO ErrSMTP
    
        TCP CLOSE hTCP
        EXIT FUNCTION
    
    ErrSMTP:
        TCP CLOSE hTCP
        ? "ERROR. Last msg from server = " & sBuf
    END FUNCTION
    
    
    FUNCTION PBMAIN () AS LONG
    LOCAL lSent AS LONG, sEmailTo AS STRING, sEmailFrom AS STRING, sSubject AS STRING, sMessage AS STRING
    
    sEmailTo = CHR$(34) & "To Name" & CHR$(34) & " <[email protected]>"
    sEmailFrom = CHR$(34) & "From Name" & CHR$(34) & " <[email protected]>"
    sSubject = "Testing one two three"
    sMessage = "Message line 1" & $CRLF & "Line 2" & $CRLF & "Line 3"
    
    lSent = SendEmail(sEmailTo, sEmailFrom, sSubject, sMessage)
    ? "Sent = " & STR$(lSent) & " (0 = success)"
    
    #IF %DEF(%PB_CC32)
     STDOUT "Done, press any key to continue...";: WAITKEY$
    #ENDIF
    END FUNCTION
    Send to multiple email addresses (ie. BCC and CC emails):
    To send to multiple email addresses you simply send the "RCPT TO:" field over and over, once for each email address ... for which you should receive something like "250 recipient <email address> ok" with each address.

    Essentially, every email starts out as a BCC - the only difference between BCC and CC is that a CC message includes in its header who it was emailed to (so if you don't include the CC part it will remain a BCC), ie:
    From: "Tech Support" <[email protected]>
    To: [email protected]
    Cc: [email protected], [email protected]

    (note: the CC header field doesn't tell the server who to send the email to, we have to repeatedly use RCPT TO for that... the CC header field on the other hand is purely to provide recipients with the information regarding who else has been sent the email)

    ESMTP
    ESMTP (Enhanced SMTP), for all intents and purposes in regards to this demo is essentially just SMTP but with one additional step at the start - using your username & password to authenticate you. It's also very easy to implement, and here I provide a demo similar to the above, that has SMTP and ESMTP (both PLAIN and LOGIN auth types) support:
    Last edited by Gary Beene; 5 Aug 2014, 07:56 PM. Reason: added link to discussion thread
    -

  • #2
    This code works fine except that the Time received is always shown as 12:00am. Am using Thunderbird so may be a function of that..... curious.

    Comment


    • #3
      The program is using the DATE$ system variable, which is wrong on a few points. First, it only includes the date, not the time (which is likely the reason you're seeing that behavior). Second, even if you combined DATE$ and TIME$ together, that's not actually an standard-compliant date and time format. It's using a localized time without specifying a timezone.

      SMTP servers and mail clients are generally designed to be fairly flexible in terms of how a message is timestamped, but it should look like this: [day] [3 letter month] [year] [hour]:[minutes]:[seconds] [tz info], It may also include the day of week at the beginning. For example: Tue, 24 Apr 2018 18:46:00 +0000 (UTC)

      There are a few other alternative date/time formats that are recognized as well, but this is the most common one.

      For other developers reading this, I'll also point out that although the original post is correct that ESMTP provides for authentication, many mail servers today will not accept mail from a MUA (mail user agent, i.e.: a client application) on port 25. Port 25 is used for MTAs (mail transfer agents, i.e.: other mail servers) and port 587 is used for MUAs (port 587 is also known as the "submission" port).

      In either case, virtually all modern mail servers today require that the authentication be performed over an encrypted connection using TLS 1.0 or later, some may require TLS 1.2. They would reject attempts to authenticate over a clear (unencrypted) connection, unless they're explicitly configured to permit relaying from the sender's IP address. Which will never be the case for third-party mail servers that are not in your own domain. In other words, code like this might work if you're using it to send mail to a local company mail server on your own network; any code that attempts to use a standard connection to submit messages won't work when trying to send mail through services like Gmail, Outlook, etc.
      Mike Stefanik
      sockettools.com

      Comment


      • #4
        Many years later.....

        Can anyone tell me how to add an attachment to the email using the above code sample?

        Comment


        • #5
          Originally posted by Owen English View Post
          Many years later.....

          Can anyone tell me how to add an attachment to the email using the above code sample?
          That code is just for sending a plain text email.

          If you want to attach something, you need to use MIME and Base64 encoding. IOW, that code will require a complete rewrite.

          A couple of alternatives:
          1. buy SocketTools
          2. Download Blat and use the DLL or Shell to the exe

          Comment


          • #6
            SImple demonstration of using Blat.dll to send an email with an attachment
            (attached zip contains the DLL)

            '
            Code:
            #COMPILE EXE
            DECLARE FUNCTION SendBlat LIB "blat.dll" ALIAS "Send" (BYVAL sCmd AS STRING) AS INTEGER
            
            $Server = "mail.example.net"
            $From = "[email protected]"
            $MyOrg ="My Company"
            
            FUNCTION PBMAIN() AS LONG
                LOCAL iresult AS INTEGER
                iresult = Blat("[email protected]","Blat Test","This is a simple email using Blat.DLL","blat.zip")
                IF iresult = 0 THEN
                    ? "OK"
                ELSE
                    ? "Error! See BlatLog.txt"
                END IF
            END FUNCTION
            
            FUNCTION Blat(strTo AS STRING,strSubject AS STRING,strBody AS STRING,strAttach AS STRING ) AS LONG
                LOCAL iResult AS INTEGER
                LOCAL strBlat AS STRING
                IF ISFILE("blatlog.txt") THEN KILL "Blatlog.txt"
                strBlat = "- -body " & quoted(strBody) & " -to " & strTo & " -SERVER " & $Server & " -f " & $From
                strBlat += " -s " & quoted(strSubject) & " -O " & quoted($MyOrg)
                strBlat += " -ti 60 -log BlatLog.txt -noh2 -attach " & quoted(strAttach)
                ​
                ? strBlat
                FUNCTION = SendBlat(strBlat)
            END FUNCTION
            
            FUNCTION Quoted( s AS STRING) AS STRING
                FUNCTION = CHR$(34,s,34)
            END FUNCTION  ​
            '
            Attached Files

            Comment


            • #7
              I can vouch for how easy SocketTools makes the process.
              Real programmers use a magnetized needle and a steady hand

              Comment


              • #8
                Many thanks Bud & Stuart. Have gone the Blatt route - drastically easier, attachments working fine and above all, the correct date on the received email!
                Basically, instead of ftping error logs to my domain server, I need to attach them to emails so that I see them immediately on my mobile phone and can respond immediately (as todays spoilt brat customers now demand).


                Comment


                • #9
                  OK, a few weeks later.... got to grips with Blat and implemented it on clients desktops using my own mail.server and encrypting attachments (recipients have decrypt function) - all good.

                  However, some clients insist that their outgoing emails use their installed Outlook. A roam around www re 'command line', 'send email', ''outlook' and many other combinations produces nothing much. Does anyone have any experience of calling outlook.exe from a shell (command line) within PBW10 and including the various 'to', 'subject' 'body-text' and 'attachment' in that command line?

                  Comment


                  • #10
                    Owen,

                    See statement in orange box at the top of the page.
                    Dale

                    Comment


                    • #11
                      Originally posted by Owen English View Post
                      OK, a few weeks later.... got to grips with Blat and implemented it on clients desktops using my own mail.server and encrypting attachments (recipients have decrypt function) - all good.

                      However, some clients insist that their outgoing emails use their installed Outlook. A roam around www re 'command line', 'send email', ''outlook' and many other combinations produces nothing much. Does anyone have any experience of calling outlook.exe from a shell (command line) within PBW10 and including the various 'to', 'subject' 'body-text' and 'attachment' in that command line?

                      Hopefully last post in this Source Code forum.

                      Search the forums for MAPI and take a look around in the Programming MS Office sub-forum and start a new thread there:

                      Comment


                      • #12
                        Simple example of attachment send.
                        Mail data is stored in the SMTP type...
                        Functions for mail date and base64 included...

                        Code:
                        '========================================================================================
                        ' Email functions
                        '----------------------------------------------------------------------------------------
                        #COMPILE EXE "testmail.exe"
                        #DIM ALL
                        #INCLUDE "win32api.inc"
                        
                        Type SMTPType
                          Server        As Asciiz * 64          'Name of SMTP mail server
                          From          As Asciiz * 64          'Mail address sender
                          IPAddress     As Asciiz * 64          'IPv4 Address sender
                          DisplayName   As Asciiz * 64          'Name to be displayed at from
                          To            As Asciiz * 64          'Mail address receiver
                          Cc            As Asciiz * 256         'Carbon copy sent
                          Caption       As Asciiz * 64          'Title of mailmessage
                          Bodytext      As Asciiz * 64          'Body of mailmessage
                          Files         As Asciiz * 256         'Attached files if any
                          Username      As Asciiz * 64          'SMTP login username
                          Password      As Asciiz * 64          'SMTP login password
                          Cmd           As Asciiz * 256         'Last sent command (error tracking)
                          Resp          As Asciiz * 256         'Last received reply (error tracking)
                          Date          As Asciiz * 64          'Last send date
                        End Type
                        
                        Global SMTP     As SMTPTYPE
                        
                        '========================================================================================
                        ' Base64Encode(): - String to Base64
                        '========================================================================================
                        FUNCTION Base64Encode(pInStr AS STRING) AS STRING
                          LOCAL lBase64, lOutStr, lPad AS STRING, lBlock, lInBlocks As Dword
                          Local lByte1, lByte2, lByte3 As Byte, InPtr, OutPtr, BasePtr As Byte Ptr
                          '--------------------------------------------------------------------------------------
                          lBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
                          lPad = String$(2- (Len(pInstr) -1) Mod 3, "=")            'Calc paddinglength
                          lInBlocks = (Len(pInStr) +2) \3                           'Blockcount rounded
                          If lInBlocks * 3 > Len(pInStr) Then                       'Ir input too short
                            pInStr = LSet$(pInStr, lInBlocks * 3 Using $Nul)        'add zeroes tp fill
                          End If                                                    '
                          lOutStr = Space$(lInBlocks * 4)                           'Prepare out buffer
                          InPtr   = StrPtr(pInStr)                                  'Setup string ptrs
                          OutPtr  = StrPtr(lOutStr)                                 '
                          BasePtr = StrPtr(lBase64)                                 '
                          For lBlock = 1 To lInBlocks
                            lByte1  = @InPtr : Incr InPtr
                            lByte2  = @InPtr : Incr InPtr
                            lByte3  = @InPtr : Incr InPtr
                            @OutPtr = @BasePtr[lByte1 \ 4] : Incr OutPtr
                            @OutPtr = @BasePtr[(lByte1 And &h03) * 16 + lByte2 \ 16] : Incr OutPtr
                            @OutPtr = @BasePtr[(lByte2 And &h0F) * 4 + lByte3 \ 64] : Incr OutPtr
                            @OutPtr = @BasePtr[lByte3 And &h3F] : Incr OutPtr
                          Next
                          RSet Abs lOutStr = lPad
                          Function = lOutStr
                        END FUNCTION
                        
                        '========================================================================================
                        ' Base64Decode(): - Base64 to string
                        '========================================================================================
                        FUNCTION Base64Decode(pInStr AS STRING) AS STRING
                          LOCAL lBase64, lOutstr AS STRING, lInBlocks, lBlock, lInMod, lCut As Dword
                          Local lByte1, lByte2, lByte3, lByte4 As Byte, InPtr, OutPtr As Byte Ptr
                          '--------------------------------------------------------------------------------------
                          lBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
                          lInMod    = Len(pInstr) Mod 4                             'Broken blocks?
                          If lInMod Then                                            '
                            pInstr = pInstr+String$(4-lInMod,Chr$(&h3D))            'Yes, add padding
                          End If
                          lInBlocks = Len(pInStr) \ 4                               '
                          lCut      = Tally(pInStr, Chr$(&h3D)) '/ 3) * 4           '
                          lOutStr   = Space$(lInBlocks * 3 + lInMod)
                          InPtr     = StrPtr(pInStr)
                          OutPtr    = StrPtr(lOutStr)
                        
                          For lBlock = 1 To lInBlocks
                            lByte1   = InStr(lBase64, Chr$(@inPtr)) -1 : Incr InPtr
                            lByte2   = InStr(lBase64, Chr$(@inPtr)) -1 : Incr InPtr
                            lByte3   = InStr(lBase64, Chr$(@inPtr)) -1 : Incr InPtr
                            lByte4   = InStr(lBase64, Chr$(@inPtr)) -1 : Incr InPtr
                            @OutPtr  =  lByte1 * 4  + lByte2 \ 16 : Incr OutPtr
                            @OutPtr  =  lByte2 * 16 + lByte3 \ 4 : Incr OutPtr
                            @OutPtr  =  lByte3 * 64 + lByte4      :Incr OutPtr
                          Next
                          Function = Left$(lOutStr, lInBlocks * 3 - lCut)
                        END FUNCTION
                        
                        '========================================================================================
                        ' MailDate() - Get date stamp
                        '========================================================================================
                        Function MailDate () As String
                          Local lszFormat As Asciiz * 40, lszStr As Asciiz * 40, lsRet As String
                          Local lST As SYSTEMTIME, lsOffset As String, tzi As TIME_ZONE_INFORMATION
                          '--------------------------------------------------------------------------------------
                          GetLocalTime lST            'Get time and format it to the local settings
                          lszFormat = "ddd',' dd MMM yyyy"
                          GetDateFormat %LOCALE_USER_DEFAULT, 0, lST, lszFormat, lszStr, SizeOf(lszStr)
                          lsRet = lszStr
                          lszFormat = "HH':'mm':'ss"
                          GetTimeFormat %LOCALE_USER_DEFAULT, 0, lST, lszFormat, lszStr, SizeOf(lszStr)
                        
                          Select Case GetTimeZoneInformation(tzi)   'Create string needed in mail header
                          Case %TIME_ZONE_ID_DAYLIGHT
                            lsOffset = IIf$((tzi.bias + tzi.DaylightBias) <= 0, "+", "-") _
                                       + Format$(Abs(tzi.bias + tzi.DaylightBias) \ 60, "00") _
                                       + Format$(Abs(tzi.bias + tzi.DaylightBias) Mod 60, "00")
                          Case %TIME_ZONE_ID_STANDARD
                            lsOffset = IIf$((tzi.bias + tzi.StandardBias) <= 0, "+", "-") _
                                       + Format$(Abs(tzi.bias + tzi.StandardBias) \ 60, "00") _
                                       + Format$(Abs(tzi.bias + tzi.StandardBias) Mod 60, "00")
                          Case Else
                            lsOffset = "-0000"
                          End Select
                          Function = lsRet + " " + lszStr + " " + lsOffset
                        End Function
                        
                        '========================================================================================
                        ' Send_Email() - Send an email through SMTP
                        '========================================================================================
                        Function Send_Email (ByRef SMTP As SMTPTYPE) As Long
                          Local lhTCP, lCnt, lCnt2 As Long, lhFile As Dword
                          Local lsHost, lsBound, lFName, lBuffIn, lBuffOut As String
                          '--------------------------------------------------------------------------------------
                          lsBound = "Boundary." +Remove$(GuidTxt$(Guid$),Any "{-}") 'Unique boundary-
                          Function = 0                                              'marker
                        
                          lhTCP = FreeFile                                          'Open connection to
                          Tcp Open Port 587 At SMTP.Server As lhTCP TimeOut 2000    'the smps server
                          If Err Then Function = ErrClear : Exit Function           'Error opening,exit
                          Tcp Recv lhTcp, SizeOf(SMTP.Resp), SMTP.Resp              'Get result
                          If Instr(SMTP.Resp, "220") = 0 Then Exit Function         'Server not ready
                          '----------------------------------------------------------------------------
                          SMTP.Cmd = "EHLO [" & SMTP.IPAddress & "]"                '
                          Tcp Print lhTcp, SMTP.Cmd                                 '
                          Tcp Recv  lhTcp, SizeOf(SMTP.Resp), SMTP.Resp             '250: OK/capability
                          If Instr(SMTP.Resp, "250") = 0 Then Exit Function         'Exit
                          '----------------------------------------------------------------------------
                          If Instr(Ucase$(SMTP.Resp),"AUTH") And Instr(Ucase$(SMTP.Resp),"LOGIN") Then
                            SMTP.Cmd = "AUTH LOGIN" : Tcp Print lhTcp, SMTP.Cmd     'Login required?
                            Tcp Recv  lhTcp, SizeOf(SMTP.Resp), SMTP.Resp
                            If Instr(SMTP.Resp, "334") Then                         '334: Auth method
                              SMTP.Cmd = Base64encode(ByCopy SMTP.Username)         'accepted. Send
                              TCP Print lhTcp, SMTP.Cmd                             'username (base64)
                              Tcp Recv lhTcp, SizeOf(SMTP.Resp), SMTP.Resp          '
                              If Instr(SMTP.Resp, "334") Then                       '334: Auth method
                                SMTP.Cmd = Base64encode(ByCopy SMTP.Password)       'accepted. Send
                                TCP Print lhTcp, SMTP.Cmd                           'password (base64)
                                Tcp Recv  lhTcp, SizeOf(SMTP.Resp), SMTP.Resp       '
                              End If                                                '
                            End If                                                  '
                          End If                                                    '
                          '----------------------------------------------------------------------------
                          SMTP.Cmd = "MAIL FROM:<" & SMTP.From & ">"                'Mail from:
                          Tcp Print lhTCP, SMTP.Cmd                                 '
                          Tcp Recv lhTCP, SizeOf(SMTP.Resp), SMTP.Resp              '
                          If Instr(SMTP.Resp, "250") = 0 Then Exit Function         '
                          '----------------------------------------------------------------------------
                          SMTP.Cmd =  "RCPT TO:<" & SMTP.To & ">"                   'Send mail to
                          Tcp Print lhTCP, SMTP.Cmd                                 '
                          Tcp Recv lhTCP, SizeOf(SMTP.Resp), SMTP.Resp              '
                          If Instr(SMTP.Resp, "250") = 0 Then Exit Function         'Exit
                          '----------------------------------------------------------------------------
                          If SMTP.Cc <> "" Then                                     'Send mail to cc:
                            For lCnt = 1 To ParseCount (SMTP.Cc)                    '(can be multiple
                              SMTP.Cmd = "RCPT TO:<" & Trim$(Parse$(SMTP.Cc, lCnt)) & ">"
                              Tcp Print lhTCP, SMTP.Cmd
                              Tcp Recv lhTCP, SizeOf(SMTP.Resp), SMTP.Resp
                              If Instr(SMTP.Resp, "250") = 0 Then Exit Function     'Exit
                            Next
                          End If
                          '----------------------------------------------------------------------------
                          SMTP.Cmd = "DATA"                                         'Start datatransfer
                          Tcp Print lhTCP, SMTP.Cmd
                          Tcp Recv lhTCP, SizeOf(SMTP.Resp), SMTP.Resp              '354: response
                          If Instr(SMTP.Resp, "354") = 0 Then Exit Function
                          '----------------------------------------------------------------------------
                          SMTP.Date  = MailDate()                                   'Send date info
                          SMTP.Cmd = "Date: " & SMTP.Date
                          Tcp Print lhTCP, SMTP.Cmd
                          If SMTP.Displayname = "" Then
                            SMTP.Cmd = "From: " & SMTP.From
                            Tcp Print lhTCP, SMTP.Cmd
                          Else
                            If SMTP.From <> "" Then
                              SMTP.Cmd = "From: " & SMTP.Displayname & "<" & SMTP.From & ">"
                              Tcp Print lhTCP, SMTP.Cmd
                            Else
                              SMTP.Cmd = "From: " & SMTP.Displayname
                              Tcp Print lhTCP, SMTP.Cmd
                            End If
                          End If
                          '----------------------------------------------------------------------------
                          SMTP.Cmd = "To: " & SMTP.To : Tcp Print lhTCP, SMTP.Cmd
                          If SMTP.Cc <> "" Then
                            SMTP.Cmd = "Cc: " & SMTP.Cc : Tcp Print lhTCP, SMTP.Cmd
                          End If
                          '----------------------------------------------------------------------------
                          Tcp Print lhTCP, "Subject: " + SMTP.Caption
                          Tcp Print lhTCP, "X-Mailer: Arcovox MIME/Base64 E-mailer 1.0"
                          Tcp Print lhTCP, "MIME-Version: 1.0"
                          SMTP.Cmd =  "Content-Type: multipart/mixed; boundary=" + $Dq + lsBound + $Dq
                          Tcp Print lhTCP,  SMTP.Cmd
                          Tcp Print lhTCP, ""
                          Tcp Print lhTCP, "--" & lsBound
                          SMTP.Cmd = "Content-Type: text/plain; charset=" + $Dq + "us-ascii" + $Dq
                          Tcp Print lhTCP,  SMTP.Cmd
                          Tcp Print lhTCP, "Content-Transfer-Encoding: 7bit"
                          Tcp Print lhTCP, ""
                          '----------------------------------------------------------------------------
                          For lCnt = 1 To ParseCount(SMTP.BodyText, $Cr)            'Write message
                            Tcp Print lhTcp, Parse$(SMTP.BodyText, lCnt)
                          Next
                          '----------------------------------------------------------------------------
                          If (SMTP.Files <> "") Then                                'Are there files?
                            For lCnt = 1 To ParseCount(SMTP.Files)                  'Yes, get 1st name
                              lFName = PathName$(NAMEX, Parse$(SMTP.Files,lCnt))    'and strip it
                              If IsFile (lFName) Then                               'Does file exist?
                                lhFile = FreeFile
                                Open lFName For Binary Access Read Lock Shared As #lhFile
                                Get$ #lhFile, Lof(lhFile), lBuffIn
                                Close #lhFile
                                If Len(lBuffIn) Then
                                  lBuffOut = Base64Encode(lBuffIn)
                                  Tcp Print lhTCP, "--" & lsBound                   'Boundary separator
                                  Tcp Print lhTCP, "Content-Type: application/octet-stream; name=" & _
                                                                             $Dq & lFName & $Dq
                                  Tcp Print lhTCP, "Content-Transfer-Encoding: base64"
                                  Tcp Print lhTCP, ""
                                  For lCnt2 = 1 To Len(lBuffOut) Step 76            'Write date in 76
                                    If Len(lBuffOut) - lCnt2 >= 76 Then             'char lines.If less
                                      Tcp Print lhTCP, Mid$(lBuffOut, lCnt2, 76)    'then add a "="
                                    Else
                                      Tcp Print lhTCP, Mid$(lBuffOut, lCnt2) & "="
                                    End If
                                  Next
                                End If
                              End If
                            Next
                          End If
                          '----------------------------------------------------------------------------
                          Tcp Print lhTCP, "--" & lsBound & "--"                    'Close mail
                          Tcp Print lhTCP, "."                                      'Line with only "."
                          Tcp Recv lhTCP, SizeOf(SMTP.Resp), SMTP.Resp
                          Tcp Print lhTCP, "QUIT"
                          Tcp Recv lhTCP, SizeOf(SMTP.Resp), SMTP.Resp
                          Tcp Close lhTCP                                           'Close socket
                          Function = 1
                        End Function
                        
                        '========================================================================================
                        ' Main
                        '========================================================================================
                        FUNCTION PBMAIN () AS LONG
                          SMTP.Server       = "smtp.provider.com"    'Name of SMTP mail server
                          SMTP.From         = "[email protected]"   'Mail address sender
                          SMTP.IPAddress    = "192.168.2.2"          'IPv4 Address sender
                          SMTP.DisplayName  = "My test email"        'Name to be displayed at from
                          SMTP.To           = "[email protected]" 'Mail address receiver
                          SMTP.Caption      = "Test with attachment" 'Title of mailmessage
                          SMTP.Bodytext     = "An attachment test..."'Body of mailmessage
                          SMTP.Files        = "testmail.bas"         'Attached files if any
                        
                          Send_Email(SMTP)
                         
                        END FUNCTION
                        
                        '========================================================================================

                        Regards,
                        Peter

                        "Simplicity is a prerequisite for reliability"

                        Comment

                        Working...
                        X