Funciones suplementarias para la librería _pop3.au3

y programas personales para otros como tu, puede que te corrijan ;)
Responder
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Funciones suplementarias para la librería _pop3.au3

Mensaje por Chefito »

Bueno bueno.......siguiendo al mensaje de Jonny (http://www.emesn.com/autoitforum/viewto ... f=3&t=1464), he ampliado la librería de Luc HENNINOT <[email protected]> (_pop3.au3).
Le he añadido varias funciones para descargar las propiedades del mensaje, el cuerpo y otra función que te dice si el mensaje tiene o no archivos adjuntos. Todo esto sin necesidad de tener que descargar todo el mensaje. Vamos....que lo hace bastante rápido y apenas bloquea el script :smt002 .
También he añadido otra función que te descarga los archivos adjuntos y los graba en la ubicación dada por el usuario.
No están muy depuradas. Puede tener fallos. El tratamiento de errores no está muy probado.
Tampoco lo he probado con muchos mails. Puede que si se envían desde otros servidores o desde otros programas de envío de mensajes el texto sea diferente y falle. Espero que no :smt005 . Yo lo he probado con hotmail (webmail).

Por cierto....me han costado un poquito hacerlas ya que no tenía ni idea del protocolo pop :smt009 . Pero pronto se aprende :smt020 .

El código del archivo _pop3_ampliado.au3 es: EDITADO EL CÓDIGO DE _POP_AMPLIADO.AU3. MEJORADO Y CORREGIDO FALLOS

Código: Seleccionar todo

;-----------------------_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 <[email protected]>
;-----------------------------------------------------------
;~ 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>
#include <String.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, 128)
		If $ret <> "" Then
			Return $ret
		EndIf
		Sleep(10)
	WEnd
EndFunc   ;==>_WaitTcpResponse

;***********************************************************
;Funciones suplementarias de chefito ;)
;Menudo trabajazo que me han llevado las cabro..... jajajaja
;Estas funciones van junto a las de arriba, las de la librería _pop.au3
;***********************************************************

#cs *********************************************************************************
Función: _Pos3InfoMail($msg)
Descripción: Te da información del mensaje. Quien lo ha enviado, a quien, asunto del mail y fecha de envio.
Parámetros dados: Tiene 1. $msg: recibe el número del mensaje del que quieres la información.
Parámetros devueltos: Te devuelve un array con 4 elementos: 
						0 quien lo ha enviado.
						1 a quien lo ha enviado.
						3 asunto del mensaje.
						4 fecha de envio del mensaje.
			Si alguno de estos elementos falla, te devolvería 0.
			Si falla la función totalmente, devuelve -1. Mirar @error.
Autor: Chefito 18/02/2009
Otros: Como siempre es libre. Se agradecería que se nombrase al Autor si se utiliza ;)=.
		Y por supuesto, si se puede mejorar...adelante ;).
#ce *********************************************************************************

