Python сохранение вложений электронной почты с именами на разных языках

Рейтинг: 0Ответов: 1Опубликовано: 24.02.2023

Пытаюсь сохранить вложения с электронной почты, имена файлов могут быть на латинице, кириллице или других языках. если для сохранения использую код:

# получаем имя файла
filename = part.get_filename()
print(f'Inbox filename: {filename}')

получаю:

=======================================
# имя файла Книга1.xlsx
Inbox filename: =?windows-1251?B?yu3o4+AxLnhsc3g=?=
=======================================
# имя файла Γειά σου.txt
Inbox filename: =?utf-8?B?zpPOtc65zqwgz4POv8+FLnR4dA==?=
=======================================
# имя файла Innovate.pdf
Inbox filename: Innovate.pdf

если добавить перекодировку:

# получаем имя файла
filename = part.get_filename()
print(f'Inbox filename: {filename}')

filename = base64.b64decode(filename).decode('windows-1251') 
# или
filename = base64.b64decode(filename).decode('utf-8')

print(f'Save filename: {filename}')

при указании 'windows-1251' имя файла на кириллице имеет лишние символы, греческий же неправильный:

=======================================
Inbox filename: =?windows-1251?B?yu3o4+AxLnhsc3g=?=
Save filename: В)ЭЈ
                   5ЫќAКнига1.xlsx
=======================================
Inbox filename: =?utf-8?B?zpPOtc65zqwgz4POv8+FLnR4dA==?=
Save filename: єЧь:O:Ч:з:°ѓ>:я>№СбР

при указании 'utf-8' получаю ошибку как на кириллице:

Inbox filename: =?windows-1251?B?yu3o4+AxLnhsc3g=?=
Traceback (most recent call last):
  File "/var/project/mailparce/mailparce.py", line 36, in <module>
    filename = base64.b64decode(filename).decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc2 in position 0: invalid continuation byte

так и на греческом:

Inbox filename: =?utf-8?B?zpPOtc65zqwgz4POv8+FLnR4dA==?=
Traceback (most recent call last):
  File "/var/project/mailparce/mailparce.py", line 36, in <module>
    filename = base64.b64decode(filename).decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xba in position 0: invalid start byte

При получении имени файла на латинице при указании кодировки всегда выскакивает ошибка:

=======================================
Inbox filename: Innovate.pdf
Traceback (most recent call last):
  File "/var/project/mailparce/mailparce.py", line 36, in <module>
    filename = base64.b64decode(filename).decode('windows-1251')
  File "/usr/lib/python3.10/base64.py", line 87, in b64decode
    return binascii.a2b_base64(s)
binascii.Error: Incorrect padding
=======================================
Inbox filename: Innovate.pdf
Traceback (most recent call last):
  File "/var/project/mailparce/mailparce.py", line 36, in <module>
    filename = base64.b64decode(filename).decode('utf-8')
  File "/usr/lib/python3.10/base64.py", line 87, in b64decode
    return binascii.a2b_base64(s)
binascii.Error: Incorrect padding

тоже и с именем файла со смешанными символами к примеру 'строка string.txt' :

Inbox filename: =?koi8-r?B?09TSz8vBIHN0cmluZy50eHQ=?=
Traceback (most recent call last):
  File "/var/project/mailparce/mailparce.py", line 36, in <module>
    filename = base64.b64decode(filename).decode('koi8-r')
  File "/usr/lib/python3.10/base64.py", line 87, in b64decode
    return binascii.a2b_base64(s)
binascii.Error: Invalid base64-encoded string: number of data characters (29) cannot be 1 more than a multiple of 4

как правильно получить правильное имя файла?

Ответы

▲ 0

нашел такое решение:

from email.header import decode_header
....
filename = part.get_filename()
encoding = decode_header(part.get_filename())[0][1]
if encoding != None:
    filename = decode_header(part.get_filename())[0][0].decode(encoding )