Что нового

[Сеть, интернет] Дополнение к UDF _pop3.au3

erlik

Продвинутый
Сообщения
317
Репутация
84
Недавно ковырялся с UDF _pop3.au3 и так как в ней есть только функционал получения сырых данных, с которыми дальше нужно что-то делать, решил это что-то воплотить в несколько более-менее удобных функций.

_Pop3GetContentHeaderByName - получает содержимое служебного заголовка после двоеточия
_Pop3HeaderDecode - декодирует (в случае необходимости) текст заголовка
_Pop3GetTextMessage - получает (и пытается декодировать) содержимое письма

На данный момент контент заголовков декодируется правильно почти во всех случаях (с исключениями нужно еще поразбираться - у меня на 70 писем два таких случая - неправильная кирилица получается). Что касается содержимого письма - то здесь все гораздо сложнее. Декодирование из base64 требует, чтобы строка состояла исключительно из валидного набора символов, чего весьма трудно добиться. Среди доп. функций есть те, которые стараются максимально очистить контент от html и прочего кода, но это не всегда помогает. Нормально декодируются небольшие письма состоящие из одной части и простого текста.
Состоящие же из несколько частей (у каждой свой набор заголовков) могут иметь разные варианты кодировки , много лишнего кода и поэтому трудно поддаются очистке и перекодированию. Над этим нужно еще поработать.

Функции, дополняющие UDF _pop3.au3:
Код:
#include <array.au3>
#include <_pop3.au3>
#include <Encoding.au3>
;#include <WinAPI.au3>

;===================================================================================
; Функции, дополняющие UDF _pop3.au3
;===================================================================================
; Получает содержимое заголовка (после двоеточия) по его имени.
; Для получения email нужно передать не RawData (сырой текст), а контент поля FROM и строку 'email'
;===================================================================================

Func _Pop3GetContentHeaderByName($sRawData, $sHeader)
	Local $aData, $sContent = ''

	Switch $sHeader
		; получим только email из строки from
		Case 'email'
			$aData = StringRegExp($sRawData, '<?([A-Za-z0-9._-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})>?', 1)
			If IsArray($aData) Then $sContent = $aData[0]

			; получим содержимое заголовка после двоеточия из raw данных
		Case Else
			$aData = StringRegExp($sRawData, '(?m)^' & $sHeader & ':\s*(.+)$', 1)
			If IsArray($aData) Then
				$sContent = StringStripCR($aData[0]) ; удаляем перенос строки
			EndIf
	EndSwitch
	Return $sContent
EndFunc   ;==>_Pop3GetContentHeaderByName


;===================================================================================
; перекодровка текста заголовков
;===================================================================================

Func _Pop3HeaderDecode($Data)
	Local $IsCyrillic
	$IsCyrillic = _Encoding_GetCyrillicANSIEncoding($Data)
	If $IsCyrillic Then Return _Encoding_CyrillicTo1251($Data)

	Local $sEndPart = ' ' ; переменная для хвостовой части строки FROM не закодированная Base64 - как правило это email в тегах <>

	; извлекаем email заключенный в теги <> для его возврата в строку после перекодировки первой части строки
	$aData = StringRegExp($Data, '(<.+>)', 1)
	If IsArray($aData) Then
		$sEndPart &= $aData[0]
	EndIf

	Select
		Case _IsQuotedPrintableSrtring($Data)
			$Data = __CleanHeaders(_Encoding_CyrillicTo1251(_Encoding_QuotedPrintableToANSI($Data)))

		Case _IsBase64String($Data)
			; очищаем строку от лишних сигнатур и хвостовых частей не закодированных в Base64
			$Data = __CleanHeaders($Data, True)
			$Data = _Encoding_CyrillicTo1251(_Encoding_Base64Decode($Data))

		Case Else
			$sEndPart = ''

	EndSelect

	Return $Data & $sEndPart
EndFunc   ;==>_Pop3HeaderDecode

;===================================================================================
; Очистка строки от сигнатуры кодировки и сепараторов в строках с base64 и quoted-printable кодировкой
;===================================================================================

