Кодировка пути к папке IMAP (IMAP UTF-7) для Python
Я хотел бы знать, существует ли какая-либо "официальная" функция / библиотека в Python для кодирования пути к папке IMAP4 UTF-7.
в imapInstance.list()
Я получаю следующий путь в кодировке IMAP UTF-7:
'(\\HasNoChildren) "." "[Mails].Test&AOk-"',
Если я сделаю следующую кодировку:
(u"[Mails].Testé").encode('utf-7')
Я получил:
'[Mails].Test+AOk-'
Который является UTF-7, но не IMAP UTF-7 в кодировке. Test+AOk-
вместо Test&AOk-
Мне нужна официальная функция или библиотека, чтобы получить версию в кодировке IMAP UTF-7.
3 ответа
Пакет IMAPClient имеет функциональность для кодирования и декодирования с использованием модифицированного UTP-7 IMAP. Загляните в модуль IMAPClient.imap_utf7. Этот модуль может использоваться автономно, или вы можете просто использовать IMAPClient, который выполняет прозрачное кодирование и декодирование имен папок.
Домашняя страница проекта: http://imapclient.freshfoo.com/
Пример кода:
from imapclient import imap_utf7
decoded = imap_utf7.decode('&BdAF6QXkBdQ-')
Я написал очень простую реализацию Python 3 для IMAP UTF7, которая соответствует спецификации, и, похоже, она работает. ("foo\rbar\n\n\n\r\r" и многие другие обходы, '&BdAF6QXkBdQ-', 'Test&Co', "[Mails].Test&AOk-" и '~peter/mail/&ZeVnLIqe-/&U,BTFw-'веди себя как положено).
#works with python 3
import base64
def b64padanddecode(b):
"""Decode unpadded base64 data"""
b+=(-len(b)%4)*'=' #base64 padding (if adds '===', no valid padding anyway)
return base64.b64decode(b,altchars='+,',validate=True).decode('utf-16-be')
def imaputf7decode(s):
"""Decode a string encoded according to RFC2060 aka IMAP UTF7.
Minimal validation of input, only works with trusted data"""
lst=s.split('&')
out=lst[0]
for e in lst[1:]:
u,a=e.split('-',1) #u: utf16 between & and 1st -, a: ASCII chars folowing it
if u=='' : out+='&'
else: out+=b64padanddecode(u)
out+=a
return out
def imaputf7encode(s):
""""Encode a string into RFC2060 aka IMAP UTF7"""
s=s.replace('&','&-')
iters=iter(s)
unipart=out=''
for c in s:
if 0x20<=ord(c)<=0x7f :
if unipart!='' :
out+='&'+base64.b64encode(unipart.encode('utf-16-be')).decode('ascii').rstrip('=')+'-'
unipart=''
out+=c
else : unipart+=c
if unipart!='' :
out+='&'+base64.b64encode(unipart.encode('utf-16-be')).decode('ascii').rstrip('=')+'-'
return out
Учитывая простоту этого кода, я установил его в открытом доступе, поэтому не стесняйтесь использовать его по своему усмотрению.
Реализация imapclient отчасти нарушена:
x = "foo\rbar\n\n\n\r\r"
imap_utf7.decode(imap_utf7.encode(x))
Результат:
>> 'foo&bar\n\n\r-'
Редактировать:
После некоторых исследований я обнаружил реализацию в MailPile, которая не дает сбоя при кодировании в обоих направлениях в этом тесте. Я также портировал его на Python3, если вам интересно: https://github.com/MarechJ/py3_imap_utf7
Вы можете использовать пакет imap_tools: https://pypi.org/project/imap-tools/
from imap_tools.imap_utf7 import encode, decode
print(encode('привет'))
>>> b'&BD8EQAQ4BDIENQRC-'
print(decode(b'&BD8EQAQ4BDIENQRC-'))
>>> привет