Email mit SMTP-Auth

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Email mit SMTP-Auth

Beitrag von Kiffi »

ich auch mal :-)

* res.s wird nirgendwo verwendet
* CloseNetworkConnection() fehlt
* Define innerhalb einer Procedure() -> Protected

und mit dieser kleinen Proc:

Code: Alles auswählen

Procedure SendString(ConnectionID, StringToSend.s)
  StringToSend + #CRLF$
  SendNetworkData(ConnectionID, @StringToSend, Len(StringToSend))
EndProcedure
kannst Du jedes

Code: Alles auswählen

SendString = "bla"+Chr(13)+Chr(10)
SendNetworkData(ConnectionID,@SendString,Len(SendString))
zu:

Code: Alles auswählen

SendString(ConnectionID, "bla")
verkürzen.

Grüße ... Kiffi
a²+b²=mc²
Der-T
Beiträge: 65
Registriert: 06.05.2009 20:01

Re: Email mit SMTP-Auth

Beitrag von Der-T »

X360 Andy hat geschrieben:Vielen dank für das bereitstellen :)
Hallo Andy, kein Problem. Wie geschrieben habe ich ja letzten Endes auch vom CAV und von Wikipedia profitiert, also von arbeiten anderer, welche ebenfalls veröffentlicht wurden. Ich habe daher kein Problem damit, diesen Code für den sich der Aufwand doch auch in Grenzen hielt hier zu veröffentlichen. Ich werde allerding auch noch versuchen, ihn gem. dem hier gegebenen Feedback zu verbessern.
Andreas21 hat geschrieben:In Zeile 19 und 20 wertest du die Antwort vom Server aus.
Der Server sendet aber diese nur 1 mal. Da bleibt der Code stehen.
Das müste geändert werden.
Hallo Andreas, danke für den Hinweis, sehr aufmerksam. Aber wenn du mit dem Code wirklich mal Mails versenden willst, sollte an dieser Stelle besser nichts geändert werden, denn es ist hier tatsächlich so, dass der Mail-Server zwei Statusmeldungen hintereinander sendet, ohne dazwischen Daten zu empfangen. Das Beispiel-Prtokoll von Wikipedia nachdem ich den Code geschrieben habe sieht so aus:

Code: Alles auswählen

> 220 mail.example.org ESMTP
< EHLO example.net

> 250-example.org Hello example.net
> 250 AUTH CRAM-MD5 LOGIN PLAIN

< AUTH LOGIN
> 334 VXNlcm5hbWU6
< aGFucw==
> 334 UGFzc3dvcmQ6
< c2Nobml0emVsbWl0a2FydG9mZmVsc2FsYXQ=
> 235 ok
< MAIL FROM: <hans@example.net>
> 250 ok
< RCPT TO: <fritz@example.org>
> 250 ok
< DATA
> 354 Go ahead.
< From: <hans@example.net>
< To: <fritz@example.org>
< Subject: Hallo
< 
< Hallo Fritz
< .
> 250 Mail delivered.
< QUIT
Und ein InitNetwork() mit rein nehmen damit der Code auch lauffähig ist.
Da es sich hier ja eh nur um einen Ausschnitt und nicht um ein vollständiges Programm handelt, muss man auch mal voraussetzen, dass interessierte ggf. selbst ihr Wissen anwenden ;)
Kiffi hat geschrieben:ich auch mal :-)

* res.s wird nirgendwo verwendet
* CloseNetworkConnection() fehlt
* Define innerhalb einer Procedure() -> Protected

und mit dieser kleinen Proc:

Code: Alles auswählen

Procedure SendString(ConnectionID, StringToSend.s)
  StringToSend + #CRLF$
  SendNetworkData(ConnectionID, @StringToSend, Len(StringToSend))
EndProcedure
kannst Du jedes

Code: Alles auswählen

SendString = "bla"+Chr(13)+Chr(10)
SendNetworkData(ConnectionID,@SendString,Len(SendString))
zu:

Code: Alles auswählen

SendString(ConnectionID, "bla")
verkürzen.

Grüße ... Kiffi
Hallo Kiffi, vielen Dank für die Anmerkungen, werden direkt umgesetzt. Bezüglich deiner Send-Procedure, nun manchmal sieht man eben den Wald vor lauter Bäumen nicht ... :D
Gruß
Der-T
PB 4.50 RC2
Andreas21
Beiträge: 390
Registriert: 30.08.2004 09:05
Computerausstattung: Desktop
Windows 10 Pro x64
CPU: AMD Ryzen 5 2600 3.40 GHz
Ram: 16GB RAM
Grafik: NVIDA Geforce 1060
PB: 5.72 X86/X64
Wohnort: Heidelberg