Func __CleanHeaders($sContent, $StripWS = False)
	If StringRegExp($sContent, '=(.+)=') Then
		Local $sPattern = '(?i)(utf-8\?(B|Q)\?|KOI8-R\?(B|Q)\?|windows-1251\?(B|Q)\?|([=?])|(<.+>))'
		$sContent = StringRegExpReplace($sContent, $sPattern, '') ; удаляем сигнатуру кодировки, знаки = и ?, а также незакодированые символы email
		If $StripWS Then $sContent = StringStripWS($sContent, 8) ; удаляем все пробелы
	EndIf
	Return $sContent
EndFunc   ;==>__CleanHeaders

;===================================================================================
; Очистка текста письма от html и прочего кода, а также пустых строк - нужна доработка
;===================================================================================
Func __CleanMessage($sTextMessage)
	$sTextMessage = StringRegExpReplace($sTextMessage, '(
)', @CRLF) ; заменяем html теги перевода строк на символы перевода строк
	$sTextMessage = StringRegExpReplace($sTextMessage, '=\r\n', ' ') ; убираем лишние переводы строк после знака =
	$sTextMessage = StringRegExpReplace($sTextMessage, '(?s)(<.+?>|\*?\s*{.+}| )', '') ; убираем html и CSS код
	$sTextMessage = StringRegExpReplace($sTextMessage, '(\r\n|\r|\n){2,}', '\1') ; удаляем пустые строки
	$sTextMessage = StringStripWS($sTextMessage, 4) ; удаляем многократный повтор пробелов
	Return $sTextMessage
EndFunc   ;==>__CleanMessage

;===================================================================================
; проверка на тип строки quoted-printable
;===================================================================================
Func _IsQuotedPrintableSrtring($sString)
	If StringRegExp($sString, '(=[A-Z0-9]{2}=)') Then Return True
	Return False
EndFunc   ;==>_IsQuotedPrintableSrtring

;===================================================================================
; проверка на тип строки base64 - предназначена только для строк-заголовков полученных по протоколу Pop3
;===================================================================================
Func _IsBase64String($sString)
	If StringRegExp($sString, '[=?](?i:utf-8\?B\?|KOI8-R\?B\?|windows-1251\?B\?)([A-Za-z0-9/+]+)[=?]') Then Return True
	Return False
EndFunc   ;==>_IsBase64String


;===================================================================================
; Получает текст письма без заголовков по номеру письма
;===================================================================================
Func _Pop3GetTextMessage($iMsg, $Decode = True)
	Local $sTextMessage, $iIndex, $sBase64Decode
	$sTextMessage = _Pop3Retr($iMsg) ; получим raw текст письма со всеми заголовками
	$iIndex = StringInStr($sTextMessage, @CRLF & @CRLF) ; получим индекс первого вхождения разделителя заголовков и текста письма
	$sTextMessage = StringMid($sTextMessage, $iIndex, -1) ; получим только текст письма

	If $Decode Then
		Local $IsCyrillic = _Encoding_GetCyrillicANSIEncoding($sTextMessage)
		If $IsCyrillic Then Return _Encoding_CyrillicTo1251($sTextMessage)

		; Перед декодированием из Base64 строку нужно полностью очистить от не Base64 символов. Валидные символы [A-Za-z0-9/+]
		; иначе Base64Decode НЕ РАБОТАЕТ
		$sBase64Decode = _Encoding_Base64Decode($sTextMessage)
		If $sBase64Decode Then
			$sTextMessage = _Encoding_CyrillicTo1251($sBase64Decode)
		ElseIf _IsQuotedPrintableSrtring($sTextMessage) Then
			$sTextMessage = _Encoding_CyrillicTo1251(_Encoding_QuotedPrintableToANSI($sTextMessage))
		EndIf
	EndIf
	Return $sTextMessage
EndFunc   ;==>_Pop3GetTextMessage

Примеры использования:
Код:
; Examples
;_Pop3Example_All('pop3.server', 'email', 'password')
;_Pop3Example_MessageText('pop3.server', 'email', 'password', номер сообщения)
;ConsoleWrite(_Pop3Example_GetLastMessage('pop3.server', 'email', 'password'))

