Недавно ковырялся с UDF _pop3.au3 и так как в ней есть только функционал получения сырых данных, с которыми дальше нужно что-то делать, решил это что-то воплотить в несколько более-менее удобных функций.
_Pop3GetContentHeaderByName - получает содержимое служебного заголовка после двоеточия
_Pop3HeaderDecode - декодирует (в случае необходимости) текст заголовка
_Pop3GetTextMessage - получает (и пытается декодировать) содержимое письма
На данный момент контент заголовков декодируется правильно почти во всех случаях (с исключениями нужно еще поразбираться - у меня на 70 писем два таких случая - неправильная кирилица получается). Что касается содержимого письма - то здесь все гораздо сложнее. Декодирование из base64 требует, чтобы строка состояла исключительно из валидного набора символов, чего весьма трудно добиться. Среди доп. функций есть те, которые стараются максимально очистить контент от html и прочего кода, но это не всегда помогает. Нормально декодируются небольшие письма состоящие из одной части и простого текста.
Состоящие же из несколько частей (у каждой свой набор заголовков) могут иметь разные варианты кодировки , много лишнего кода и поэтому трудно поддаются очистке и перекодированию. Над этим нужно еще поработать.
Функции, дополняющие UDF _pop3.au3:
Примеры использования:
--------------------------------------------------------------------------
В примерах используется версия _pop3.au3 0.99 (March 2006, 9th)
С новой (не знал, что есть) версией 1.03 (2011) они несовместимы.
----------------------------------------------------------------------------------------------
Вариант примеров для последней версии UDF _pop3.au3 1.03
_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