Func _Pop3InfoMail($msg)
	Local $ret
	If $pop3_IsAuth = 1 Then
		Local $ret
		
		$ret = TCPSend ($pop3_socket, "TOP " & $msg & " 0" & @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
		
		Local $TotalText=""
		Local $FromNoEncontrado=1,$ToNoEncontrado=1,$SubjectNoEncontrado=1
		Local $Origen, $Destino, $Asunto, $Fecha, $posIni, $posFin
		Local $DatosDevueltos[4]
		For $n=0 To 3
			$DatosDevueltos[$n]=0
		Next
		$ret=""
		While Not StringRegExp($ret, "\r\n\.\r\n")	;****
			$ret = $ret & _WaitTcpResponse()
			If @error Then
				SetError($pop3_error_no_TCP_response)
				Return -1
			EndIf
				If $FromNoEncontrado Then
					$posIni=StringInStr($ret,"From: ")
					If $posIni<>0 Then
						$posIni=$posIni+6
						$posFin=StringInStr($ret,@CRLF,0,1,$posIni)
						If $posFin<>0 Then
							$Origen=StringMid($ret,$posIni,$posFin-$posIni)
							$DatosDevueltos[0]=$Origen
							$FromNoEncontrado=0
						EndIf
					EndIf
				EndIf
				If $ToNoEncontrado Then
					$posIni=StringInStr($ret,"To: ")
					If $posIni<>0 Then
						$posIni=$posIni+5
						$posFin=StringInStr($ret,">" & @CRLF,0,1,$posIni)
						If $posFin<>0 Then
							$Destino=StringMid($ret,$posIni,$posFin-$posIni)
							$DatosDevueltos[1]=$Destino
							$ToNoEncontrado=0
						EndIf
					EndIf
				EndIf
				If $SubjectNoEncontrado Then
					$posIni=StringInStr($ret,"Subject: ")
					If $posIni<>0 Then
						$posIni=$posIni+9
						$posFin=StringInStr($ret,@CRLF,0,1,$posIni)
						If $posFin<>0 Then
							$Asunto=StringMid($ret,$posIni,$posFin-$posIni)
							$DatosDevueltos[2]=$Asunto
							$SubjectNoEncontrado=0
						EndIf
					EndIf
				EndIf
					$posIni=StringInStr($ret,"Date: ")
					If $posIni<>0 Then
						$posIni=$posIni+6
						$posFin=StringInStr($ret," +0100",0,1,$posIni)
						If $posFin<>0 Then
							$Fecha=StringMid($ret,$posIni,$posFin-$posIni)
							$DatosDevueltos[3]=$Fecha
							Return $DatosDevueltos
						EndIf
					EndIf
		WEnd	;********
		Return $DatosDevueltos
	Else
		SetError($pop3_error_no_auth)
		Return -1
	EndIf
EndFunc   ;==>

#cs *********************************************************************************
Función: _Pop3CuerpoMail($msg,$MyPopServer, $MyLogin, $MyPasswd, $TextPlanoHtml=0, $modo=0)
Descripción: Te devuelve el texto plano o en HTML del mensaje.
Parámetros dados: Tiene 6.
			$msg (obligatorio): recibe el número del mensaje del que quieres el texto.
			$MyPopServer (obligatorio): recibe el servidor pop.
			$MyLogin (obligatorio): recibe el login del correo.
			$MyPasswd (obligatorio): recibe la clave del correo.
			$TextoPlanoHtml (opcional): Si es 0 (por defecto), devuelve el mensaje en texto plano. Si 
			es distinto de 0 lo devuelve en código HTML.
			$modo (opcional): recibe el modo de codificación del texto del mensaje. Si es 0 (por defecto)
			te devuelve el texto tal cual. Si es distinto de 0, codifica caracteres especiales.
Parámetros devueltos: Te devuelve el texto del mensaje 
			Si falla la función, devuelve -1. Mirar @error.
Autor: Chefito 18/02/2009
Otros: 	He tenido que introducir los 3 parámetros $MyPopServer, $MyLogin, $MyPasswd porque por lo visto
		se queda algo colgado el acceso al servidor pop a causa de cortar el mensaje antes de tiempo. Para
		evitar que esté esperando un tiempo una respuesta erronea, he tenido que desconectar y conectar la
		conexión con el servidor de nuevo. Si alguien encuentra una solución mejor que lo corrija y lo diga.
		
		Como siempre es libre. Se agradecería que se nombrase al Autor si se utiliza ;)=.
		Y por supuesto, si se puede mejorar...adelante ;).
#ce *********************************************************************************