; Examples
;===================================================================================
; Пример считывает все письма с основными заголовками.
; На письмах с тяжелым контентом - фото, много html и т.д, считывание может зависнуть
; PS: Правильнее было бы считывать текст письма по байтам до завершающей точки, вместо полного возврата контента
; через _Pop3Retr(msg_number), но не знаю как это сделать
;===================================================================================
Func _Pop3Example_All($MyPopServer, $MyLogin, $MyPasswd)

	_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 $aPop3Stat = _Pop3Stat()
	If @error Then
		MsgBox(0, "Error", "Unable get statistics " & $MyPopServer & @CR & @error)
		ConsoleWrite(_Pop3Quit() & @CR)
		_pop3Disconnect()
		Exit
	Else
		;_ArrayDisplay($aPop3Stat)
		; возвращает массив, где
		; a[0]= 2  - число ячеек с данными
		; a[1]= общее число писем
		; a[2]= общий размер писем
		; выводим общее число сообщений и общий размер
		ConsoleWrite('TOTAL MSG:' & $aPop3Stat[1] & @CRLF)
		ConsoleWrite('SIZE MSG:'  & $aPop3Stat[2] & @CRLF)
	EndIf

	; выводим некоторые заголовки и текст письма
	For $iMsg = 1 To $aPop3Stat[1]

		; выводим текст некоторых заголовков
		;----------------------------------
		_Pop3Example_HeadersText($iMsg)
		;----------------------------------
		; выводим текст письма
		$sTextMessage = __CleanMessage(_Pop3GetTextMessage($iMsg))
		ConsoleWrite('====================================' & @CRLF)
		ConsoleWrite('MESSAGE:' & $iMsg & @CRLF)
		ConsoleWrite('====================================' & @CRLF)
		ConsoleWrite($sTextMessage)

	Next

	;----------------------------------
	; разъединяемся с сервером
	ConsoleWrite(_Pop3Quit() & @CR)
	_pop3Disconnect()

EndFunc   ;==>_Pop3Example

;===================================================================================
; выводит некоторые из заголовков письма
;===================================================================================
Func _Pop3Example_HeadersText($iMsg)
	Local $aPop3List, $sRawData, $aSize
	; возвращает массив, где
	; a[0]= 1 - номер ячейки с данными - всегда равно 1
	; a[1]= номер письма и размер письма, разделенные пробелом
	$aPop3List = _Pop3List($iMsg)
	If IsArray($aPop3List) Then
		;_ArrayDisplay($aPop3List)
		$aSize = StringSplit($aPop3List[1], ' ', 2)
	EndIf

	$sRawData = _Pop3Top($iMsg, 0) ; вернем заголовки

	Local $sContentType, $sContentEncoding, $sFrom, $sEmail, $sSubject, $sDate
	$sContentEncoding = _Pop3GetContentHeaderByName($sRawData, 'Content-Transfer-Encoding')
	$sContentType     = _Pop3GetContentHeaderByName($sRawData, 'Content-Type')
	$sDate            = _Pop3GetContentHeaderByName($sRawData, 'Date')
	$sFrom            = _Pop3GetContentHeaderByName($sRawData, 'From')
	$sFrom            = _Pop3HeaderDecode($sFrom) ; попытка перекодировать данные заголовков
	$sEmail           = _Pop3GetContentHeaderByName($sFrom, 'email') ; получим только email из заголовка from
	$sSubject         = _Pop3GetContentHeaderByName($sRawData, 'Subject')
	$sSubject         = _Pop3HeaderDecode($sSubject) ; попытка перекодировать данные заголовков

	ConsoleWrite( _
			'====================================' & @CRLF & _
			'№ MSG: '        & $iMsg & @CRLF & _
			'SIZE: '         & $aSize[1] & @CRLF & _
			'Content-Type: ' & $sContentType & @CRLF & _
			'Encoding: '     & $sContentEncoding & @CRLF & _
			'DATE: '         & $sDate & @CRLF & _
			'FROM (RAW): '   & $sFrom & @CRLF & _
			'EMAIL: '        & $sEmail & @CRLF & _
			'SUBJECT: '      & $sSubject & @CRLF _
			)

