auch wenn der Code sicher dieselben Fehler hat, wie bereits weiter vorn kritisiert, wollte ich ihn doch mal posten. Er ist schon einen Schluck älter, realisiert aber die Anmeldung auf SMTP-Servern auf 3 verschiedene Weisen. 2 mal mit unverschlüsseltem Passwort und CRAM-MD5 mit Passworthash.
Code: Alles auswählen
EnableExplicit
#auth_plain = "PLAIN"
#auth_login = "LOGIN"
#auth_md5 = "CRAM-MD5"
#auth_sha1 = "SCRAM-SHA-1" ;not supported
#server = "smtp.server.de"
#port = 25
#auth = #auth_md5
#user = "user"
#pass = "pass"
#from = "adress"
#to = "adress"
#subject = "subject"
#text = "text"
#max_len = 65536
Procedure my_poke_s(*pointer, string.s)
Protected *temp = AllocateMemory(Len(string) + 1)
PokeS(*temp, string, Len(string), #PB_Ascii)
CopyMemory(*temp, *pointer, Len(string))
FreeMemory(*temp)
EndProcedure
Procedure send_string(connection.l, string.s)
Protected *buffer = AllocateMemory(Len(string) + 4)
PokeS(*buffer, string, Len(string), #PB_Ascii)
PokeC(*buffer + Len(string), 13) ; add the additional sring end
PokeC(*buffer + Len(string) + 1, 10)
;WriteStringN(1, "-> " + string)
SendNetworkData(connection, *buffer, Len(string) + 2)
EndProcedure
Procedure.s receive_string(connection.l)
Protected *buffer = AllocateMemory(#max_len)
Protected length.l
Protected string.s
length = ReceiveNetworkData(connection, *buffer, #max_len)
string = PeekS(*buffer, length, #PB_Ascii)
;WriteStringN(1, "<- " + string)
ProcedureReturn string
EndProcedure
Procedure.s encode_base_64(string.s)
Protected length.l
Protected out_length.l = 64 + 2 * Len(string)
Protected *in_buffer = AllocateMemory(Len(string) + 1)
Protected *out_buffer = AllocateMemory(out_length)
PokeS(*in_buffer, string, Len(string), #PB_Ascii)
length = Base64Encoder(*in_buffer, Len(string), *out_buffer, out_length)
ProcedureReturn PeekS(*out_buffer, length, #PB_Ascii)
EndProcedure
Procedure.s decode_base_64(string.s)
Protected length.l
Protected out_length.l = 64 + 2 * Len(string)
Protected *in_buffer = AllocateMemory(Len(string) + 1)
Protected *out_buffer = AllocateMemory(out_length)
PokeS(*in_buffer, string, Len(string), #PB_Ascii)
length = Base64Decoder(*in_buffer, Len(string), *out_buffer, out_length)
ProcedureReturn PeekS(*out_buffer, length, #PB_Ascii)
EndProcedure
Procedure.a connect_plain(connection.l, user.s, pass.s)
Protected out.a = 0
Protected string.s
Protected *buffer
Protected *code
Protected length.l
send_string(connection, "AUTH " + #auth_plain)
string = receive_string(connection)
If (Left(string, 3) = "334")
; string contains null -> encode_base_64 not useable
*buffer = AllocateMemory(2 + Len(user) + Len(pass))
my_poke_s(*buffer + 1, user)
my_poke_s(*buffer + 2 + Len(user), pass)
*code = AllocateMemory(64 + 2 * (2 + Len(user) + Len(pass)))
length = Base64Encoder(*buffer, 2 + Len(user) + Len(pass), *code, 64 + 2 * (2 + Len(user) + Len(pass)))
send_string(connection, PeekS(*code, length, #PB_Ascii))
string = receive_string(connection)
If (Left(string, 3) = "235")
out = 1
EndIf
EndIf
ProcedureReturn out
EndProcedure
Procedure.a connect_login(connection.l, user.s, pass.s)
Protected out.a = 0
Protected string.s
send_string(connection, "AUTH " + #auth_login)
string = receive_string(connection)
If (Left(string, 3) = "334")
send_string(connection, encode_base_64(user))
string = receive_string(connection)
If (Left(string, 3) = "334")
send_string(connection, encode_base_64(pass))
string = receive_string(connection)
If (Left(string, 3) = "235")
out = 1
EndIf
EndIf
EndIf
ProcedureReturn out
EndProcedure
#ipad = $36
#opad = $5c
#block_size = 64
Procedure xor_block(*block, value.a)
Protected i.l
For i = 0 To (#block_size - 1)
PokeA(*block + i, PeekA(*block + i) ! value)
Next
EndProcedure
Procedure hex_string_2_bin(string.s, *bin)
Protected size.l
Protected i.l
size = Round(Len(string) / 2, #PB_Round_Down)
For i = 0 To (size - 1)
PokeA(*bin, Val("$" + Mid(string, i * 2 + 1, 2)))
*bin = *bin + 1
Next
EndProcedure
Procedure.s hmac_md5(key.s, text.s)
Protected *i_key
Protected *o_key
Protected *front_part
Protected *back_part
Protected *text = AllocateMemory(#block_size)
Protected fingerprint.s
Protected *fingerprint
*i_key = AllocateMemory(#block_size)
my_poke_s(*i_key, key)
xor_block(*i_key, #ipad)
*back_part = AllocateMemory(#block_size + Len(text))
CopyMemory(*i_key, *back_part, #block_size)
my_poke_s(*back_part + #block_size, text)
fingerprint = MD5Fingerprint(*back_part, #block_size + Len(text))
*fingerprint = AllocateMemory(16)
hex_string_2_bin(fingerprint, *fingerprint)
*o_key = AllocateMemory(#block_size)
my_poke_s(*o_key, key)
xor_block(*o_key, #opad)
*front_part = AllocateMemory(#block_size + Len(fingerprint))
CopyMemory(*o_key, *front_part, #block_size)
CopyMemory(*fingerprint, *front_part + #block_size, 16)
fingerprint = MD5Fingerprint(*front_part, #block_size + 16)
ProcedureReturn fingerprint
EndProcedure
Procedure.s hmac_sha1(key.s, text.s)
Protected *i_key
Protected *o_key
Protected *front_part
Protected *back_part
Protected *text = AllocateMemory(#block_size)
Protected fingerprint.s
Protected *fingerprint
*i_key = AllocateMemory(#block_size)
my_poke_s(*i_key, key)
xor_block(*i_key, #ipad)
*back_part = AllocateMemory(#block_size + Len(text))
CopyMemory(*i_key, *back_part, #block_size)
my_poke_s(*back_part + #block_size, text)
fingerprint = SHA1Fingerprint(*back_part, #block_size + Len(text))
*fingerprint = AllocateMemory(20)
hex_string_2_bin(fingerprint, *fingerprint)
*o_key = AllocateMemory(#block_size)
my_poke_s(*o_key, key)
xor_block(*o_key, #opad)
*front_part = AllocateMemory(#block_size + Len(fingerprint))
CopyMemory(*o_key, *front_part, #block_size)
CopyMemory(*fingerprint, *front_part + #block_size, 20)
fingerprint = SHA1Fingerprint(*front_part, #block_size + 20)
ProcedureReturn fingerprint
EndProcedure
Procedure.a connect_md5(connection.l, user.s, pass.s)
Protected out.a = 0
Protected string.s
Protected challenge.s
Protected *buffer
send_string(connection, "AUTH " + #auth_md5)
string = receive_string(connection)
If (Left(string, 3) = "334")
challenge = Mid(string, 5, Len(string) - 6)
send_string(connection, encode_base_64(user + " " + hmac_md5(pass, decode_base_64(challenge))))
string = receive_string(connection)
If (Left(string, 3) = "235")
out = 1
EndIf
EndIf
ProcedureReturn out
EndProcedure
Procedure.a connect(connection.l, auth.s, user.s, pass.s)
Protected out.a = 0
Protected string.s
Protected position.l
string = receive_string(connection)
If (Left(string, 3) = "220")
If (FindString(string, "ESMTP", 1))
send_string(connection, "EHLO program.purebasic.com")
string = receive_string(connection)
If (Left(string, 3) = "250")
position = FindString(string, "AUTH", 1)
If position
If FindString(string, auth, position + 4)
Select auth
Case #auth_plain
If (connect_plain(connection, user, pass))
out = 1
EndIf
Case #auth_login
If (connect_login(connection, user, pass))
out = 1
EndIf
Case #auth_md5
If (connect_md5(connection, user, pass))
out = 1
EndIf
EndSelect
EndIf
EndIf
EndIf
EndIf
EndIf
ProcedureReturn out
EndProcedure
Procedure.a send_content(connection.l, from_adress.s, to_adress.s, subject.s, text.s)
Protected out.a = 0
Protected string.s
send_string(connection, "MAIL FROM:<" + from_adress + ">")
string = receive_string(connection)
If (Left(string, 3) = "250")
send_string(connection, "RCPT TO:<" + to_adress + ">")
string = receive_string(connection)
If (Left(string, 3) = "250")
send_string(connection, "DATA")
string = receive_string(connection)
If (Left(string, 3) = "354")
send_string(connection, "From:<" + from_adress + ">")
send_string(connection, "To:<" + to_adress + ">")
send_string(connection, "Subject: " + subject)
send_string(connection, text)
send_string(connection, ".")
string = receive_string(connection)
If (Left(string, 3) = "250")
out = 1
EndIf
EndIf
EndIf
EndIf
ProcedureReturn out
EndProcedure
Procedure.a send_mail(server.s, port.c, auth.s, user.s, pass.s, from_adress.s, to_adress.s, subject.s, text.s)
Protected out.a = 0
Protected connection.l
Protected string.s
;CreateFile(1, "out.txt")
If InitNetwork()
connection = OpenNetworkConnection(server, port, #PB_Network_TCP)
If connection
If connect(connection, auth, user, pass)
If send_content(connection, from_adress, to_adress, subject, text)
out = 1
EndIf
EndIf
send_string(connection, "QUIT")
string = receive_string(connection)
CloseNetworkConnection(connection)
EndIf
EndIf
;CloseFile(1)
ProcedureReturn out
EndProcedure
send_mail(#server, #port, #auth, #user, #pass, #from, #to, #subject, #text)