'===========================================================================
' Subject: RAPID-Q E-MAIL FUNCTIONS           Date: 10-18-00 (21:05)       
'  Author: Wolfgang Kempin                    Code: RAPIDQ                 
'  Origin: wolfgang.kempin@epost.de         Packet: RAPIDQ.ABC
'===========================================================================
' **************************************
' * RQ/mail - Rapid-Q e-mail functions * Version 1.99d [BETA]
' **************************************
' coded by Wolfgang 'DarkWulf' Kempin <wolfgang.kempin@gmx.de>
'
' <<< Feel free to use this code (or parts of it) in your programs :) >>>
'
' - RQ/mail was formerly known as 'Express Mailer'
' - There is almost no POP3 support at the moment :(
' - See demo code at the end of the program
'
' =============================================================================
'
' - WARNING: Don't try to send e-mails to multiple recipients (multiple TOs/CCs/
'    ! ! !   BCCs) -- I have to rewrite that part first; it's too buggy ;(
'            (some mails will be sent and some not)
'
' <<< BETA VERSION - still a lot of bugs in it >>>
' <<< I'm not responsible for what you do with >>>
' <<< this code. This project is in a very     >>>
' <<< early stage; you have been warned ;-)    >>>
'
' =============================================================================
'
' Versions
' --------
'
' Date*    Version Change Description              [* = date format DD/MM/YY]
' ??/??/99   1.00     +   First complete and working version
' ??/??/99   1.01     +   Fixed '555 Syntax error' when sending mails
' 03/10/00   1.05     +   Fix: Mails were sent with empty body
'                         (only the subject was there)
' 04/10/00   1.99     +   Decided to rework on the project upon public demand ;)
'                     +   Complete rewrite of the program
'                    <i>  RENAMED to RQ/mail
'                     +   Splitted the project up into the RQ/mail functions
'                         and a sample mailer program (not yet done)
'                     +   All further versions will be tested on Linux, too :)
' 10/10/00   1.99b    +   Added a simple POP-before-SMTP function
'                     +   Corrected multi-line SMTP reply bug
'                         (not the POP multi-line replys... but the only
'                         POP3 function yet is the POP3beforeSMTP, and there
'                         will hardly be multi-line replys when just logging in)
' 11/10/00   1.99c    +   Reduced code size a bit
' 21/10/00   1.99d    +   Fixed: tried to send e-mails with emtpy strings as
'                         destination
'                     +   First working Linux version
'                    <i>  First public release after a _very_ long time
'
' To do/plans for this project:
' -----------------------------
'
' Priority Description
'    1     create sample mailer
'    2     add basic POP3 support to get complete RQ/mail library
'    3     add support to exclude unused functions
'    4     change RQmail_SendMail function to just send the e-mails to all
'          addresses at once (and not one e-mail to each address)
'    5     documentation
'    9     MIME support?
'    ?     a better interface
'    ?     write a complete mail program (sth. like OE, but much better ;-)
'
' =============================================================================
' This library is far from being complete but I think you can already use it
' for some simple tasks. If you've got any questions, want to report bugs or
' have an idea how this library could be improved feel free to mail me at
' <wolfgang.kempin@gmx.de>.
' =============================================================================
' Known bugs: (in brackets: state of the function)
'
' RQmail_SendRaw:           * none at the moment, seems to be OK
' [WORKING]
'
' RQmail_SendMail:          * no format checking is done with the TO$/CC$/BCC$
' [BUGGY, but working]        variables yet
'                           * multiple recipients don't really work yet
'
' POP3beforeSMTP:           * no multi-line replys supported yet (but there
' [UNTESTED]                  will hardly be such replies when you are
'                             just logging in [IMO])
'                           * has not been tested very much
'
' =============================================================================

DIM RQmail_Error AS STRING                       ' Global error variable

' POP3
DECLARE FUNCTION POP3beforeSMTP (server$, username$, passwd$) AS INTEGER

' SMTP
DECLARE FUNCTION RQmail_SendMail (from$, to$, cc$, bcc$, priority AS INTEGER, subject$, text$, server$) AS STRING
DECLARE FUNCTION RQmail_SendRaw (smtp_server$, email_from$, email_to$, content$) AS INTEGER

' =============================================================================
' === SMTP support - Send e-mails                                           ===
' =============================================================================

' -----------------------------------------------------------------------------
' | Function RQmail_SendMail(from$, to$, cc$, bcc$, prior, subject$, text$)   |
' -----------------------------------------------------------------------------
' | Send an e-mail to the specified addresses (including cc's and bcc's! :)   |
' -----------------------------------------------------------------------------
' | from$ :=       full name and e-mail address of the person sending the     |
' |                e-mail (format: see below)                                 |
' | to$ :=         dito for the recipients, but you can add more than one here|
' | cc$ :=         dito for the 'carbon' copies                               |
' | bcc$ :=        dito...                                                    |
' | prior :=       priority { 0 = low; 1 = normal; 2 = high; }                |
' | subject$ :=    subject of the e-mail                                      |
' | text$ :=       the content of the e-mail                                  |
' -----------------------------------------------------------------------------
' | from$, to$ and cc$ have to be in the following format:                    |
' | "Mr. Smith <mr.smith@somewhere.com>"                                      |
' | for multiple reciepients you can add several addresses separated by       |
' | semicolons (';'):                                                         |
' | "Mark <see@above.com>;John <j@ohn.net>;bob@cheap.mail.org; . . ."         |
' -----------------------------------------------------------------------------
' | Returns 0 if there were no errors, 1 if some e-mails could not be sent and|
' | 2 if NO e-mail could be sent.                                             |
' =============================================================================

FUNCTION RQmail_SendMail (from$, to$, cc$, bcc$, priority AS INTEGER, subject$, text$, server$) AS INTEGER
   DIM eml AS STRING 'contains the e-mail
   DIM cl AS STRING 'cl will be set to <CR>+<LF>

   DIM a AS INTEGER 'counter
   DIM em AS STRING 'one extracted e-mail address
   DIM ret AS INTEGER 'return code
   DIM errtmp AS STRING 'temporary error stack

   DIM m_all AS INTEGER ' count of all mails
   DIM m_err AS INTEGER ' number of mails which could not be sent

   ' ---=== FIRST STEP: Create a valid e-mail with a correct header ===---
   
   cl = CHR$(13) + CHR$(10) '= <CR>+<LF>

   eml = "From: " + from$ +cl '###!!!### TO DO: add format checking here
   eml = eml + "To: " + to$ +cl
   eml = eml + "Cc: " + cc$ +cl
                              '###!!!### TO DO: add date info here
   eml = eml + "Subject: " + subject$ +cl
   eml = eml + "X-Mailer: RQ/mail version 2.0" +cl
   IF priority = 0 THEN
      eml = eml + "X-Priority: 5" +cl
      eml = eml + "X-MSMail-Priority: Low" +cl
   ELSEIF priority = 1 THEN
      eml = eml + "X-Priority: 3" +cl
      eml = eml + "X-MSMail-Priority: Normal" +cl
   ELSEIF priority = 2 THEN
      eml = eml + "X-Priority: 1" +cl
      eml = eml + "X-MSMail-Priority: High" +cl
   ELSE
      eml = eml + "X-Priority: 3" +cl
      eml = eml + "X-MSMail-Priority: Normal" +cl
   END IF
   
   eml = eml +cl
   eml = eml + text$
   ' ---=== SECOND STEP: Send the e-mail ===---

   IF INSTR(to$, ";") = 0 THEN to$ = to$ + ";"
   IF INSTR(cc$, ";") = 0 THEN cc$ = cc$ + ";"
   IF INSTR(bcc$, ";") = 0 THEN bcc$ = bcc$ + ";"

   'Now extract all e-mail addresses from to$, cc$ and bcc$ and send
   'a copy to each one. If an error is encountered, the process will
   'continue; all errors will be logged to RQmail_Error.

   '###!!!### change this soon -- this takes much too long, why not use
   '          multiple "RCPT TO:<>" 's in one session?

   errtmp = ""
   m_all = 0
   m_err = 0

   '>> TO$
   FOR A = 1 TO TALLY(to$, ";")+1
      em = FIELD$(FIELD$(to$, ";", A), "<", 2) 'automatically strips of '<'
      em = MID$(em, 1, LEN(em) - 1)            'now get rid of the '>'

      IF em = "" THEN em = FIELD$(to$, ";", A)  'no name given, just a plain e-mail address

      IF em <> "" THEN ret = RQmail_SendRaw(server$, MID$(FIELD$(from$, "<", 2), 1, LEN(FIELD$(from$, "<", 2)) - 1), em, eml) ELSE ret = 0
      IF ret <> 0 THEN
         errtmp = "<" + em + ">: '" + RQmail_Error + "'"
         m_err = m_err + 1
      ELSE
         m_all = m_all + 1
      END IF
   NEXT A

   '>> CC$
   IF CC$ <> ";" THEN
      FOR A = 1 TO TALLY(cc$, ";")+1
         em = FIELD$(FIELD$(cc$, ";", A), "<", 2) 'automatically strips of '<'
         em = MID$(em, 1, LEN(em) - 1)            'now get rid of the '>'

         IF em = "" THEN em = FIELD$(cc$, ";", A)  'no name given, just a plain e-mail address
   
         IF em <> "" THEN ret = RQmail_SendRaw(server$, MID$(FIELD$(from$, "<", 2), 1, LEN(FIELD$(from$, "<", 2)) - 1), em, eml) ELSE ret = 0
         IF ret <> 0 THEN
            errtmp = "<" + em + ">: '" + RQmail_Error + "'"
            m_err = m_err + 1
         ELSE
            m_all = m_all + 1
         END IF
      NEXT A
   END IF

   '>> BCC$
   IF bcc$ <> ";" THEN
      FOR A = 1 TO TALLY(bcc$, ";")+1
         em = FIELD$(FIELD$(bcc$, ";", A), "<", 2) 'automatically strips of '<'
         em = MID$(em, 1, LEN(em) - 1)             'now get rid of the '>'

         IF em = "" THEN em = FIELD$(bcc$, ";", A)  'no name given, just a plain e-mail address
   
         IF em <> "" THEN ret = RQmail_SendRaw(server$, MID$(FIELD$(from$, "<", 2), 1, LEN(FIELD$(from$, "<", 2)) - 1), em, eml) ELSE ret = 0
         IF ret <> 0 THEN
            errtmp = "<" + em + ">: '" + RQmail_Error + "'"
            m_err = m_err + 1
         ELSE
            m_all = m_all + 1
         END IF
      NEXT A
   END IF

   RQmail_Error = errtmp

   IF m_err = m_all THEN                         'no mail could be sent
      RQmail_SendMail = 2
   ELSEIF (m_all > m_err) AND (m_err > 0)THEN    'some could be sent
      RQmail_SendMail = 1
   ELSEIF m_err = 0 THEN                         'all could be sent
      RQmail_SendMail = 0
   END IF
END FUNCTION

' =============================================================================

' -----------------------------------------------------------------------------
' | Function RQmail_Internal_SMTPreply (Socket AS QSocket, Handle AS INTEGER) |
' | AS STRING                                                                 |
' -----------------------------------------------------------------------------
' | Returns a SMTP reply (supports multi-line replies)                        |
' -----------------------------------------------------------------------------

FUNCTION RQmail_Internal_SMTPreply (Socket AS QSocket, Handle AS INTEGER) AS STRING
   DIM ErrLine AS STRING                         ' Last SMTP server message
   DIM ErrLinePart AS STRING                     ' Last SMTP server message
                                                 ' (current line of a multi-
                                                 ' line reply)

   ErrLine = ""
   DO
      ErrLinePart = Socket.ReadLine(Handle) 'Get the last server message
      ErrLine = ErrLine + ErrLinePart + CHR$(13) + CHR$(10)
   LOOP UNTIL MID$(ErrLinePart, 4, 1) <> "-"
   ErrCode = VAL(MID$(ErrLine, 1, 3))                'Extract the 3 digit error code (will stay the same in multi-line replys)

   IF (Socket.Transferred < 0) AND (ErrLine = "") THEN
      ErrLine = "5XX Connection was closed unexpectedly."
      Socket.Close(Handle)
   END IF

   RQmail_Internal_SMTPreply = ErrLine
END FUNCTION

' =============================================================================

' -----------------------------------------------------------------------------
' | Function RQmail_SendRaw(smtp_server$, email_from$, email_to$, content$)   |
' -----------------------------------------------------------------------------
' | smtp_server$ := Host name of the mail server you want to send the e-mail  |
' |                 to.                                                       |
' |                 i.e.: mail.myserver.com                                   |
' | email_from$ :=  The e-mail address of the account sending the e-mail.     |
' |                 i.e.: hello@world.net                                     |
' | email_to$ :=    The e-mail address of the person you want to write to.    |
' |                 i.e.: wow@this.is.a.very.long.hostname.is.it.cx           |
' | content$ :=     The e-mail content (including header)                     |
' -----------------------------------------------------------------------------
' | This function looks very complicated... but it isn't at all ;)            |
' | If you take a closer look, you will see that it is just almost the same   |
' | commands repeated several times; except the parser part of the function.  |
' | When sending an e-mail you need to verify that your e-mail doesn't contain|
' | a single line with just a dot ('.') in it -- this is already used to mark |
' | the end of a mail. So we've got to check that. The parser should work on  |
' | Windows and on Linux, too.                                                |
' |                                                                           |
' | 11/11/00: put most of the SMTP reply check code into a separate function. |
' |           (-> program size reduced)                                       |
' -----------------------------------------------------------------------------
' | Returns 0 if everything went alright and 1 if there was an error.         |
' -----------------------------------------------------------------------------

FUNCTION RQmail_SendRaw (smtp_server$, email_from$, email_to$, content$) AS INTEGER
   DIM SMTP_Socket AS QSocket                    ' Define QSocket
   DIM SMTP_SocketHandle AS INTEGER

   DIM ErrCode AS INTEGER                        ' Last SMTP error code
   DIM ErrLine AS STRING                         ' Last SMTP server message

   DIM ParsedLine AS STRING                      ' used by the e-mail parser
   DIM a AS INTEGER
   DIM eol AS INTEGER                            ' end of line?

   ' Connect to server
   SMTP_SocketHandle = SMTP_Socket.Connect(smtp_server$, 25)

   IF SMTP_SocketHandle < 0 THEN                          ' Connect error?
      RQmail_Error = "5XX Could not connect to server"
      RQmail_SendRaw = 1 'abort
      EXIT FUNCTION
   END IF
   
   ' ---=== Check for errors or broken connection ===---
   ErrLine = RQmail_Internal_SMTPreply(SMTP_Socket, SMTP_SocketHandle)
   ErrCode = VAL(MID$(ErrLine, 1, 3))
   IF (ErrCode >= 400) THEN 'Error?
      RQmail_Error = ErrLine
      RQmail_SendRaw = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Say hello ===---
   SMTP_Socket.WriteLine(SMTP_SocketHandle, "HELO localhost")

   ' ---=== Check for errors or broken connection ===---
   ErrLine = RQmail_Internal_SMTPreply(SMTP_Socket, SMTP_SocketHandle)
   ErrCode = VAL(MID$(ErrLine, 1, 3))
   IF (ErrCode >= 400) THEN 'Error?
      RQmail_Error = ErrLine
      RQmail_SendRaw = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Mail from ===---
   SMTP_Socket.WriteLine(SMTP_SocketHandle, "MAIL FROM:<" + email_from$ + ">")

   ' ---=== Check for errors or broken connection ===---
   ErrLine = RQmail_Internal_SMTPreply(SMTP_Socket, SMTP_SocketHandle)
   ErrCode = VAL(MID$(ErrLine, 1, 3))
   IF (ErrCode >= 400) THEN 'Error?
      RQmail_Error = ErrLine
      RQmail_SendRaw = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Mail to ===---
   SMTP_Socket.WriteLine(SMTP_SocketHandle, "RCPT TO:<" + email_to$ + ">")

   ' ---=== Check for errors or broken connection ===---
   ErrLine = RQmail_Internal_SMTPreply(SMTP_Socket, SMTP_SocketHandle)
   ErrCode = VAL(MID$(ErrLine, 1, 3))
   IF (ErrCode >= 400) THEN 'Error?
      RQmail_Error = ErrLine
      RQmail_SendRaw = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Now send the mail ===---
   SMTP_Socket.WriteLine(SMTP_SocketHandle, "DATA")

   ' ---=== Check for errors or broken connection ===---
   ErrLine = RQmail_Internal_SMTPreply(SMTP_Socket, SMTP_SocketHandle)
   ErrCode = VAL(MID$(ErrLine, 1, 3))
   IF (ErrCode >= 400) THEN 'Error?
      RQmail_Error = ErrLine
      RQmail_SendRaw = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Parse mail ===---
   '[lines with a single dot ('.') will be changed to ('..') because a single
   'dot marks the end of the e-mail]

   'CHR$(13) = <CR>, CHR$(10) = <LF>
   
   ParsedLine = ""
   FOR A = 1 TO LEN(content$)
      IF (MID$(content$, A, 1) = CHR$(13)) OR _
         (MID$(content$, A, 1) = CHR$(10)) THEN
         'line ends, check whether content$ uses
         '<CR>, <LF>, <CR>+<LF> or <LF>+<CR> to mark the end of a line

         eol = ASC(MID$(content$, A, 1))
         A = A + 1
         IF ASC(MID$(content$, A, 1)) = eol THEN
            'one line of text plus one empty line ending with 2 <CR>s or <LF>s
   
            IF ParsedLine = "." THEN
               SMTP_Socket.WriteLine(SMTP_SocketHandle, "..")
            ELSE
               SMTP_Socket.WriteLine(SMTP_SocketHandle, ParsedLine)
            END IF
            SMTP_Socket.WriteLine(SMTP_SocketHandle, "")
            ParsedLine = ""
         ELSE
            IF (MID$(content$, A, 1) = CHR$(13)) OR _
               (MID$(content$, A, 1) = CHR$(10)) THEN
               'one line ending with <CR>+<LF> or <LF>+<CR>

               IF ParsedLine = "." THEN
                  SMTP_Socket.WriteLine(SMTP_SocketHandle, "..")
               ELSE
                  SMTP_Socket.WriteLine(SMTP_SocketHandle, ParsedLine)
               END IF
               ParsedLine = ""
            ELSE
               'one line ending with <CR> or <LF>

               IF ParsedLine = "." THEN
                  SMTP_Socket.WriteLine(SMTP_SocketHandle, "..")
               ELSE
                  SMTP_Socket.WriteLine(SMTP_SocketHandle, ParsedLine)
               END IF
               ParsedLine = ""
            END IF
         END IF
      ELSE
         ParsedLine = ParsedLine + MID$(content$, A, 1)
      END IF
   NEXT A

   'write the rest
   IF ParsedLine <> "" THEN
      IF ParsedLine = "." THEN 
         SMTP_Socket.WriteLine(SMTP_SocketHandle, "..")
      ELSE
         SMTP_Socket.WriteLine(SMTP_SocketHandle, ParsedLine)
      END IF
   END IF

   'End of mail ===---
   SMTP_Socket.WriteLine(SMTP_SocketHandle, ".")

   ' ---=== Check for errors or broken connection ===---
   ErrLine = RQmail_Internal_SMTPreply(SMTP_Socket, SMTP_SocketHandle)
   ErrCode = VAL(MID$(ErrLine, 1, 3))
   IF (ErrCode >= 400) THEN 'Error?
      RQmail_Error = ErrLine
      RQmail_SendRaw = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Bye bye ===---
   SMTP_Socket.WriteLine(SMTP_SocketHandle, "QUIT")

   ' ---=== Check for errors or broken connection ===---
   ErrLine = RQmail_Internal_SMTPreply(SMTP_Socket, SMTP_SocketHandle)
   ErrCode = VAL(MID$(ErrLine, 1, 3))
   IF (ErrCode >= 400) THEN 'Error?
      RQmail_Error = ErrLine
      RQmail_SendRaw = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   SMTP_Socket.Close(SMTP_SocketHandle)
   RQmail_SendRaw = 0 ' ---=== mail sent successfully ===---
END FUNCTION

' =============================================================================
' === POP3 support - Recieve e-mails                                        ===
' =============================================================================

' -----------------------------------------------------------------------------
' | Function RQmail_POP3beforeSMTP(server$, username$, passwd$) AS INTEGER    |
' -----------------------------------------------------------------------------
' | Logs in on the specified POP3 server and quits the connection afterwards. |
' | This function is only of use to someone who's e-mail server requires      |
' | POP-before-SMTP.                                                          |
' -----------------------------------------------------------------------------
' | server$ :=   host name of the server (i.e. pop3.myserver.com)             |
' | username$ := user name                                                    |
' | passwd$ :=   password                                                     |
' -----------------------------------------------------------------------------
' | The function returns 0 if there were no errors and 1 if the operation     |
' | could not be completed successfully (see also RQmail_Error$)              |
' =============================================================================

FUNCTION RQmail_POP3beforeSMTP (server$, username$, passwd$) AS INTEGER
   DIM POP3_Socket AS QSocket                    ' Define QSocket
   DIM POP3_SocketHandle AS INTEGER

   DIM ErrCode AS STRING                         ' Last POP3 error code
   DIM ErrLine AS STRING                         ' Last POP3 server message

   ' Connect to server
   POP3_SocketHandle = POP3_Socket.Connect(server$, 110)

   IF POP3_SocketHandle < 0 THEN                          ' Connect error?
      RQmail_Error = "-ERR Could not connect to server"
      POP3beforeSMTP = 1 'abort
      EXIT FUNCTION
   END IF

   ' ---=== Check for errors or broken connection ===---
   ErrLine = POP3_Socket.ReadLine(POP3_SocketHandle) 'Get the last server message
   ErrCode = LEFT$(ErrLine, 1)                       'Extract the first letter (should be either '+' or '-')
   IF (ErrCode = "-") OR (POP3_Socket.Transferred < 0) THEN 'Error?
      IF (POP3_Socket.Transferred < 0) AND (ErrLine = "") THEN ErrLine = "-ERR Connection was closed unexpectedly."
      POP3_Socket.Close(POP3_SocketHandle)
      RQmail_Error = ErrLine
      POP3beforeSMTP = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Send username ===---
   POP3_Socket.WriteLine(POP3_SocketHandle, "USER " + username$)

   ' ---=== Check for errors or broken connection ===---
   ErrLine = POP3_Socket.ReadLine(POP3_SocketHandle) 'Get the last server message
   ErrCode = LEFT$(ErrLine, 1)                       'Extract the first letter (should be either '+' or '-')
   IF (ErrCode = "-") OR (POP3_Socket.Transferred < 0) THEN 'Error?
      IF (POP3_Socket.Transferred < 0) AND (ErrLine = "") THEN ErrLine = "-ERR Connection was closed unexpectedly."
      POP3_Socket.Close(POP3_SocketHandle)
      RQmail_Error = ErrLine
      POP3beforeSMTP = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Send password ===---
   POP3_Socket.WriteLine(POP3_SocketHandle, "PASS " + passwd$)

   ' ---=== Check for errors or broken connection ===---
   ErrLine = POP3_Socket.ReadLine(POP3_SocketHandle) 'Get the last server message
   ErrCode = LEFT$(ErrLine, 1)                       'Extract the first letter (should be either '+' or '-')
   IF (ErrCode = "-") OR (POP3_Socket.Transferred < 0) THEN 'Error?
      IF (POP3_Socket.Transferred < 0) AND (ErrLine = "") THEN ErrLine = "-ERR Connection was closed unexpectedly."
      POP3_Socket.Close(POP3_SocketHandle)
      RQmail_Error = ErrLine
      POP3beforeSMTP = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'Quit ===---
   POP3_Socket.WriteLine(POP3_SocketHandle, "QUIT")

   ' ---=== Check for errors or broken connection ===---
   ErrLine = POP3_Socket.ReadLine(POP3_SocketHandle) 'Get the last server message
   ErrCode = LEFT$(ErrLine, 1)                       'Extract the first letter (should be either '+' or '-')
   IF (ErrCode = "-") OR (POP3_Socket.Transferred < 0) THEN 'Error?
      IF (POP3_Socket.Transferred < 0) AND (ErrLine = "") THEN ErrLine = "-ERR Connection was closed unexpectedly."
      POP3_Socket.Close(POP3_SocketHandle)
      RQmail_Error = ErrLine
      POP3beforeSMTP = 1 ' ---=== abort ===---
      EXIT FUNCTION
   END IF

   'everything was OK
   POP3_Socket.Close(POP3_SocketHandle)
   RQmail_Error = ""
   POP3beforeSMTP = 0
END FUNCTION

' =============================================================================

'Demo code
DIM ret AS INTEGER

ret = RQmail_POP3beforeSMTP("pop.mail.com", "test@rqmail", "nopwd")
ShowMessage "Return code of POP3-before-SMTP: " + STR$(ret) + " -- Error: '" + RQmail_Error + "'"

ret = RQmail_SendMail("someone <darkwulf>", "you <user>", "", "", 2, "New version!", "<<<contents>>>", "smtp.mail.com")
ShowMessage "Return code of SendMail: " + STR$(ret) + " --- Error information: '" + RQmail_Error + "' ['' means: no error]"