EndFunc   ;==>_Pop3Example_HeadersText

;===================================================================================
; выводим текст тела письма по его номеру - нумерация начинается с самого старого письма
; т.о чтобы узнать номер последнего пришедшего письма нужно обратиться к массиву, возвращаемому _Pop3Stat()
;===================================================================================
Func _Pop3Example_MessageText($MyPopServer, $MyLogin, $MyPasswd, $iMsg)
	_pop3Connect($MyPopServer, $MyLogin, $MyPasswd)

	;----------------------------------------------------------------------
	Local $sRawData = _Pop3Top($iMsg, 0) ; вернем заголовки
	ConsoleWrite(_Pop3GetContentHeaderByName($sRawData, 'Date') & @CRLF)
	ConsoleWrite(_Pop3HeaderDecode(_Pop3GetContentHeaderByName($sRawData, 'From')) & @CRLF)
	ConsoleWrite(_Pop3HeaderDecode(_Pop3GetContentHeaderByName($sRawData, 'Subject')) & @CRLF)
	;----------------------------------------------------------------------

	Local $sTextMessage = __CleanMessage(_Pop3GetTextMessage($iMsg))
	ConsoleWrite('====================================' & @CRLF)
	ConsoleWrite('MESSAGE:' & $iMsg & @CRLF)
	ConsoleWrite('====================================' & @CRLF)
	ConsoleWrite($sTextMessage)
	; разъединяемся с сервером
	ConsoleWrite(_Pop3Quit() & @CR)
	_pop3Disconnect()
EndFunc   ;==>_Pop3Example_MessageText

;===================================================================================
; Получает текст самого последнего(нового) сообщения.
;===================================================================================
Func _Pop3Example_GetLastMessage($MyPopServer, $MyLogin, $MyPasswd)
	Local $aPop3Stat, $iMsg, $sTextMessage
	_pop3Connect($MyPopServer, $MyLogin, $MyPasswd)
	$aPop3Stat = _Pop3Stat()
	$iMsg = $aPop3Stat[1]
	Local $sTextMessage = __CleanMessage(_Pop3GetTextMessage($iMsg))
	_Pop3Quit()
	_pop3Disconnect()
	Return $sTextMessage
EndFunc   ;==>_Pop3Example_GetLastMessage

--------------------------------------------------------------------------

В примерах используется версия _pop3.au3 0.99 (March 2006, 9th)
С новой (не знал, что есть) версией 1.03 (2011) они несовместимы.
----------------------------------------------------------------------------------------------
Вариант примеров для последней версии UDF _pop3.au3 1.03

Код:
#include <array.au3>
#include <_pop3.au3>
#include <Encoding.au3>


 ; отключить вывод в консоль трассировочной информации, в том числе всех служебных заголовков, иначе выводится по умолчанию
$POP3_TRACE = False

;_Pop3Example_All('email', 'password','pop3.server')
;_Pop3Example_MessageText('email', 'password','pop3.server',1)
;ConsoleWrite(_Pop3Example_GetLastMessage('email', 'password','pop3.server'))

;If _POP3Connect('email', 'password','pop3.server') Then
;_Pop3Example_HeadersText(1)
;_POP3Quit()
;_POP3Disconnect()
;EndIf

;~ ; пример использования функции _POP3Info, которой не было в _pop3.au3 v.0.99
;~ If _POP3Connect('email', 'password','pop3.server') Then
;~ 	;$a = _POP3Info() ; вернет контент четырых основных заголовков: date,from,to,subject
;~ 	;$a = _POP3Info('from') ; вернет массив с контентом поля FROM
;~ 	Local $aData[2]=['from','subject']
;~ 	$a = _POP3Info($aData) ; вернет массив с контентом полей FROM и SUBJECT
;~ 	_ArrayDisplay($a)
;~ 	_POP3Quit()
;~ 	_POP3Disconnect()
;~ EndIf



