Jump to content

_INetSmtpMail


Recommended Posts

I'm trying to send mail to a smtp server but it needed a login. Thus i looked around and i found this

http://www.jonfullmer.com/smtpauth/

http://makcoder.sourceforge.net/demo/base64.php

Long story short I dont know how to code a base64 converter, but i think i improved the UDF code because it was hard to understand. So i took out and added stuff while makeing it work better in my opinion, and its easier to read. Only thing is it will only do smtp if you have a login and password, but it shouldn't be that hard to bring the two code bases together.

Func _INetSmtpMail($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject = "", $as_Body = "", $s_username = "", $s_password = "", $LoginString = "", $s_helo = "")
    
    Local $v_Socket
    Local $s_IPAddress
    Local $i_Count
    Local $s_Send[11]
    Local $s_ReplyCode[11];Return code from SMTP server indicating success
    
    If $s_SmtpServer = "" Or $s_FromAddress = "" Or $s_ToAddress = "" Or $s_FromName = "" Or StringLen($s_FromName) > 256 Then
        SetError(1)
        Return 0
    EndIf
    If $s_helo = "" Then $s_helo = @ComputerName
    If $LoginString = "" Then $LoginString = "HELO"

;Start Connection
    If TCPStartup() = 0 Then
        SetError(2)
        Return 0
    EndIf
    StringRegExp($s_SmtpServer, "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
    If @extended Then
        $s_IPAddress = $s_SmtpServer
    Else
        $s_IPAddress = TCPNameToIP($s_SmtpServer)
    EndIf
    If $s_IPAddress = "" Then
        TCPShutdown()
        SetError(3)
        Return 0
    EndIf
    $v_Socket = TCPConnect($s_IPAddress, 25)
    If $v_Socket = -1 Then
        TCPShutdown()
        SetError(4)
        Return (0)
    EndIf
    
;Messages to send 
    $s_Send[2] = "AUTH LOGIN" & @CRLF
    $s_ReplyCode[2] = "334"
    $s_Send[3] = $s_username & @CRLF
    $s_ReplyCode[3] = "334"
    $s_Send[4] = $s_password & @CRLF
    $s_ReplyCode[4] = "235"
    $s_Send[5] = "MAIL FROM: <" & $s_FromAddress & ">" & @CRLF
    $s_ReplyCode[5] = "250"
    $s_Send[6] = "RCPT TO: <" & $s_ToAddress & ">" & @CRLF
    $s_ReplyCode[6] = "250"
    $s_Send[7] = "DATA" & @CRLF
    $s_ReplyCode[7] = "354"
    
    $s_Send[8] =    "From:" & $s_FromName & "<" & $s_FromAddress & ">" & @CRLF & _
            "To:" & "<" & $s_ToAddress & ">" & @CRLF & _
            "Subject:" & $s_Subject & @CRLF & _
            "Mime-Version: 1.0" & @CRLF & _
            "Content-Type: text/plain; charset=US-ASCII" & @CRLF & _
            @CRLF
    $s_ReplyCode[8] = "0"

    $s_Send[9] = @CRLF & "." & @CRLF
    $s_ReplyCode[9] = "0"
    $s_Send[10] = "QUIT" & @CRLF
    $s_ReplyCode[10] = "0"


;Connect to server
    $s_Receive = ""
    While $s_Receive = ""
        $s_Receive = WaitForReply($v_Socket)
        If StringInStr($s_Receive, "220") Then;login
            TCPSend($v_Socket, $LoginString & $s_helo & @CRLF)
            $s_Receive = WaitForReply($v_Socket)
            If Not StringInStr($s_Receive, "250") Then
                TCPSend($v_Socket, "EHLO" & $s_helo & @CRLF)
                $s_Receive = WaitForReply($v_Socket)
                If Not StringInStr($s_Receive, "250") Then
                    TCPSend($v_Socket, "HELO" & $s_helo & @CRLF)
                    $s_Receive = WaitForReply($v_Socket)
                EndIf
            EndIf
        EndIf
    WEnd
    
;Send To, From, Ect...
    For $ii = 2 To 8 Step + 1
        TCPSend($v_Socket, $s_Send[$ii])
        $s_Receive = WaitForReply($v_Socket)
        If Not StringInStr($s_Receive, $s_ReplyCode[$ii]) Then
            MsgBox(0, "", $s_Receive & @CRLF & @CRLF & $s_ReplyCode[$ii] & @CRLF & @CRLF & $s_Send[$ii])
        EndIf
    Next
    
;Send Body
    For $i_Count = 0 To UBound($as_Body) - 1
        If StringLeft($as_Body[$i_Count], 1) = "." Then $as_Body[$i_Count] = "." & $as_Body[$i_Count]
        TCPSend($v_Socket, $as_Body[$i_Count] & @CRLF)
    Next
    
;Flush recv buffer
    $s_Receive = TCPRecv($v_Socket, 1000)
    
;Close Message and Connection
    For $ii = 9 To 10 Step + 1
        TCPSend($v_Socket, $s_Send[$ii])
        $s_Receive = WaitForReply($v_Socket)
        If Not StringInStr($s_Receive, $s_ReplyCode[$ii]) Then
            MsgBox(0, "", $s_Receive & @CRLF & @CRLF & $s_ReplyCode[$ii] & @CRLF & @CRLF & $s_Send[$ii])
        EndIf
    Next
    
    TCPCloseSocket($v_Socket)
    TCPShutdown()
    Return 1
EndFunc  ;==>_INetSmtpMail

;Waits for Reply
Func WaitForReply($v_Socket)
    $counter = 0
    $s_Receive = ""
    While $s_Receive = ""
        $s_Receive = TCPRecv($v_Socket, 1000)
        $counter = $counter + 1
        If $counter > 50 Then
            Return 0
        EndIf
    WEnd
    Return $s_Receive
EndFunc  ;==>WaitForReply



;EXAMPLE CODE
$s_SmtpServer = "smtp.com"
$s_FromName = "Me"
$s_FromAddress = "dude@autoitscript.com"
$s_ToAddress = "spam@hotmail.com"
$s_Subject = "My Test UDF"
Dim $as_Body[2]
$as_Body[0] = "Testing the new email udf"
$as_Body[1] = "Second Line"
$s_username = InputBox("Username", "Username")
$s_password = InputBox("Password", "Password")
Dim $s_helo
Dim $s_first = @CRLF

$Response = _INetSmtpMail($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject, $as_Body, $s_username, $s_password)
$err = @error
If $Response = 1 Then
    MsgBox(0, "Success!", "Mail sent")
Else
    MsgBox(0, "Error!", "Mail failed with error code " & $err)
EndIf

Right now it will keep sending messages when the return code doesn't match but it will popup a msg box to let you know. I tested this with my university account and i got it working. Gmail doesnt allow mail on port 25 so that kinda sucks.

Use the latest Beta, and let me know how this goes. I know its a quick hack but someone had to do it. Username and Password must be in base64!

Link to comment
Share on other sites

I updated this UDF, its written in what I understand so Im sure it can be sped up. I combined mine and most of latest betas UDF. I'm still don't have a base64 converter, so right now I use this webpage to convert it.

http://makcoder.sourceforge.net/demo/base64.php

Also the trace output is actually useful now. I havent implemented any error checking, so I need to do that.

Func _INetSmtpMail($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject = "", $as_Body = "", $s_Trace = "", $s_helo = "", $s_LoginString = "", $s_AuthUser = "", $s_username = "", $s_password = "")
    
    Local $v_Socket
    Local $s_IPAddress
    Local $i_Count
    
    Local $s_Auth[3]
    Local $s_AuthReplyCode[3]
    
    Local $s_Send[4]
    Local $s_SendReplyCode[4];Return code from SMTP server indicating success
    
    Local $s_End[2]
    Local $s_EndReplyCode[2]
    
    If $s_SmtpServer = "" Or $s_FromAddress = "" Or $s_ToAddress = "" Or $s_FromName = "" Or StringLen($s_FromName) > 256 Then
        SetError(1)
        Return 0
    EndIf
    If $s_helo = "" Then $s_helo = @ComputerName
    If $s_LoginString = "" Then $s_LoginString = "HELO"
    If $s_AuthUser = "" Then $s_AuthUser = 0
    If TCPStartup() = 0 Then
        SetError(2)
        Return 0
    EndIf
    StringRegExp($s_SmtpServer, "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
    If @extended Then
        $s_IPAddress = $s_SmtpServer
    Else
        $s_IPAddress = TCPNameToIP($s_SmtpServer)
    EndIf
    If $s_IPAddress = "" Then
        TCPShutdown()
        SetError(3)
        Return 0
    EndIf
    $v_Socket = TCPConnect($s_IPAddress, 25)
    If $v_Socket = -1 Then
        TCPShutdown()
        SetError(4)
        Return (0)
    EndIf
    
;Login with Username And Password Commands
    $s_Auth[0] = "AUTH LOGIN" & @CRLF
    $s_AuthReplyCode[0] = "334"
    $s_Auth[1] = $s_username & @CRLF
    $s_AuthReplyCode[1] = "334"
    $s_Auth[2] = $s_password & @CRLF
    $s_AuthReplyCode[2] = "235"
    
;Send Mail Headers
    $s_Send[0] = "MAIL FROM: <" & $s_FromAddress & ">" & @CRLF
    $s_SendReplyCode[0] = "250"
    $s_Send[1] = "RCPT TO: <" & $s_ToAddress & ">" & @CRLF
    $s_SendReplyCode[1] = "250"
    $s_Send[2] = "DATA" & @CRLF
    $s_SendReplyCode[2] = "354"
    
    $s_Send[3] =    "From:" & $s_FromName & "<" & $s_FromAddress & ">" & @CRLF & _
            "To:" & "<" & $s_ToAddress & ">" & @CRLF & _
            "Subject:" & $s_Subject & @CRLF & _
            "Mime-Version: 1.0" & @CRLF & _
            "Content-Type: text/plain; charset=US-ASCII" & @CRLF & _
            @CRLF
    $s_SendReplyCode[3] = ""
    
;Close Email and Session
    $s_End[0] = @CRLF & "." & @CRLF
    $s_EndReplyCode[0] = "250"
    $s_End[1] = "QUIT" & @CRLF
    $s_EndReplyCode[1] = "221"
    
    
;Start Connection with SMTP Host
    Dim $s_Receive
    $s_Receive = _GetLastReplyMsg($v_Socket, "220", $s_Trace)
    _SendTcp($v_Socket, $s_LoginString & " " & $s_helo & @CRLF, $s_Trace)
    $s_Receive = _GetLastReplyMsg($v_Socket, "250", $s_Trace)
    If @error Then
        _SendTcp($v_Socket, "EHLO" & " " & $s_helo & @CRLF, $s_Trace)
        $s_Receive = _GetLastReplyMsg($v_Socket, "250", $s_Trace)
        If @error Then
            _SendTcp($v_Socket, "HELO" & " " & $s_helo & @CRLF, $s_Trace)
            $s_Receive = _GetLastReplyMsg($v_Socket, "250", $s_Trace)
            If @error Then
                MsgBox(0, "", "Can Not Connect To Server" & @CRLF & $s_Receive)
                Return 0
            EndIf
        EndIf
    EndIf
    
;Send Login
    If $s_AuthUser Then
        For $ii = 0 To 2 Step + 1
            _SendTcp($v_Socket, $s_Auth[$ii], $s_Trace)
            $s_Receive = _GetLastReplyMsg($v_Socket, $s_AuthReplyCode[$ii], $s_Trace)
            If @error Then
                MsgBox(0, "", $s_Receive & @CRLF & @CRLF & $s_AuthReplyCode[$ii] & @CRLF & @CRLF & $s_Auth[$ii])
            EndIf
        Next
    EndIf
    
;Send To, From, Ect...
    For $ii = 0 To 2 Step + 1
        _SendTcp($v_Socket, $s_Send[$ii], $s_Trace)
        $s_Receive = _GetLastReplyMsg($v_Socket, $s_SendReplyCode[$ii], $s_Trace)
        If @error Then
            MsgBox(0, "", $s_Receive & @CRLF & @CRLF & $s_SendReplyCode[$ii] & @CRLF & @CRLF & $s_Send[$ii])
        EndIf
    Next
    _SendTcp($v_Socket, $s_Send[3], $s_Trace);send last one, dont need to recieve anything
    
;Send Body
    For $i_Count = 0 To UBound($as_Body) - 1
        If StringLeft($as_Body[$i_Count], 1) = "." Then $as_Body[$i_Count] = "." & $as_Body[$i_Count]
        _SendTcp($v_Socket, $as_Body[$i_Count] & @CRLF, $s_Trace)
    Next
    
;Close Message and Connection
    For $ii = 0 To 1 Step + 1
        _SendTcp($v_Socket, $s_End[$ii], $s_Trace)
        $s_Receive = _GetLastReplyMsg($v_Socket, $s_EndReplyCode[$ii], $s_Trace)
        If @error Then
            MsgBox(0, "", $s_Receive & @CRLF & @CRLF & $s_EndReplyCode[$ii] & @CRLF & @CRLF & $s_End[$ii])
        EndIf
    Next
    
    TCPCloseSocket($v_Socket)
    TCPShutdown()
    Return 1
EndFunc ;==>_INetSmtpMail

;Waits for Reply

Func _GetLastReplyMsg($v_Socket, $s_ReplyCode, $s_Trace)
    Dim $s_Receive
    For $iii = 0 To 20 Step + 1
        $s_Receive = TCPRecv($v_Socket, 1000)
        If $s_Receive = "" Then
        Else
            If $s_Trace Then
                _SmtpTrace("<Recv>  " & $s_Receive)
            EndIf
            If StringInStr($s_Receive, $s_ReplyCode) Then
                Return $s_Receive
            EndIf
        EndIf
        Sleep(200);will wait a max of 4 seconds for reply
    Next
    SetError(1)
    Return $s_Receive
EndFunc ;==>_GetLastReplyMsg

Func _SmtpTrace($str, $timeout = 0)
    Local $W_TITLE = "SMTP trace"
    Local $g_smtptrace = ControlGetText($W_TITLE, "", "Static1")
    $str = StringLeft(StringReplace($str, @CRLF, ""), 70)
    $g_smtptrace &= @HOUR & ":" & @MIN & ":" & @SEC & " " & $str & @LF
    If WinExists($W_TITLE) Then
        ControlSetText($W_TITLE, "", "Static1", $g_smtptrace)
    Else
        SplashTextOn($W_TITLE, $g_smtptrace, 400, 500, 500, 100, 4 + 16, "", 8)
    EndIf
    If $timeout Then Sleep($timeout * 1000)
EndFunc ;==>_SmtpTrace

Func _SendTcp($v_Socket, $s_Command, $s_Trace)
    TCPSend($v_Socket, $s_Command)
    If $s_Trace Then
        _SmtpTrace("<Send>  " & $s_Command)
    EndIf
EndFunc ;==>_SendTcp




;EXAMPLE CODE
$s_SmtpServer = "smtp.com"
$s_FromName = "Me"
$s_FromAddress = "dude@autoitscript.com"
$s_ToAddress = "spam@hotmail.com"
$s_Subject = "My Test UDF"
Dim $as_Body[2]
$as_Body[0] = "Testing the new email udf"
$as_Body[1] = "Second Line"
$s_username = InputBox("Username", "Username Must be base64")
$s_password = InputBox("Password", "Password Must be base64")
$s_Trace = 1 ;0 no trace window, 1 trace window displayed
$s_helo = @ComputerName
$s_LoginString = "EHLO"
$s_AuthUser = 1 ;0 no user/pass, 1 send user/pass

$Response = _INetSmtpMail($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject, $as_Body, $s_Trace, $s_helo, $s_LoginString, $s_AuthUser, $s_username, $s_password)
$err = @error
If $Response = 1 Then
    MsgBox(0, "Success!", "Mail sent")
Else
    MsgBox(0, "Error!", "Mail failed with error code " & $err)
EndIf

Please let me know if this is helpful, I have it working with my SMTP server thus I dont care for error checking, thats why its out. BUT if someone out there can use this let me know and Ill try to add it back in. Or if someone else wants to do that by all means please do!

If your looking for the original UDF, install the latest beta and odds are its in C:\Program Files\AutoIt3\beta\Include\Inet.au3 at the bottom of the file.

Edited by mikeytown2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...