Func _Pop3CuerpoMail($msg,$MyPopServer, $MyLogin, $MyPasswd, $TextPlanoHtml=0, $modo=0)
	Local $ret
	If $pop3_IsAuth = 1 Then
		Local $ModoMsg, $longModoMsg
		; Send Retr
		If $TextPlanoHtml=0 Then 
			$ModoMsg="Content-Type: Text/plain;"
			$longModoMsg=27
		Else 
			$ModoMsg="Content-Type: Text/html;"
			$longModoMsg=26
		EndIf
		$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
		
		Local $TotalText="",$codigo2, $textoplano, $posIni=0, $posFin=0
		Local $encontrarTexto=0,$encontrarClave=1,$encontrarHTML=0,$EncontrarCodigo2=0
		$ret=""
		;While Not StringRegExp($ret, "\r\n\.\r\n")	;****
		While StringInStr($ret, "--" & $codigo2 & "--" & @CRLF)=0	;****
			$ret = $ret & _WaitTcpResponse()
			If @error Then
				;*********** Bloque de desconexión/conexión para que no se quede bloqueado el script ********
				$desconectar=_pop3Disconnect()
				If $desconectar<>-1 Then
					$conectar=_pop3Connect($MyPopServer, $MyLogin, $MyPasswd)
					If $conectar=-1 Then Return -1
				Else
					Return -1
				EndIf
				;*********** Fin bloque de desconexión/conexión para que no se quede bloqueado el script ********
				SetError($pop3_error_no_TCP_response)
				Return -1
			EndIf
			
				If $EncontrarCodigo2=0 Then
					$codigo2=_Codigo2($ret)
					If $codigo2<>-1 Then $EncontrarCodigo2=1
				EndIf

				If $posIni=0 Then
					$posIni=StringInStr($ret,$codigo2 & @CRLF & $ModoMsg)
					If $posIni<>0 Then 
						$posIni=$posIni+StringLen($codigo2)+$longModoMsg
					EndIf
				EndIf
					$posFin=StringInStr($ret,$Codigo2,0,1,$posIni)
					If $posFin<>0 Then
						$posIni=StringInStr($ret,"Content-Transfer-Encoding: quoted-printable",0,1,$posIni)+47
						$TextoPlano=StringMid($ret,$posIni,$posFin-$posIni-6)
						
						;*********** Bloque de desconexión/conexión para que no se quede bloqueado el script ********
						$desconectar=_pop3Disconnect()
						If $desconectar<>-1 Then
							$conectar=_pop3Connect($MyPopServer, $MyLogin, $MyPasswd)
							If $conectar=-1 Then Return -1
						Else
							Return -1
						EndIf
						;*********** Fin bloque de desconexión/conexión para que no se quede bloqueado el script ********


						If $modo=0 Then
							Return $TextoPlano
						Else
							$TextoPlano=ConvertirTextoUnicode($TextoPlano)
							Return $TextoPlano
						EndIf
					EndIf
		WEnd	
		;Return -1
	Else
		SetError($pop3_error_no_auth)
		Return -1
	EndIf
EndFunc  

#cs *********************************************************************************
Función: _Pop3DescargarFicheros($msg, $path=@ScriptDir)
Descripción: Te descarga los ficheros adjuntos del mensaje y los guarda.
Parámetros dados: Tiene 2.
			$msg (obligatorio): recibe el número del mensaje del que quieres el texto (0bligatorio).
			$path (opcional): recibe el camino (path) donde se van a guardar los ficheros descargados.
			Si no le pasas nada, por defecto los guarda en la ubicación del script.
Parámetros devueltos: Te devuelve una matriz (array) donde el elemento 0 tiene almacenados el número de
			archivos bajado, y todos los elementos contienen el path más el nombre del archivo. Si falla
			algún archivo, el elemento referente a este archivo contiene -1.
			Si falla la función totalmente, devuelve -1. Mirar @error.
Autor: Chefito 18/02/2009
Otros: Como siempre es libre. Se agradecería que se nombrase al Autor si se utiliza ;)=.
		Y por supuesto, si se puede mejorar...adelante ;).
#ce *********************************************************************************