; Examples
;===================================================================================
; Пример считывает все письма с основными заголовками.
; На письмах с тяжелым контентом - фото, много html и т.д, считывание может зависнуть
; PS: Правильнее было бы считывать текст письма по байтам до завершающей точки, вместо полного возврата контента
; через _Pop3Retr(msg_number), но не знаю как это сделать
;===================================================================================
Func _Pop3Example_All($MyLogin, $MyPasswd,$MyPopServer)

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

	Local $aPop3Stat = _Pop3Stat()
	If @error Then
		MsgBox(0, "Error", "Unable get statistics " & $MyPopServer & @CR & @error)
		ConsoleWrite(_Pop3Quit() & @CR)
		_pop3Disconnect()
		Exit
	Else
		;_ArrayDisplay($aPop3Stat)
		; возвращает массив, где
		; a[0]= общее число писем
		; a[1]= общий размер писем
		; выводим общее число сообщений и общий размер
		ConsoleWrite('TOTAL MSG:' & $aPop3Stat[0] & @CRLF)
		ConsoleWrite('SIZE MSG:'  & $aPop3Stat[1] & @CRLF)
	EndIf

	; выводим некоторые заголовки и текст письма
	For $iMsg = 1 To $aPop3Stat[0]

		; выводим текст некоторых заголовков
		;----------------------------------
		_Pop3Example_HeadersText($iMsg)
		;----------------------------------
		; выводим текст письма
		$sTextMessage = __CleanMessage(_Pop3GetTextMessage($iMsg))
		ConsoleWrite('====================================' & @CRLF)
		ConsoleWrite('MESSAGE:' & $iMsg & @CRLF)
		ConsoleWrite('====================================' & @CRLF)
		ConsoleWrite($sTextMessage)

	Next

	;----------------------------------
	; разъединяемся с сервером
	_Pop3Quit()
	_pop3Disconnect()

EndFunc   ;==>_Pop3Example

;===================================================================================
; выводит некоторые из заголовков письма
;===================================================================================
Func _Pop3Example_HeadersText($iMsg)
	Local $aPop3List, $sRawData, $iSize
	; возвращает двумерный массив, где a[1]=[номер сообщения,размер]
	$aPop3List = _Pop3List($iMsg)
	If IsArray($aPop3List) Then
		$iSize = $aPop3List[1][1]
	EndIf

	$sRawData = _Pop3Top($iMsg) ; вернем заголовки

	Local $sContentType, $sContentEncoding, $sFrom, $sEmail, $sSubject, $sDate
	$sContentEncoding = _Pop3GetContentHeaderByName($sRawData, 'Content-Transfer-Encoding')
	$sContentType     = _Pop3GetContentHeaderByName($sRawData, 'Content-Type')
	$sDate            = _Pop3GetContentHeaderByName($sRawData, 'Date')
	$sFrom            = _Pop3GetContentHeaderByName($sRawData, 'From')
	$sFrom            = _Pop3HeaderDecode($sFrom) ; попытка перекодировать данные заголовков
	$sEmail           = _Pop3GetContentHeaderByName($sFrom, 'email') ; получим только email из заголовка from
	$sSubject         = _Pop3GetContentHeaderByName($sRawData, 'Subject')
	$sSubject         = _Pop3HeaderDecode($sSubject) ; попытка перекодировать данные заголовков

	ConsoleWrite( _
			'====================================' & @CRLF & _
			'№ MSG: '        & $iMsg & @CRLF & _
			'SIZE: '         & $iSize & @CRLF & _
			'Content-Type: ' & $sContentType & @CRLF & _
			'Encoding: '     & $sContentEncoding & @CRLF & _
			'DATE: '         & $sDate & @CRLF & _
			'FROM (RAW): '   & $sFrom & @CRLF & _
			'EMAIL: '        & $sEmail & @CRLF & _
			'SUBJECT: '      & $sSubject & @CRLF _
			)

EndFunc   ;==>_Pop3Example_HeadersText

