SMTP client functions (no authorization)

Miscellaneous Forums/Blitz Showcase/SMTP client functions (no authorization)

I've created some SMTP client functions. It works fine, but it doesn't support authorization at the moment and i don't have any SMTP servers either where i could authorize myself, so could anybody help me on that part.

Usage example:
SMTPStream% = SMTPConnect("smtp.some-server.com", "username", "password")
SMTPSendHeader(SMTPStream%, "mail@...", "rcpt@...", "Mail subject")
WriteLine SMTPStream%, "This is the message"
SMTPEndMail(SMTPStream%)


Functions:
Global SMTPError$ = ""

Function SMTPConnect%(server$, username$ = "", password$ = "", port% = 25)
	Local stream% = OpenTCPStream(server$, port%)
	Local AUTH_type% = 0 ; 1 - LOGIN, 2 - PLAIN, 3 - DIGEST-MD5, 4 - CRAM-MD5
	
	If stream%
		While Not Eof(stream%)
			If Not msg$ = ""
				DebugLog "SMTP>>>" + msg$
				WriteLine stream%, msg$
			EndIf
			
			If ReadAvail(stream%)
				txt$ = ReadLine$(stream%): DebugLog "SMTP<<<" + txt$
				code$ = Left$(txt$, 3)
				cmd$ = Mid(txt$, 5)
				value$ = Sector(cmd$, " ", 1, True)
				cmd$ = Sector(cmd$, " ", 0)
			Else
				txt$ = "": code$ = "": cmd$ = "": value$ = ""
			EndIf
			
			msg$ = ""
			Select code$
				Case "220"
					msg$ = "EHLO " + server$
				Case "250"
					; COMMAND
					Select cmd$
						Case "AUTH"
							; SET AUTH type
							If Instr(value$, "PLAIN") Then AUTH_type% = 2
							If Instr(value$, "DIGEST-MD5") Then AUTH_type% = 3
							If Instr(value$, "CRAM-MD5") Then AUTH_type% = 4
							If Instr(value$, "LOGIN") Then AUTH_type% = 1
							
							Select AUTH_type%
								Case 1
									msg$ = "AUTH LOGIN"
								Case 2
									msg$ = "AUTH PLAIN " + base64_enc$(username$ + Chr(0) + username$ + Chr(0) + password$)
								Case 3
									msg$ = "AUTH DIGEST-MD5"
								Case 4
									msg$ = "AUTH CRAM-MD5"
							End Select
						Case "8BITMIME" ; No AUTH type
							If AUTH_type% = 0 Then Return stream%
					End Select
				Case "334" ; AUTH type ok
					Select AUTH_type%
						Case 1 ; LOGIN
							Select cmd$
								Case "VXNlcm5hbWU6" ; Username
									msg$ = base64_enc$(username$)
								Case "UGFzc3dvcmQ6" ; Password
									msg$ = base64_enc$(password$)
							End Select
						Case 3 ; DIGEST-MD5
						Case 4 ; CRAM-MD5
					End Select
				Case "535", "501" ; Authorization failed
					SMTPError$ = Mid(txt$, 5)
					
					CloseTCPStream stream%
					Return False
				Case "235" ; Authorized
					If AUTH_type% = 0 Then Return stream%
			End Select
		Wend
		
		Return stream%
	EndIf
End Function

Function SMTPSendHeader(stream%, from$, rcpt$, subject$)
	Local index% = 0, msg$
	
	msg$ = "MAIL FROM:<" + from$ + ">"
	While Not Eof(stream%)
		If ReadAvail(stream%)
			txt$ = ReadLine$(stream%): DebugLog "SMTP<<<" + txt$
			code$ = Left$(txt$, 3)
			cmd$ = Mid(txt$, 5)
		Else
			code$ = "": cmd$ = ""
		EndIf
		
		If Not msg$ = ""
			DebugLog "SMTP>>>" + msg$
			WriteLine stream%, msg$
		EndIf
		
		msg$ = ""
		Select code$
			Case ""
			Case "250"
				index% = index% + 1
				Select index%
					Case 1
						msg$ = "RCPT TO:<" + rcpt$ + ">"
					Case 2
						msg$ = "DATA"
					Case 3
				End Select
			Case "354"
				msg$ = "Subject: " + subject$
				DebugLog "SMTP>>>" + msg$
				WriteLine stream%, msg$ + Chr(13) + Chr(10)
				Return True
			Default
				SMTPError$ = Mid(txt$, 5)
				Return False
		End Select
	Wend