Re: Email mit SMTP-Auth

Beitrag von Andreas21 »

Nur das ich damit bei GMX keine senden konnte und wenn ich dan die eine abfrage raus genommen habe, hats geklapt.

Mit der 2 Abfrage bekomme ich immer die Meldung das GMX die verbindung beendet hat.
Windows 10 x64 Pro - PB 5.61 X64 / x32 - PB 4.6 x32
Der-T
Beiträge: 65
Registriert: 06.05.2009 20:01

Re: Email mit SMTP-Auth

Beitrag von Der-T »

Das ist seltsam, denn mit GMX hatte ich den Code ebenfalls getestet. Ich werde mir das ganze nochmal ansehen, will den Code ja eh gem. den Anmerkungen von Dark noch etwas überarbeiten. Bis dahin habe ich aber gerade die letzte Überarbeitung nach den Anregungen der anderen Beiträge hier eingefügt.
Gruß
Der-T
PB 4.50 RC2
Andreas21
Beiträge: 390
Registriert: 30.08.2004 09:05
Computerausstattung: Desktop
Windows 10 Pro x64
CPU: AMD Ryzen 5 2600 3.40 GHz
Ram: 16GB RAM
Grafik: NVIDA Geforce 1060
PB: 5.72 X86/X64
Wohnort: Heidelberg

Re: Email mit SMTP-Auth

Beitrag von Andreas21 »

Mein Debug sied so aus:

Mit den 2 Abfragen

Code: Alles auswählen

220 mail.gmx.net GMX Mailservices ESMTP {mp005}
250-mail.gmx.net GMX Mailservices
250-8BITMIME
250-ENHANCEDSTATUSCODES
250-SIZE
250-AUTH=LOGIN PLAIN
250-AUTH LOGIN PLAIN
250 STARTTLS
Wenn ich die zweite Abfrage wieder raus nehme bekomme ich das

Code: Alles auswählen

220 mail.gmx.net GMX Mailservices ESMTP {mp065}
250-mail.gmx.net GMX Mailservices
250-8BITMIME
250-ENHANCEDSTATUSCODES
250-SIZE
250-AUTH=LOGIN PLAIN
250-AUTH LOGIN PLAIN
250 STARTTLS
334 ***********
334 ***********
235 2.7.0 Go ahead {mp065}
250 2.1.0 ok {mp065}
250 2.1.5 ok {mp065}
354 mail.gmx.net Go ahead {mp065}
250 2.6.0 Message accepted {mp065}
Damit hab ich Debug gemacht.

Code: Alles auswählen

Procedure.s ReceiveData(ConnectionID)
  Define DataResult.s
  DataResult = Space(4999)
  ReceiveNetworkData(ConnectionID,@DataResult,4999)   
  Debug DataResult
  DataResult = Left(DataResult,3)
  ProcedureReturn DataResult
EndProcedure
Windows 10 x64 Pro - PB 5.61 X64 / x32 - PB 4.6 x32
Der-T
Beiträge: 65
Registriert: 06.05.2009 20:01

Re: Email mit SMTP-Auth

Beitrag von Der-T »

Hallo Andreas,

danke für die Bereitstellung von dem Protokoll. Wie geschrieben, werde ich mich dem Code nochmal annehmen und versuchen einen zu erstellen, der in allen Fällen korrekt arbeitet. Leider kann ich im Moment noch nicht sagen, wann ich diesen zur Verfügung stellen kann.
Gruß
Der-T
PB 4.50 RC2
Benutzeravatar
rolaf
Beiträge: 3843
Registriert: 10.03.2005 14:01

Re: Email mit SMTP-Auth

Beitrag von rolaf »

Habe mir erlaubt mal ein bisschen aufzuräumen und Kiffis Anregung aufzunehmen...

Code: Alles auswählen

;Email (PB 4.41, PB 4.50)
;von Der-T, Kiffi, ..., ...

InitNetwork()

Procedure.s ReceiveData(ConnectionID)
  Define DataResult.s
  DataResult = Space(4999)
  ReceiveNetworkData(ConnectionID,@DataResult,4999)   
  Debug DataResult
  DataResult = Left(DataResult,3)
  ProcedureReturn DataResult
EndProcedure

Procedure SendString(ConnectionID, StringToSend.s)
  StringToSend + #CRLF$
  SendNetworkData(ConnectionID, @StringToSend, Len(StringToSend))