;===================================================================================
; выводим текст тела письма по его номеру - нумерация начинается с самого старого письма
; т.о чтобы узнать номер последнего пришедшего письма нужно обратиться к массиву, возвращаемому _Pop3Stat()
; или воспользоваться функцией _POP3MsgCnt(), которая вернет число сообщений
;===================================================================================
Func _Pop3Example_MessageText($MyLogin, $MyPasswd,$MyPopServer, $iMsg)
	_pop3Connect($MyLogin, $MyPasswd,$MyPopServer)
	If @error Then
		ConsoleWrite("Unable to connect to " & $MyPopServer & @CR & @error)
		Exit
	EndIf
	;----------------------------------------------------------------------
	Local $sRawData = _Pop3Top($iMsg) ; вернем только заголовки
	ConsoleWrite(_Pop3GetContentHeaderByName($sRawData, 'Date') & @CRLF)
	ConsoleWrite(_Pop3HeaderDecode(_Pop3GetContentHeaderByName($sRawData, 'From')) & @CRLF)
	ConsoleWrite(_Pop3HeaderDecode(_Pop3GetContentHeaderByName($sRawData, 'Subject')) & @CRLF)
	;----------------------------------------------------------------------

	Local $sTextMessage = __CleanMessage(_Pop3GetTextMessage($iMsg))
	ConsoleWrite('====================================' & @CRLF)
	ConsoleWrite('MESSAGE:' & $iMsg & @CRLF)
	ConsoleWrite('====================================' & @CRLF)
	ConsoleWrite($sTextMessage)
	; разъединяемся с сервером
	_Pop3Quit()
	_pop3Disconnect()
EndFunc   ;==>_Pop3Example_MessageText

;===================================================================================
; Получает текст самого последнего(нового) сообщения.
;===================================================================================
Func _Pop3Example_GetLastMessage($MyLogin, $MyPasswd,$MyPopServer)
	Local $sTextMessage=''
	If _pop3Connect($MyLogin, $MyPasswd,$MyPopServer) Then
		$sTextMessage = __CleanMessage(_Pop3GetTextMessage(_POP3MsgCnt()))
	    ; разъединяемся с сервером
	     _Pop3Quit()
	    _pop3Disconnect()
	Endif
	Return $sTextMessage
EndFunc   ;==>_Pop3Example_GetLastMessage


;===================================================================================
; Функции, дополняющие UDF _pop3.au3
;===================================================================================
; Получает содержимое заголовка (после двоеточия) по его имени.
; Для получения email нужно передать не RawData (сырой текст), а контент поля FROM и строку 'email'
;===================================================================================

Func _Pop3GetContentHeaderByName($sRawData, $sHeader)
	Local $aData, $sContent = ''

	Switch $sHeader
		; получим только email из строки from
		Case 'email'
			$aData = StringRegExp($sRawData, '<?([A-Za-z0-9._-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})>?', 1)
			If IsArray($aData) Then $sContent = $aData[0]

			; получим содержимое заголовка после двоеточия из raw данных
		Case Else
			$aData = StringRegExp($sRawData, '(?m)^' & $sHeader & ':\s*(.+)$', 1)
			If IsArray($aData) Then
				$sContent = StringStripCR($aData[0]) ; удаляем перенос строки
			EndIf
	EndSwitch
	Return $sContent
EndFunc   ;==>_Pop3GetContentHeaderByName


;===================================================================================
; перекодровка текста заголовков
;===================================================================================

Func _Pop3HeaderDecode($Data)
	Local $IsCyrillic,$aData
	$IsCyrillic = _Encoding_GetCyrillicANSIEncoding($Data)
	If $IsCyrillic Then Return _Encoding_CyrillicTo1251($Data)

	Local $sEndPart = ' ' ; переменная для хвостовой части строки FROM не закодированная Base64 - как правило это email в тегах <>

	; извлекаем email заключенный в теги <> для его возврата в строку после перекодировки первой части строки
	$aData = StringRegExp($Data, '(<.+>)', 1)
	If IsArray($aData) Then
		$sEndPart &= $aData[0]
	EndIf

	Select
		Case __IsQuotedPrintableSrtring($Data)
			$Data = __CleanHeaders(_Encoding_CyrillicTo1251(_Encoding_QuotedPrintableToANSI($Data)))

		Case __IsBase64String($Data)
			; очищаем строку от лишних сигнатур и хвостовых частей не закодированных в Base64
			$Data = __CleanHeaders($Data, True)
			$Data = _Encoding_CyrillicTo1251(_Encoding_Base64Decode($Data))

		Case Else
			$sEndPart = ''

	EndSelect

	Return $Data & $sEndPart
