;-----------------------_POP3.AU3---------------------------
;~ Basic functions for AU3 Scripts, based on the 1939 RFC.
;~ See http://www.ietf.org/rfc/rfc1939.txt
;~ Include version : 0.99 (March 2006, 9th).
;~ Requires AU3 beta version 3.1.1.110 or newer.
;~ Author : Luc HENNINOT <lhenninot@nordnet.fr>
;-----------------------------------------------------------
;~ Int _pop3Connect (server, login, passwd [, port]) ; Conects to the according pop3 server. Returns 0 for OK, -1 if error and sets @error. Server can be an IP address, or a full text name.
;~ String _Pop3Dele(msg_number) ; Delete msg n?msg_number. Returns the server response or -1 if error, and sets @error.
;~ Array _Pop3List([msg_number]) ; Returns an array with the msg number and its size (octets), -1 if error ans sets @error.
;~ String _Pop3Noop() ; Actually, does nothing. The most interesting command from RFC 1939 ;)
;~ String _Pop3Quit() ; Validates your actions (dele for example) and stops the connection as it should. Returns the server response, or -1 and sets @error.
;~ String _Pop3Retr(msg_number) ; Downloads the according message, or returns -1 and sets @error.
;~ Int _Pop3Rset() ; Withdraw changes, such as dele orders. Returns 0 for success, -1 for error and sets @error.
;~ Array _Pop3Stat() ; Sends the number of messages in the pop3 account (array[1]) and the size(array[2]) in octets, or -1 ans sets @error.
;~ Sting _Pop3Top(msg_number, lines) ; Retreives the mail headers, and the X first lines of the message. Or returns -1 and sets @error.
;~ Array _Pop3Uidl([msg_number]) ; Same as _Pop3List(), but with UIDL identifiers instead of message size.
;~ Subfunctions, used by the above ones --------------------
;~ Int _pop3Disconnect() ; Shuts down connection. Returns 0 for OK, -1 if error and sets @error. Use _Pop3Quit to exit !!
;~ Sting _Pop3WaitForOK() ; Returns the server response if it starts with "+OK", or -1 and sets @error.
;~ String _WaitTcpResponse() ; Returns the server response, or -1 and sets @error.
#include-once
#include <array.au3>
; -- _POP3 error codes, sent by SetError. Use @error to display it. --
Global Const $pop3_error_tcpconnect_failed = 1
Global Const $pop3_error_server_response_timeout = 2
Global Const $pop3_error_already_connected = 3
Global Const $pop3_error_not_connected = 4
Global Const $pop3_error_no_auth = 5
Global Const $pop3_error_tcprecv_timeout = 6
Global Const $pop3_error_user_refused = 7
Global Const $pop3_error_passwd_refused = 8
Global Const $pop3_error_no_OK_response = 9
Global Const $pop3_error_stat_badresponse = 10
Global Const $pop3_error_no_TCP_response = 11
Global Const $pop3_error_stat_refused = 12
Global Const $pop3_error_list_refused = 13
Global Const $pop3_error_rset_refused = 14
Global Const $pop3_error_retr_refused = 15
Global Const $pop3_error_quit_refused = 16
Global Const $pop3_error_dele_refused = 17
Global Const $pop3_error_top_refused = 18
Global Const $pop3_error_uidl_refused = 19
Global Const $pop3_error_noop_refused = 20; I love this one ;)
;-- _POP3 vars --
Global Const $POP3_OK = "^\+OK"; Regexp syntax
Global Const $POP3_ERR = "^-ERR"; Unused yet, may help later.
Global $pop3_IsConnected = 0
Global $pop3_IsAuth = 0
Global $pop3_socket
Global $pop3_server_response_timeout = 60000 ; 1 mn, modify it if needed
;-- _POP3 Funcs --
Func _pop3Connect($server, $login, $passwd, $port = 110)
Local $ret
If $pop3_IsConnected = 0 Then
Local $server2
TCPStartUp ()
; Basic name to IP conversion
If StringRegExp($server, "[a-zA-Z]") Then
$server2 = TCPNameToIP ($server)
Else
$server2 = $server
EndIf
$pop3_socket = TCPConnect ($server2, $port)
If @error Then
SetError($pop3_error_tcpconnect_failed)
Return -1
Else
$pop3_IsConnected = 1
EndIf
; We need a first OK from pop3 server
$ret = _Pop3WaitForOK()
If @error Then
SetError($pop3_error_no_OK_response)
Return -1
EndIf
; Send user
$ret = TCPSend ($pop3_socket, "USER " & $login & @CRLF)
If @error Then
SetError($pop3_error_user_refused)
Return -1
EndIf
$ret = _Pop3WaitForOK()
If @error Then
SetError($pop3_error_no_OK_response)
Return -1
EndIf
; Send passwd
$ret = TCPSend ($pop3_socket, "PASS " & $passwd & @CRLF)
If @error Then
SetError($pop3_error_passwd_refused)
Return -1
EndIf
$ret = _Pop3WaitForOK()
If @error Then
SetError($pop3_error_no_OK_response)
Return -1
EndIf
$pop3_IsAuth = 1
Return 0
Else
SetError($pop3_error_already_connected)
Return -1
EndIf
EndFunc ;==>_pop3Connect
Func _Pop3Stat()
If $pop3_IsAuth = 1 Then
Local $ret
Local $a_ret
; Send STAT
$ret = TCPSend ($pop3_socket, "STAT" & @CRLF)
If @error Then
SetError($pop3_error_stat_refused)
Return -1
EndIf
$ret = _Pop3WaitForOK()
If @error Then
SetError($pop3_error_no_OK_response)
Return -1
EndIf
$a_ret = StringSplit($ret, " ")
If IsArray($a_ret) Then
_ArrayDelete($a_ret, 1)
$a_ret[0] = $a_ret[0] - 1
Return $a_ret
Else
SetError($pop3_error_stat_badresponse)
Return -1
EndIf
EndIf
EndFunc ;==>_Pop3Stat
Func _Pop3Noop()
If $pop3_IsAuth = 1 Then
Local $ret
Local $a_ret
; Send NOOP
$ret = TCPSend ($pop3_socket, "NOOP" & @CRLF)
If @error Then
SetError($pop3_error_noop_refused)
Return -1
EndIf
$ret = _Pop3WaitForOK()
If @error Then
SetError($pop3_error_no_OK_response)
Return -1
EndIf
Return $ret
EndIf
EndFunc ;==>_Pop3Noop
Func _Pop3Rset()
If $pop3_IsAuth = 1 Then
Local $ret
; Send RSET
$ret = TCPSend ($pop3_socket, "RSET" & @CRLF)
If @error Then
SetError($pop3_error_rset_refused)
Return -1
EndIf
$ret = _Pop3WaitForOK()
If @error Then
SetError($pop3_error_no_OK_response)
Return -1
EndIf
Return 0
EndIf
EndFunc ;==>_Pop3Rset
Func _Pop3List($msg = -1)
If $pop3_IsAuth = 1 Then
Local $ret
Local $AddMsg = ""
If $msg <> - 1 Then
$AddMsg = " " & $msg
EndIf
; Send List
$ret = TCPSend ($pop3_socket, "LIST" & $AddMsg & @CRLF)
If @error Then
SetError($pop3_error_list_refused)
Return -1
EndIf
$ret = _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
While $msg = -1 And Not StringRegExp($ret, "\r\n\.\r\n")
$ret = $ret & _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
WEnd
; Stripping useless infos for complete listing
$ret = StringSplit(StringStripCR($ret), @LF)
If $msg = -1 Then
_ArrayDelete($ret, $ret[0])
_ArrayDelete($ret, $ret[0] - 1)
_ArrayDelete($ret, 1)
$ret[0] = $ret[0] - 3
Else
_ArrayDelete($ret, $ret[0])
$ret[0] = $ret[0] - 1
$ret[1] = StringReplace($ret[1], "+OK ", "")
EndIf
Return $ret
EndIf
EndFunc ;==>_Pop3List
Func _Pop3Uidl($msg = -1)
If $pop3_IsAuth = 1 Then
Local $ret
Local $AddMsg = ""
If $msg <> - 1 Then
$AddMsg = " " & $msg
EndIf
; Send List
$ret = TCPSend ($pop3_socket, "UIDL" & $AddMsg & @CRLF)
If @error Then
SetError($pop3_error_uidl_refused)
Return -1
EndIf
$ret = _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
While $msg = -1 And Not StringRegExp($ret, "\r\n\.\r\n")
$ret = $ret & _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
WEnd
; Stripping useless infos for complete listing
$ret = StringSplit(StringStripCR($ret), @LF)
If $msg = -1 Then
_ArrayDelete($ret, $ret[0])
_ArrayDelete($ret, $ret[0] - 1)
_ArrayDelete($ret, 1)
$ret[0] = $ret[0] - 3
Else
_ArrayDelete($ret, $ret[0])
$ret[0] = $ret[0] - 1
$ret[1] = StringReplace($ret[1], "+OK ", "")
EndIf
Return $ret
EndIf
EndFunc ;==>_Pop3Uidl
Func _Pop3Retr($msg)
If $pop3_IsAuth = 1 Then
Local $ret
; Send Retr
$ret = TCPSend ($pop3_socket, "RETR " & $msg & @CRLF)
If @error Then
SetError($pop3_error_retr_refused)
Return -1
EndIf
$ret = _Pop3WaitForOK()
If @error Then
SetError($pop3_error_no_OK_response)
Return -1
EndIf
$ret = _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
; Downloading until final dot and cariage return.
While Not StringRegExp($ret, "\r\n\.\r\n")
$ret = $ret & _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
WEnd
Return $ret
Else
SetError($pop3_error_no_auth)
Return -1
EndIf
EndFunc ;==>_Pop3Retr
Func _Pop3Top($msg, $nb)
If $pop3_IsAuth = 1 Then
Local $ret
; Send Top
$ret = TCPSend ($pop3_socket, "TOP " & $msg & " " & $nb & @CRLF)
If @error Then
SetError($pop3_error_top_refused)
Return -1
EndIf
$ret = _Pop3WaitForOK()
If @error Then
SetError($pop3_error_no_OK_response)
Return -1
EndIf
$ret = _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
; Downloading until final dot and cariage return.
While Not StringRegExp($ret, "\r\n\.\r\n")
$ret = $ret & _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
WEnd
Return $ret
Else
SetError($pop3_error_no_auth)
Return -1
EndIf
EndFunc ;==>_Pop3Top
Func _Pop3Quit()
If $pop3_IsAuth = 1 Then
$ret = TCPSend ($pop3_socket, "QUIT" & @CRLF)
If @error Then
SetError($pop3_error_quit_refused)
Return -1
EndIf
$ret = _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
Return $ret
Else
SetError($pop3_error_no_auth)
Return -1
EndIf
EndFunc ;==>_Pop3Quit
Func _Pop3Dele($msg)
If $pop3_IsAuth = 1 Then
$ret = TCPSend ($pop3_socket, "DELE " & $msg & @CRLF)
If @error Then
SetError($pop3_error_dele_refused)
Return -1
EndIf
$ret = _WaitTcpResponse()
If @error Then
SetError($pop3_error_no_TCP_response)
Return -1
EndIf
Return $ret
Else
SetError($pop3_error_no_auth)
Return -1
EndIf
EndFunc ;==>_Pop3Dele
Func _pop3Disconnect()
If $pop3_IsConnected <> 0 Then
TCPCloseSocket ($pop3_socket)
TCPShutDown ()
$pop3_IsConnected = 0
Return 0
Else
SetError($pop3_error_not_connected)
Return -1
EndIf
EndFunc ;==>_pop3Disconnect
Func _Pop3WaitForOK()
; Wait for server response.
Local $ret
Local $T = TimerInit()
While 1
If TimerDiff($T) > $pop3_server_response_timeout Then
SetError($pop3_error_server_response_timeout)
Return -1
EndIf
$ret = _WaitTcpResponse()
If Not @error And StringRegExp($ret, $POP3_OK) Then
Return $ret
EndIf
Sleep(10)
WEnd
SetError($pop3_error_no_OK_response)
Return -1
EndFunc ;==>_Pop3WaitForOK
Func _WaitTcpResponse($timeout = 30000)
;Timeout to 30 s, should be enough in most cases. Overwright it if needed.
Local $ret
Local $T = TimerInit()
While 1
If TimerDiff($T) > $timeout Then
SetError($pop3_error_tcprecv_timeout)
Return -1
EndIf
$ret = TCPRecv ($pop3_socket, 512)
If $ret <> "" Then
Return $ret
EndIf
Sleep(10)
WEnd
EndFunc ;==>_WaitTcpResponse |