Func _Pop3DescargarFicheros($msg, $path=@ScriptDir)
	Local $ret
	;***************** Bloque donde asigno los valores de las claves de comienzo y final de las distintas partes del mensaje ****
	$ret=_Pop3Retr($msg)
	If @error Then 
		SetError(@error)
		Return -1
	EndIf
	$finCodigo2=_Codigo2($ret) & "--"
	$Codigo1=_Codigo1($ret)
	$IniCodigo1=@CRLF & @CRLF & "--" & $Codigo1
	$IniCodigos=$fincodigo2 & $iniCodigo1 & @CRLF
	
	$finCodigo1=$IniCodigo1 & "--"
	;***************** Fin de bloque de asignación de claves *****************************************************************
	
	$iniFicheros=StringInStr($ret,$IniCodigos)	;busca si hay ficheros en el mensaje.
	If $iniFicheros<>0 Then
		$longIniCodigos=StringLen($IniCodigos)
		$ret=StringMid($ret,$iniFicheros + $longIniCodigos,StringLen($ret)-$longIniCodigos-$iniFicheros)
		;************ Quita la clave final del mail ******************************************************************
		;$ret=StringReplace($ret,$finCodigo1)	;también funciona con esta linea. Esta linea sustituiría a las 3 siguientes.
		$posFinClave1=StringInStr($ret,$finCodigo1)
		$longFicheros=StringLen($ret)
		$ret=StringLeft($ret,$longFicheros-($longFicheros-$posFinClave1))
		;************* Fin de bloque que quita la clave final del mail ************************************************
		$ret=StringSplit($ret,$IniCodigo1,1)
		For $n=1 To $ret[0]		;repito hasta guardar todos los ficheros.
			;************* Busca y almacena el nombre del fichero ********************************
			$posIniName=StringInStr($ret[$n],'filename="')+10
			$posFinName=StringInStr($ret[$n],'"',0,1,$posIniName)
			$nameFichero=StringMid($ret[$n],$posIniName,$posFinName-$posIniName)
			;************* Fin de bloque de nombre del fichero ***********************************
			
			$posIniFichero=$posFinName+5	;Posición inicial del fichero. Adelanta 5 caracteres (2 @crlf).
													
			$ret[$n]=StringMid($ret[$n],$posIniFichero,StringLen($ret[$n]))		;almaceno el código del fichero en Base 64.
			$FicheroBinario=_Base64Decode($ret[$n])		;lo descodifico convirtiendose en código binario.
			$PathFichero=$path & "\" & $nameFichero		;path donde se va a guardar el fichero más el nombre de éste.
			
			;***************** Bloque para crear y guardar el fichero descargardo **************************
			$Fichero=FileOpen($PathFichero,2)
			If $Fichero=-1 Then 
				$ret[$n]=-1
			Else
				$FicheroEscrito=FileWrite($Fichero,$FicheroBinario)
				If $FicheroEscrito=0 Then 
					SetError(22)	;si no puede escribir en el fichero, @error=22
					Return -1
				EndIf
				FileClose($Fichero)
				$ret[$n]=$PathFichero
			EndIf
			;***************** Fin de bloque para crear y guardar el fichero descargado *********************
		Next
		Return $ret
	Else			;Si no hay ficheros en el mensaje, la función devuelve 0
		SetError(21)	;@error=21 indica que no hay ficheros en este mensaje.
		Return -1

	EndIf
EndFunc  

#cs *********************************************************************************
Función: _Pop3ContieneAdjuntos($msg)
Descripción: Te dice si el mensaje contione o no archivos adjuntos.
Parámetros dados: Tiene 1.
			$msg (obligatorio): recibe el número del mensaje del que quieres el texto (0bligatorio).
Parámetros devueltos: Si contiene algún archivo adjunto, la función devuelve 1, si no, devuelve -1 (@error=21)
			Si falla la función totalmente, devuelve -1. Mirar @error.
Autor: Chefito 18/02/2009
Otros: Como siempre es libre. Se agradecería que se nombrase al Autor si se utiliza ;)=.
		Y por supuesto, si se puede mejorar...adelante ;).
#ce *********************************************************************************

Func _Pop3ContieneAdjuntos($msg)
	Local $ret
	If $pop3_IsAuth = 1 Then
		; Send Retr
		$ret = TCPSend ($pop3_socket, "TOP " & $msg & " 0" & @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
		
		Local $TotalText="", $codigo1
		$ret=""
		While Not StringRegExp($ret, "\r\n\.\r\n")	;****
			$ret = $ret & _WaitTcpResponse()
			If @error Then
				SetError($pop3_error_no_TCP_response)
				Return -1
			EndIf
			$codigo1=StringInStr($ret,"Content-Type: multipart/mixed;")
			If $codigo1<>0 Then Return 1
		WEnd	
		SetError(21)	;@error=21 indica que no hay ficheros en este mensaje.
		Return -1
	Else
		SetError($pop3_error_no_auth)
		Return -1
	EndIf
EndFunc  

#cs *********************************************************************************
Funciones complementarias: Son funciones necesarias para las de arriba.
Descripción: ConvertirTextoUnicode($Texto) -> convierte texto del mensaje Unicode.
			_Codigo1($Texto) -> Devuelve el primer código único del mensaje.
								Suele indicar el comienzo y final de los archivos adjuntos. 
			_Codigo2($Texto) -> Devuelve el segundo código único del mensaje.
								Suele indicar el comienzo y final del cuerpo del mensaje. 
Autor: Chefito 18/02/2009
Otros: Como siempre es libre. Se agradecería que se nombrase al Autor si se utiliza ;)=.
		Y por supuesto, si se puede mejorar...adelante ;).
#ce *********************************************************************************

