Seite 1 von 1

Lokaler SMTP Server - Thread Unterstützung

Verfasst: 20.01.2009 17:28
von funk.munich
Hallo zusammen,

ich habe mir einen kleinen dummy smtp server geschrieben.
Dieser empfängt nur die Emails welche von jeglichen mail clients
zum dummy server gesendet wird und speichert diese lokal ab.

Offene Fragen:

- Thread Unterstützung
Zur Zeit wird jedes Email nacheinander abgearbeitet. Ich würde
jedoch fast gleichzeitig unmengen an emails empfangen.

Hier weiß ich jedoch nicht wie ich die Thread Unterstützung mit einbinden
kann/soll.

- Manueller Server Zugriff über "telnet"

Wenn ich den dummy server über "telnet localhost <port>"
aufrufe und danach manuell Kommandos eingeben möchte
wie z.B.

Mail From: ....

Nimmt der dummy server sich jeden Zeichen einzelnd vor.
Somit kann ich über die DOS Zeile den server zur Zeit nicht nutzen.

Hätte jemand einen Vorschlag, wie ich das im PB code lösen
könnte?

Anbei auch der Code:

Code: Alles auswählen

;
;
;
;--- Console Mode
OpenConsole()

;--- Constants
#TITLE = "SMTP Dummy Server, v0.1"

;--- Global Parameters
Global Dim Cli.s(2)
Global Quit.l = 0, flag.l = 0
Global ServerEvent.l, clientID.l
Global result.s = "", fileName.s = ""

;--- Procedures
Procedure SetCli()
  
  ; SMTP Port
  Cli(0) = "25"
  
  ; Save Incoming Mails
  Cli(1) = "spool"
  
  ; Reserve Address Area
  Cli(2) = "512"

EndProcedure

Procedure GetHelp()

  PrintN("SMTP Dummy Server - 0.1 - Command Line Interface")
  PrintN("")
  PrintN("Usage:  smtpds.exe OPTIONS")
  PrintN("")
  PrintN("Options:  ")
  PrintN(LSet(" ", 10) + "-h        Prints this help message.")
  PrintN(LSet(" ", 10) + "-p port   Port number for connection.")
  PrintN(LSet(" ", 20) + "(default: 25)")
  PrintN(LSet(" ", 10) + "-s spool  directory where incoming mails are saved.")
  PrintN(LSet(" ", 20) + "(default: .\spool)")
  PrintN(LSet(" ", 10) + "-m kb     Avalaible memory in KB for the cache.")
  PrintN(LSet(" ", 20) + "(default: 512)")
  PrintN("")

  End
  
EndProcedure

Procedure GetCli()

  Protected count.l, i.l, cli.s

  count = CountProgramParameters()
  
  For i = 0 To count - 1
  
    cli = ProgramParameter(i)
    
    Select LCase(cli)
      Case "-h"
        GetHelp()
      Case "-p"
        Cli(0) = ProgramParameter(i+1)  
      Case "-s"
        Cli(1) = ProgramParameter(i+1)  
      Case "-m"
        Cli(2) = ProgramParameter(i+1)  
    EndSelect
    
  Next

EndProcedure