EndProcedure

Procedure SendMyMail(Server.s, User.s, Pass.s, MailFrom.s, MailTo.s, Betreff.s, Inhalt.s)
  Protected ReturnValue = 0     
  Protected ConnectionID = OpenNetworkConnection(Server, 25)
  Protected TmpString.s
  If ConnectionID
    If ReceiveData(ConnectionID) = "220"
      SendString(ConnectionID, "EHLO localhost")
      If ReceiveData(ConnectionID) = "250"
        SendString(ConnectionID, "AUTH LOGIN")
        If ReceiveData(ConnectionID) = "334"
          TmpString = Space(1024)
          Base64Encoder(@User, StringByteLength(User), @TmpString, 1024)
          SendString(ConnectionID, TmpString)
          If ReceiveData(ConnectionID) = "334"
            TmpString = Space(1024)
            Base64Encoder(@Pass, StringByteLength(Pass), @TmpString, 1024)
            SendString(ConnectionID, TmpString)
            If ReceiveData(ConnectionID) = "235"
              SendString(ConnectionID, "MAIL FROM: <" + MailFrom + ">")
              If ReceiveData(ConnectionID) = "250"
                SendString(ConnectionID, "RCPT TO: <" + MailTo + ">")
                If ReceiveData(ConnectionID) = "250"
                  SendString(ConnectionID, "DATA")  
                  If ReceiveData(ConnectionID) = "354"
                    SendString(ConnectionID, "From: <" + MailFrom + ">")
                    SendString(ConnectionID, "To: <" + MailTo + ">")
                    SendString(ConnectionID, "Subject: " + Betreff + #CRLF$)
                    SendString(ConnectionID, Inhalt)
                    SendString(ConnectionID, ".")
                    If ReceiveData(ConnectionID) = "250"
                      SendString(ConnectionID, "QUIT")
                      ReturnValue = 1                     
                    EndIf                 
                  EndIf                     
                EndIf                   
              EndIf                 
            EndIf               
          EndIf             
        EndIf           
      EndIf         
    EndIf     
  EndIf
  CloseNetworkConnection(ConnectionID)
  ProcedureReturn ReturnValue
EndProcedure

SendMyMail("mailserver.dein" ,"user" ,"passwort" ,"mailaddy_von", "mailaddy_an" ,"Betreff" ,"Inhalt")
Funktioniert bei mir einwandfrei! :allright:

Edit: Sorry, gerade gesehen das Kiffis Vorschläge schon am 12.7. im Startposting eingepflegt wurden. Meine "Mitarbeit" ist daher für die runde Endablage = Mülleimer. :oops: Die Wärme, ich sags ja...
Zuletzt geändert von rolaf am 15.07.2010 11:10, insgesamt 5-mal geändert.
:::: WIN 10 :: PB 5.73 :: (x64) ::::
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Email mit SMTP-Auth

Beitrag von NicTheQuick »

Jetzt noch das Denglish rausnehmen und alle sind froh. :wink:
Benutzeravatar
rolaf
Beiträge: 3843
Registriert: 10.03.2005 14:01

Re: Email mit SMTP-Auth

Beitrag von rolaf »

NicTheQuick hat geschrieben:Jetzt noch das Denglish rausnehmen und alle sind froh. :wink:
Jo, mach mal - mir ist schon wieder zu warm. :mrgreen:
:::: WIN 10 :: PB 5.73 :: (x64) ::::
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Email mit SMTP-Auth

Beitrag von NicTheQuick »

Sorry, hab das ganze mal komplett verbessert.

Übersichtlicher, sicherer und Unicode-fähig.

Code: Alles auswählen

;Email (PB 4.41, PB 4.50)
;von Der-T, Kiffi, DrFalo, NicTheQuick, ...

EnableExplicit

InitNetwork()

#MAIL_BUFFER = 1024

Procedure.s Mail_ReceiveString(*hConnection.Integer)
	If (Not *hConnection\i)
		ProcedureReturn ""
	EndIf
	Protected DataResult.s = ""
	Protected *mem = AllocateMemory(#MAIL_BUFFER), received.i
	Repeat
		received = ReceiveNetworkData(*hConnection\i, *mem, #MAIL_BUFFER)
		If (received = -1)
			Debug "ReceiveNetworkData() returns error -1. Received Data: '" + DataResult + "'"
			*hConnection\i = 0
			Break
		EndIf
		DataResult + PeekS(*mem, received, #PB_Ascii)
	Until received < #MAIL_BUFFER
	Debug "Debug 'DataResult':" + #CRLF$ + DataResult
	FreeMemory(*mem)
	ProcedureReturn DataResult
EndProcedure

Procedure Mail_SendString(*hConnection.Integer, StringToSend.s)
	If (Not *hConnection\i)
		ProcedureReturn
	EndIf
	StringToSend + #CRLF$
	Protected sent.i = 0, length = Len(StringToSend), res.i
	Protected *mem = AllocateMemory(length + 1)
	
	PokeS(*mem, StringToSend, length, #PB_Ascii)
	
	Repeat
		res = SendNetworkData(*hConnection\i, *mem + sent, length - sent)
		If (res = -1)
			Debug "SendNetworkData() returns error -1. Sent Data: '" + PeekS(*mem, sent, #PB_Ascii) + "'"
			*hConnection = 0
			Break
		EndIf
		sent + res
	Until sent = length
	FreeMemory(*mem)
EndProcedure

Procedure Mail_CheckAnswer(*hConnection.Integer, expected.s)
	If (Not *hConnection\i)
		ProcedureReturn #False
	EndIf
	Protected answer.s = Mail_ReceiveString(*hConnection)
	If (Left(answer, Len(expected)) = expected)
		ProcedureReturn #True
	EndIf
	Debug "Server says '" + answer + "', but expected was '" + expected + "'"
	*hConnection\i = 0
	ProcedureReturn #False
EndProcedure

Procedure.s Mail_Base64Encoder(string.s)
	Protected *mem = AllocateMemory(Len(string) + 1)
	Protected result.s = Space(Len(string) * 3 / 2)
	
	PokeS(*mem, string, Len(string), #PB_Ascii)
	Base64Encoder(*mem, Len(string), @result, Len(result))
	
	FreeMemory(*mem)
	
	ProcedureReturn result
EndProcedure

Procedure Mail_Send(Server.s, User.s, Pass.s, MailFrom.s, MailTo.s, Subject.s, Content.s)
	Protected ConnectionID.i = OpenNetworkConnection(Server, 25), state.i
	Protected TmpString.s
	
	If ConnectionID
		state = ConnectionID
		Mail_CheckAnswer(@state, "220")
		Mail_SendString(@state, "EHLO localhost")
		Mail_CheckAnswer(@state, "250")
		Mail_SendString(@state, "AUTH LOGIN")
		Mail_CheckAnswer(@state, "334")
		Mail_SendString(@state, Mail_Base64Encoder(User))
		Mail_CheckAnswer(@state, "334")
		Mail_SendString(@state, Mail_Base64Encoder(Pass))
		Mail_CheckAnswer(@state, "235")
		Mail_SendString(@state, "MAIL FROM: <" + MailFrom + ">")
		Mail_CheckAnswer(@state, "250")
		Mail_SendString(@state, "RCPT TO: <" + MailTo + ">")
		Mail_CheckAnswer(@state, "250")
		Mail_SendString(@state, "DATA")
		Mail_CheckAnswer(@state, "354")
		Mail_SendString(@state, "From: <" + MailFrom + ">")
		Mail_SendString(@state, "To: <" + MailTo + ">")
		Mail_SendString(@state, "Subject: " + Subject + #CRLF$)
		Mail_SendString(@state, Content)
		Mail_SendString(@state, ".")
		Mail_CheckAnswer(@state, "250")
		Mail_SendString(@state, "QUIT")
		
		CloseNetworkConnection(ConnectionID)
	EndIf
	
	
	ProcedureReturn state
EndProcedure

Define result.i
result = Mail_Send("Server" ,"User" ,"Pass" ,"MailFrom", "MailTo" ,"Subject ,"Content")
Debug "Mail_Send returns: " + Str(result)
Leider mag unser Uni-Mail-Server keine Authentifizierung. Aber wen's interessiert. Hier das Log:
Debug 'DataResult':

220 triton.rz.uni-saarland.de ESMTP Sendmail; Thu, 15 Jul 2010 10:34:13 +0200


Debug 'DataResult':

250-triton.rz.uni-saarland.de Hello wpa-uds054.funklan.uni-saarland.de [134.96.118.63], pleased to meet you

250-ENHANCEDSTATUSCODES

250-PIPELINING

250-8BITMIME

250-SIZE 21485760

250-DSN

250-ETRN

250-STARTTLS

250-DELIVERBY

250 HELP


Debug 'DataResult':

503 5.3.3 AUTH not available


Server says '503 5.3.3 AUTH not available

', but expected was '334'
Mail_Send returns: 0
Antworten