EndFunc   ;==>_Pop3HeaderDecode

;===================================================================================
; Получает текст письма без заголовков по номеру письма
;===================================================================================
Func _Pop3GetTextMessage($iMsg, $Decode = True)
	Local $sTextMessage, $iIndex, $sBase64Decode
	$sTextMessage = _Pop3Retr($iMsg) ; получим raw текст письма со всеми заголовками
	$iIndex = StringInStr($sTextMessage, @CRLF & @CRLF) ; получим индекс первого вхождения разделителя заголовков и текста письма
	$sTextMessage = StringMid($sTextMessage, $iIndex, -1) ; получим только текст письма

	If $Decode Then
		Local $IsCyrillic = _Encoding_GetCyrillicANSIEncoding($sTextMessage)
		If $IsCyrillic Then Return _Encoding_CyrillicTo1251($sTextMessage)

		; Перед декодированием из Base64 строку нужно полностью очистить от не Base64 символов. Валидные символы [A-Za-z0-9/+]
		; иначе Base64Decode НЕ РАБОТАЕТ
		$sBase64Decode = _Encoding_Base64Decode($sTextMessage)
		If $sBase64Decode Then
			$sTextMessage = _Encoding_CyrillicTo1251($sBase64Decode)
		ElseIf __IsQuotedPrintableSrtring($sTextMessage) Then
			$sTextMessage = _Encoding_CyrillicTo1251(_Encoding_QuotedPrintableToANSI($sTextMessage))
		EndIf
	EndIf
	Return $sTextMessage
EndFunc   ;==>_Pop3GetTextMessage

#region Internal functions
;==================================================================================
; Internal fucntions
;===================================================================================
; Очистка строки от сигнатуры кодировки и сепараторов в строках с base64 и quoted-printable кодировкой
;===================================================================================

Func __CleanHeaders($sContent, $StripWS = False)
	If StringRegExp($sContent, '=(.+)=') Then
		Local $sPattern = '(?i)(utf-8\?(B|Q)\?|KOI8-R\?(B|Q)\?|windows-1251\?(B|Q)\?|([=?])|(<.+>))'
		$sContent = StringRegExpReplace($sContent, $sPattern, '') ; удаляем сигнатуру кодировки, знаки = и ?, а также незакодированые символы email
		If $StripWS Then $sContent = StringStripWS($sContent, 8) ; удаляем все пробелы
	EndIf
	Return $sContent
EndFunc   ;==>__CleanHeaders

;===================================================================================
; Очистка текста письма от html и прочего кода, а также пустых строк - нужна доработка
;===================================================================================
Func __CleanMessage($sTextMessage)
	$sTextMessage = StringRegExpReplace($sTextMessage, '(
)', @CRLF) ; заменяем html теги перевода строк на символы перевода строк
	$sTextMessage = StringRegExpReplace($sTextMessage, '(?s)(<.+?>|\*?\s*{.+}| )', '') ; убираем html и CSS код
	$sTextMessage = StringRegExpReplace($sTextMessage, '(\r\n|\r|\n){2,}', '\1') ; удаляем пустые строки
	$sTextMessage = StringStripWS($sTextMessage, 4) ; удаляем многократный повтор пробелов
	Return $sTextMessage
EndFunc   ;==>__CleanMessage

;===================================================================================
; проверка на тип строки quoted-printable
;===================================================================================
Func __IsQuotedPrintableSrtring($sString)
	If StringRegExp($sString, '(=[A-Z0-9]{2}=)') Then Return True
	Return False
EndFunc   ;==>__IsQuotedPrintableSrtring

;===================================================================================
; проверка на тип строки base64 - предназначена только для строк-заголовков полученных по протоколу Pop3
;===================================================================================
Func __IsBase64String($sString)
	If StringRegExp($sString, '[=?](?i:utf-8\?B\?|KOI8-R\?B\?|windows-1251\?B\?)([A-Za-z0-9/+]+)[=?]') Then Return True
	Return False
EndFunc   ;==>__IsBase64String

#EndRegion Internal functions
 
Верх