Procedure ValidateSpoolDirectory()

  Protected newPath.s = "", count.l
  
  If Right(Left(Cli(1), 3), 2) <> ":\"
    Cli(1) = GetCurrentDirectory() + Cli(1)
  EndIf

  If FileSize(Cli(1)) = -1
    count.l = CountString(Cli(1), "\")
    For i = 1 To count + 1
      newPath = newPath + StringField(Cli(1), i, "\") + "\"
      If FileSize(newPath) = -1
        CreateDirectory(newPath)
      EndIf
    Next
  EndIf
  
  If Right(Cli(1), 1) <> "\"
    Cli(1) = Cli(1) + "\"
  EndIf

EndProcedure

Procedure DisplayCli()

  PrintN(LSet("-", 40, "-"))
  PrintN("   Spool Directory:  " + Cli(1))
  PrintN("   Reserved Memory:  " + Cli(2) + "Kb")
  PrintN("   Server Address:   <localhost> : " + Cli(0))
  PrintN("")
  PrintN("   Note: Press keyboard key " + Chr(39) + "q" + Chr(39))
  PrintN("         to shutdown the server.")
  PrintN(LSet("-", 40, "-"))

EndProcedure

Procedure.s GetRandomNumber()

  Protected number.s, tmpChar.s, result.s
  
  number.s = "0000" + Str(Random(1000))
  tmpChar.s = Chr(65 + Random(25)) + Chr(97 + Random(25)) + Chr(65 + Random(25)) + Chr(97 + Random(25))
  result.s = FormatDate("%yyyy%mm%dd%hh%ii%ss", Date()) + "-" + Right(result, 4) + tmpChar
  
  ProcedureReturn result 
  
EndProcedure

Procedure.l InitNet()

  Protected result.l
  
  If InitNetwork() = 0
    result = #False
  Else
    result = #True
  EndIf
  
  ProcedureReturn result

EndProcedure

Procedure.l CloseNet()

  CloseNetworkConnection(clientID)

EndProcedure

Procedure ShutdownSmtpServer()

  Protected key.s
  
  key = Inkey()
  
  If key = "q"
    Quit = 1
    PrintN("SMTP Dummy Server is stopped ...")
    Delay(500)
  EndIf

EndProcedure

Procedure SendNetData(Cmd.s)

  SendNetworkString(clientID, Cmd + Chr(13) + Chr(10))

EndProcedure

Procedure.s ReceiveNetData()

  Protected *buffer
  Protected bufferData.s
  
  Delay(100)

  *buffer = AllocateMemory(Val(Cli(2)))

  ReceiveNetworkData(clientID, *buffer, Val(Cli(2)))
  bufferData = PeekS(*buffer, Val(Cli(2)))

  FreeMemory(*buffer)

  ProcedureReturn bufferData

EndProcedure

Procedure SpoolIncomingMail(mailContent.s)

  If OpenFile(0, fileName)
    FileSeek(0, Lof(0))
    WriteString(0, mailContent)
    CloseFile(0)
  EndIf

EndProcedure

;--- Main Program
SetCli()
GetCli()

; Validate TCP/IP Stack
If InitNet() = #False
  PrintN("Error: 0x0001 - No TCP/IP stack available on the system.")
  End
EndIf

; Start Server
If CreateNetworkServer(#PB_Any, Val(Cli(0)), #PB_Network_TCP)

  ; Set Windows/1st Line Title
  ConsoleTitle(#TITLE)
  PrintN(#TITLE)
  
  ; Validate if spool directory exists,otherwise createit
  ValidateSpoolDirectory()
  
  ; Display configuration information
  DisplayCli()
  
  ; Loop
  Repeat
    ShutdownSmtpServer()
    ServerEvent = NetworkServerEvent()
    
    If ServerEvent
      clientID = EventClient()
      
      Select ServerEvent
        Case #PB_NetworkEvent_Connect
          SendNetData("220 SMTP Dummy Server is available")
          PrintN("Client session opens:  " + Str(clientID))
          
        Case #PB_NetworkEvent_Disconnect
          PrintN("Client session closed: " + Str(clientID))
          
        Case #PB_NetworkEvent_Data
          
          result = ReceiveNetData()    
          
          If Left(Trim(LCase(result)), 4) = "data"
            flag = 1
            fileName = Cli(1) + GetRandomNumber() + ".txt"
            SendNetData("354 Add your data information.")
            
            Repeat
              result = ReceiveNetData()
              If FindString(Right(result, 20), "QUIT", 1)
                flag = 0
                ;PrintN(Left(result, Len(result) - 11))
                SpoolIncomingMail(Left(result, Len(result) - 11))
                SendNetData("221 Bye.")
                CloseNet()
                PrintN(" [" + Str(clientID) + "] Spooled: " + fileName)
                PrintN("Client session closed: " + Str(clientID))
                
              ElseIf FindString(Right(result, 20), "RSET", 1)
                flag = 0
                ;PrintN(Left(result, Len(result) - 11))
                SpoolIncomingMail(Left(result, Len(result) - 11))
                PrintN(" [" + Str(clientID) + "] Spooled: " + fileName)
                
              ElseIf FindString(Right(result, 20), "." + Chr(13), 1)
                flag = 0
                ;PrintN(Left(result, Len(result) - 5))
                SpoolIncomingMail(Left(result, Len(result) - 5))
                PrintN(" [" + Str(clientID) + "] Spooled: " + fileName)
                SendNetData("250 Mail has been queued successfully.")
                
              Else
                ;PrintN(result)
                SpoolIncomingMail(result)
              EndIf
            Until flag = 0
            
          ElseIf result = "."
            SendNetData("250 Mail has been queued successfully.")
          ElseIf Left(Trim(LCase(result)), 4) = "quit"
            SendNetData("221 Bye.")
            CloseNet()
            PrintN("Client session closed: " + Str(clientID))
          ElseIf Right(result, 2) = Chr(13)+ Chr(10)
            SendNetData("250 OK")
          EndIf          
          
      EndSelect
    EndIf
    
    Delay(20)
  Until Quit = 1

  CloseNetworkServer(0)
Else
  PrintN("Cannot start server.Port is already busy.")
  End
EndIf

End
Erstellt mit PB 4.3 Win x86.

Danke + Gruß,
Daniel