End Function

Function SMTPEndMail(stream%)
	WriteLine stream%, "."
	WriteLine stream%, "QUIT"
	CloseTCPStream stream%
End Function

Function SMTPLastError$()
	Return SMTPError$
End Function

Function base64_enc$(inp$)
	Local b64_enc$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
	Local nl$ = Chr$(13) + Chr$(10)
	Local out$, trp$, char, i = 1
		
	Repeat
		trp$ = Mid$(inp$, i, 3)
	
		Select Len(trp$)
			Case 3
				out$ = out$ + Mid$(b64_enc$, (Asc(Mid$(trp$, 1, 1)) Shr 2) + 1, 1)
				out$ = out$ + Mid$(b64_enc$, (((Asc(Mid$(trp$, 1, 1)) Shl 4) Or (Asc(Mid$(trp$, 2, 1)) Shr 4)) And $3f) + 1, 1)
				out$ = out$ + Mid$(b64_enc$, (((Asc(Mid$(trp$, 2, 1)) Shl 2) Or (Asc(Mid$(trp$, 3, 1)) Shr 6)) And $3f) + 1, 1)
				out$ = out$ + Mid$(b64_enc$, (Asc(Mid$(trp$, 3, 1)) And $3f) + 1, 1)
			Case 2
				out$ = out$ + Mid$(b64_enc$, (Asc(Mid$(trp$, 1, 1)) Shr 2) + 1, 1)
				out$ = out$ + Mid$(b64_enc$, (((Asc(Mid$(trp$, 1, 1)) Shl 4) Or (Asc(Mid$(trp$, 2, 1)) Shr 4)) And $3f) + 1, 1)
				out$ = out$ + Mid$(b64_enc$, ((Asc(Mid$(trp$, 2, 1)) Shl 2) And $3f) + 1, 1)
				out$ = out$ + "="
			Case 1
				out$ = out$ + Mid$(b64_enc$, (Asc(Mid$(trp$, 1, 1)) Shr 2) + 1, 1)
				out$ = out$ + Mid$(b64_enc$, ((Asc(Mid$(trp$, 1, 1)) Shl 4) And $3f) + 1, 1)
				out$ = out$ + "=="
		End Select
	
		i = i + 3
		char = char + 4
		If char = 76
			out$ = out$ + nl$
			char = 0
		EndIf
	Until i > Len(inp$)
	If char And add_nl Then out$ = out$ + nl$
	
	Return out$
End Function

Function Sector$(txt$, separator$, sector%, toend% = False)
	Local result$ = "", occ
	For i = 1 To Len(txt$)
		If Mid$(txt$, i, 1) = separator$
			occ = occ + 1
			If toend% And occ% > sector% Then result$ = result$ + Mid$(txt$, i, 1)
		Else
			If occ => sector Then result$ = result$ + Mid$(txt$, i, 1)
		EndIf
		If Not toend% Then If occ > sector Then Exit
	Next
	Return result$
End Function


Function 'sector' not found

Sorry for that, added it.

Sounds cool, but I cant get it to connect to hotmail/yahoo

Probably because it needs authorization, enable debugging. I'll try tu use it with my own account on hotmail.

dont you guys have an ISP that provides e-mail ? if you do then smtp.yourISP.com

Most ISP's dont request any authentication for sending mail, they check your IP and Mac off of their list and then allow you to send/connect so it shouldnt be needed. Unless your trying to use a server thats not your ISP like yahoo or some other random server.

PS. this code could come in handy for making one of those E-Mail games where moves are made and sent via mail.

@Andres - Judging by some of your code, it would appear that you've already found this (the authentication has been tested and works)??

@Xzider - Hotmail/Yahoo aren't SMTP servers, AFAIR they use the webDAV HTTP extension.

@Yavin, yes, like i said it works well, but i'd like the code to work with authorization too.

@Yan, Nope didin't found that. I read examples and reference from "googling".
I just added the authorization as I think it would work, but i haven't tested it. I've only got as far as it says "Authorization failed", but no "Authorization successfull" message yet. It seems that i don't need to create my own functions anymore, i'll just use your code :). Does your code support "Progressbar"? :P