Estou escrevendo em um script que extrai e salva anexos JPEG de e-mails e os passa para o imagemagick. No entanto, moro na Alemanha e caracteres especiais no texto/assunto do e-mail como "ö", "ä", "ü" e "ß" são bastante comuns.
Estou extraindo o assunto com formail:
SUBJECT=$(formail -zxSubject: <"$file")
e isso resulta em:
- =?UTF-8?Q?Meine_G=c3=bcte?=
("Meine Güte") ou pior ainda
- =?UTF-8?B?U2Now7ZuZSBHcsO8w59lIQ==?=
("Schöne Grüße!").
Tento usar parte do assunto como nome de arquivo e como anotação de texto do imagemagick, o que obviamente não funciona.
Como faço para converter esse texto UTF-8 em texto com caracteres especiais no bash?
Desde já, obrigado! Marcus
Responder1
Como faço para converter esse texto UTF-8 em texto com caracteres especiais no bash?
O que você tem não ébastante"Texto UTF-8". Você realmentequerertexto simples UTF-8 comosaída, pois é o que o Linux usa para "caracteres especiais" em todos os lugares.
Sua entrada, em vez disso, é MIME (RFC 2047) codificado em UTF-8. O "Q" marca o modo Quoted-Printable e o "B" marca o modo Base64. Entre outros, PerlCodificar::MIME::Cabeçalhopode ser usado para decodificar ambos:
#!/usr/bin/env perl
use open qw(:std :utf8);
use Encode qw(decode);
while (my $line = <STDIN>) {
print decode("MIME-Header", $line);
}
Oneliner (veja perldoc perlrun
para explicação):
perl -CS -MEncode -ne 'print decode("MIME-Header", $_)'
Isso pode assumir qualquer formato como entrada:
$ echo "Subject: =?UTF-8?Q?Meine_G=c3=bcte?=, \
=?UTF-8?B?U2Now7ZuZSBHcsO8w59lIQ==?=" | perl ./decode.pl
Subject: Meine Güte, Schöne Grüße!
Uma versão em Python 3:
#!/usr/bin/env python3
import email.header, sys
words = email.header.decode_header(sys.stdin.read())
words = [s.decode(c or "utf-8") for (s, c) in words]
print("".join(words))
Responder2
O próprio assunto do e-mail é o cabeçalho e os cabeçalhos devem conter apenas caracteres ASCII. É por isso que o assunto UTF-8 (ou qualquer outro conjunto de caracteres não ASCII) deve ser codificado.
Esta forma de codificar caracteres não ASCII para ASCII é descrita na RFC 1342.
Basicamente, o assunto codificado tem (como você já listou em seus exemplos) o seguinte formato:
=?charset?encoding?encoded-text?=
Com base no valor da codificação, o texto codificado é decodificado como imprimível entre aspas (Q) ou como base64 (B).
Para obter um formato legível por humanos, você precisa passar a parte do texto codificado do valor do cabeçalho do assunto para o programa que o decodifica. Acredito que existam alguns comandos independentes para fazer isso (uudecode), mas prefiro usar one-liners Perl:
Para impressão cotada:
perl -pe 'use MIME::QuotedPrint; $_=MIME::QuotedPrint::decode($_);'
e para base64:
perl -pe 'use MIME::Base64; $_=MIME::Base64::decode($_);'
Certifique-se de passar apenas a parte do texto codificado e não o valor inteiro do cabeçalho do assunto.