Func ConvertirTextoUnicode($Texto)
	Local $posIgual=0, $caracter
	While 1
		$posIgual=StringInStr($texto,"=",0,1,$posIgual+1)
		If $posIgual<>0 Then
			$caracter=StringMid($Texto,$posIgual+1,2)
			If StringIsXDigit($caracter) Then
				$texto=StringReplace($texto,"=" & $caracter,ChrW("0x" & $caracter),1)
			EndIf
		Else
			$texto=StringReplace($texto,"=" & @CRLF,"")
			$texto=StringLeft($texto,StringLen($texto)-1)
			Return $texto
		EndIf
		If @error Then 
			Return -1
		EndIf
	WEnd
EndFunc


Func _Codigo1($texto)
	Local $Codigo, $posIni, $posFin
	$posIni=StringInStr($texto,"Content-Type: multipart/mixed;" & @CRLF & Chr(9) & 'boundary="')
	If $posIni<>0 Then
		$posIni=$posIni+43
		$posFin=StringInStr($texto,'"',0,1,$posIni)
		If $posFin<>0 Then
			$Codigo=StringMid($texto,$posIni,$posFin-$posIni)
			Return $Codigo
		EndIf
	Else
		Return -1
	EndIf
EndFunc

Func _Codigo2($texto)
	Local $Codigo, $posIni, $posFin
	$posIni=StringInStr($texto,"Content-Type: multipart/alternative;" & @CRLF & Chr(9) & 'boundary="')
	If $posIni<>0 Then
		$posIni=$posIni+49
		$posFin=StringInStr($texto,'"',0,1,$posIni)
		If $posFin<>0 Then
			$Codigo=StringMid($texto,$posIni,$posFin-$posIni)
			Return $Codigo
		EndIf
	Else
		Return -1
	EndIf
EndFunc


;*************************************************************************************
;Fin de funciones de Chefito :/
;*************************************************************************************

#cs Función _Base64Decode($Data)
;Descodifica un mensaje en Base 64. En mi caso la utilizo para descodificar los ficheros adjuntos del mensaje a binario.
;La conseguí en el foro ingles http://www.autoitscript.com/forum/index.php?showtopic=76976&st=0, de una UDF.
;Es una UDF con muchos métodos de codificación y descodificación. Rápida y poco tamaño. Muy recomendable tenerla.
#ce SU AUTOR ES Ward.

Func _Base64Decode($Data)
	Local $Opcode = "0xC81000005356578365F800E8500000003EFFFFFF3F3435363738393A3B3C3DFFFFFF00FFFFFF000102030405060708090A0B0C0D0E0F10111213141516171819FFFFFFFFFFFF1A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132338F45F08B7D0C8B5D0831D2E9910000008365FC00837DFC047D548A034384C0750383EA033C3D75094A803B3D75014AB00084C0751A837DFC047D0D8B75FCC64435F400FF45FCEBED6A018F45F8EB1F3C2B72193C7A77150FB6F083EE2B0375F08A068B75FC884435F4FF45FCEBA68D75F4668B06C0E002C0EC0408E08807668B4601C0E004C0EC0208E08847018A4602C0E00624C00A46038847028D7F038D5203837DF8000F8465FFFFFF89D05F5E5BC9C21000"
	
	Local $CodeBuffer = DllStructCreate("byte[" & BinaryLen($Opcode) & "]")
	DllStructSetData($CodeBuffer, 1, $Opcode)

	Local $Ouput = DllStructCreate("byte[" & BinaryLen($Data) & "]")
	Local $Ret = DllCall("user32.dll", "int", "CallWindowProc", "ptr", DllStructGetPtr($CodeBuffer), _
													"str", $Data, _
													"ptr", DllStructGetPtr($Ouput), _
													"int", 0, _
													"int", 0)

	Return BinaryMid(DllStructGetData($Ouput, 1), 1, $Ret[0])
EndFunc
El código de un ejemplo:

Código: Seleccionar todo

#include <array.au3>
#include <_pop3_ampliado.au3>

ConsoleWrite(@AutoItVersion & @CRLF)
;~ See _pop3.au3 for a complete description of the pop3 functions
;~ Requires AU3 beta version 3.1.1.110 or newer.

Global $MyPopServer = "mail.ivermedia.com"
Global $MyLogin = "[email protected]"
Global $MyPasswd = "cvkjsp0lvk9"

_pop3Connect($MyPopServer, $MyLogin, $MyPasswd)
If @error Then
	MsgBox(0, "Error", "Unable to connect to " & $MyPopServer & @CR & @error)
	Exit
Else
	ConsoleWrite("Connected to server pop3 " & $MyPopServer & @CR)
EndIf

;Local $stat = _Pop3Stat()
;If Not @error Then
;	_ArrayDisplay($stat, "Result of STAT COMMAND")
;Else
;	ConsoleWrite("Stat commande failed" & @CR)
;EndIf

;~ Local $list = _Pop3List()
;~ If Not @error Then
;~ 	_ArrayDisplay($list, "")
;~ Else
;~ 	ConsoleWrite("List commande failed" & @CR)
;~ EndIf

;~ Local $noop = _Pop3Noop()
;~ If Not @error Then
;~ 	ConsoleWrite($noop & @CR)
;~ Else
;~ 	ConsoleWrite("List commande failed" & @CR)
;~ EndIf

;~ Local $uidl = _Pop3Uidl()
;~ If Not @error Then
;~ 	_ArrayDisplay($uidl, "")
;~ Else
;~ 	ConsoleWrite("Uidl commande failed" & @CR)
;~ EndIf
 
;~ Local $top = _Pop3Top(3, 0)
;~ If Not @error Then
;~ 	ConsoleWrite(StringStripCR($top) & @CR)
;~ Else
;~ 	ConsoleWrite("top commande failed" & @CR)
;~ EndIf
#cs
MsgBox(0,"","Se va a proceder a descargar todo el mensaje en la ventana inferior de mensajes del Scite")
 Local $retr = _Pop3Retr(2)
 If Not @error Then
 	ConsoleWrite(StringStripCR($retr) & @CR)
 Else
 	ConsoleWrite("Retr commande failed" & @CR)
 EndIf
#ce
;~ Local $dele = _Pop3Dele(1)
;~ If Not @error Then
;~ 	ConsoleWrite($dele & @CR)
;~ Else
;~ 	ConsoleWrite("Dele commande failed" & @CR)
;~ EndIf
;#cs
MsgBox(0,"","Se va a mostrar la información del mensaje número 2")
Local $info=_pop3infomail(2)
If $info<>-1 Then 
	MsgBox(0,"","De: " & $info[0] & @CR & "A: " & $info[1] & @CR & "Asunto: " & $info[2] & @CR & "Enviado con fecha: " & $info[3])
Else
	MsgBox(0,"Error","Error. No se ha podido descargar la información del mensaje")
EndIf
;#ce
;#cs
MsgBox(0,"","Se va a mostrar el cuerpo del mensaje número 2")

Local $cuerpo=_pop3cuerpomail(4,$MyPopServer, $MyLogin, $MyPasswd,0,1)
If $cuerpo<>-1 Then
	MsgBox(0,"Texto del mensaje",$cuerpo)
Else
	MsgBox(0,"Error","No se puede mostrar el texto del mensaje")
EndIf
;#ce
Local $numMail=3
Local $hayficheros=_pop3contieneadjuntos($numMail)
	If $hayficheros=1 Then
		MsgBox(0,"","El mensaje " & $numMail & " contiene ficheros adjuntos")
	Else
		If @error=21 Then
			MsgBox(0,"","El mensaje " & $numMail & " no contiene ficheros adjuntos")
		Else
			MsgBox(0,"Error","Ha habido algún error al acceder al mensaje")
		EndIf
	EndIf

;#cs
Local $numMail=4
MsgBox(0,"","Se va a descargar los archivos adjuntos del mensaje número " & $numMail)
Local $texto=""
Local $archivos=_Pop3DescargarFicheros($numMail)
Switch $archivos
	Case 0	
			MsgBox(0,"Error","No hay archivos adjuntos")
	Case not -1
		For $n=1 to $archivos[0]
			If $archivos[$n]<>-1 Then
				$texto=$texto & "Ha sido descargado y guardado el archivo en: " & $archivos[$n] & @CR
			Else
				$texto=$texto & "El archivo " & $archivos[$n] & " no ha podido ser guardado" & @CR
			EndIf
		Next
		MsgBox(0,"",$texto) 
	Case Else 
		MsgBox(0,"Error","No ha podido descargarse los archivos")

	
EndSwitch
;#ce
ConsoleWrite(_Pop3Quit() & @CR)
_pop3Disconnect()
Espero que os gusten.
Voy a subir las librerías originales. Estas son _pop3.au3, _pop3_ampliado.au3, base64.au3. También subo un ejemplo.

SUBIDO EL NUEVO ARCHIVO CON EL NUEVO CÓDIGO DE LA LIBRERÍA _POP_AMPLIADO.AU3

Las direcciones url de los archivos, se encuentran en las explicaciones de las funciones.
Espero que os guste.

Saludos :smt026 .
Adjuntos
_pop3_ampliado.rar
(11.16 KiB) Descargado 258 veces
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Funciones suplementarias para la librería _pop3.au3

Mensaje por Jonny »

Hola

Muy buena .. en cuanto pueda lo pruebo...
¿Dices que incluyes Base64?... ¿Para que se requiere?...
No se, yo aprendí algo de pop3, quizá no todo (seguro) pero en lso comandos que ví no se requería...

Por cierto,la función para conectar al servidor está sin modificar ¿Verdad?
Creo que siendo así, a esta librería le faltaría que esta función conectara también mediante apop (con la contraseña encriptada en md5)
Si no lo puede hacer alguien, en cuanto tenga un rato lo hago yo, pues tengo una función para conectar al servidor pop3 que soporta tanto conexión mediante contraseña plana como encriptada en md5, pero es completamente diferente a la función de esta librería.

Gracias Chefito por la actualización de la librería!

Salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Funciones suplementarias para la librería _pop3.au3

Mensaje por Chefito »

Mmmmm....he tenido que corregir bastantes fallos del código de mis funciones. En algunos casos entraba en bucles largos, no devolvía el texto, daba un error, etc :smt011 . Más o menos está corregido....aunque seguramente siga teniendo fallos :smt021 .
También he eliminado el trozo de código que separaba en lineas completas el texto devuelto. Cuando lo estaba programando al principio, si lo necesitaba. Pero cambié el rumbo del código y me he dado cuenta que ya no hace apenas falta....asi que lo he eliminado y así tiene que hacer menos cosas :smt002 .
Jonny escribió:¿Dices que incluyes Base64?... ¿Para que se requiere?...
Es una especie de codificado ¿ligero?. El código binario de los archivos los codigica con este método. Por eso los tengo que descodificar a binario de nuevo.
Jonny escribió:Por cierto,la función para conectar al servidor está sin modificar ¿Verdad?
No he tocado ninguna función de la librería original.
Lo único que he hecho es utilizar algo su código para hacer las mias.
Jonny escribió:Creo que siendo así, a esta librería le faltaría que esta función conectara también mediante apop (con la contraseña encriptada en md5)
Si no lo puede hacer alguien, en cuanto tenga un rato lo hago yo, pues tengo una función para conectar al servidor pop3 que soporta tanto conexión mediante contraseña plana como encriptada en md5, pero es completamente diferente a la función de esta librería.
Sí, falta eso.
Y la verdad....no tengo ganas de meterme en ese embrollo :smt005 . Pero vi cosas referente a este tema en el foro ingles.
Jonny escribió:Gracias Chefito por la actualización de la librería!
De nada. A mandar.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Funciones suplementarias para la librería _pop3.au3

Mensaje por Jonny »

hum, es cierto, que para los archivos adjuntos se necesita la codificación/decodificación Base64...

Bien, en cuanto que pueda hecho un vistazo a la función que hice y modifico un poquito la función que comenté de la libbrería, para ya dejarla del todo completa... (no es muy difícil), solo hay que hecharle ganas.
Lo más complicado es, la función para la codificación md5, que no encontré mucha cosa por el foro inglés, más que una función que no iba y una que si va, pero ... es más larga que un día sin pan :P.
En cualquier caso, solo habrá que incluirla.

¿Ya subiste pues, la librería corregida?

Salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Funciones suplementarias para la librería _pop3.au3

Mensaje por Chefito »

Mmmmm....no has mirado bien el código que puse (función base64). Mira la librería de Ward, http://www.autoitscript.com/forum/index ... 76976&st=0, ahí hay muchos métodos de codificación, entre ellos la función para MD5. Además, son muy rápidas.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Funciones suplementarias para la librería _pop3.au3

Mensaje por Jonny »

Hola

sí, sí, de ahí me descargué la función md5 que digo que no me funcionó.
Me pareció muy interesante ese paquete, precisamente por la cantidad de sistemas de encriptación que tiene, pero no se porqué, al implementarla en la función que hice para conectar mediante apop al servidor éste no reconocía la contraseña y daba login fallido.

Salu2!
Responder