como saber se uma string é base64 ou não
Pergunta
Eu tenho muitos e-mails provenientes de diferentes fontes. todos eles têm anexos, muitos deles têm nomes de anexos em chinês, assim que estes nomes são convertidos para base64 por seus clientes de e-mail.
Quando eu receber esses e-mails, eu desejo para decodificar o nome. mas há outros nomes que são não base64. Como posso diferenciar se uma string é base64 ou não, usando o Jython linguagem de programação ?
Ie.
Primeiro anexo:
------=_NextPart_000_0091_01C940CC.EF5AC860
Content-Type: application/vnd.ms-excel;
name="Copy of Book1.xls"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="Copy of Book1.xls"
segundo anexo:
------=_NextPart_000_0091_01C940CC.EF5AC860
Content-Type: application/vnd.ms-excel;
name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="
Por favor, note tanto " Content-Transfer-Encoding " Have base64
Solução
Por favor, note tanto
Content-Transfer-Encoding
Tem base64
Não é relevante neste caso, o Content-Transfer-Encoding
só se aplica à carga corpo, para não os cabeçalhos.
=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=
Isso é um RFC2047 codificado pelo cabeçalho átomo. A função stdlib para descodificar é email.header.decode_header
. Ele ainda precisa de um pouco de pós-processamento para interpretar o resultado dessa função no entanto:
import email.header
x= '=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?='
try:
name= u''.join([
unicode(b, e or 'ascii') for b, e in email.header.decode_header(x)
])
except email.Errors.HeaderParseError:
pass # leave name as it was
No entanto ...
Content-Type: application/vnd.ms-excel;
name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="
Isto é simplesmente errado. O mailer criou? codificação RFC2047 só pode acontecer em átomos, e uma cadeia de caracteres citado não é um átomo de. RFC2047 §5 nega explicitamente o seguinte:
- Uma 'palavra-codificado', não deve aparecer dentro de um 'citou-corda'.
A maneira aceitável de cabeçalhos de parâmetro codificar quando cadeia longa ou caracteres Unicode estão presentes é RFC2231 , que é um saco totalmente novo de dor. Mas você deve estar usando uma biblioteca de análise de e-mail padrão que irá lidar com isso para você.
Então, você poderia detectar a '=?'
nos parâmetros de nome de arquivo, se quiser, e tentar decodificá-lo via RFC2047. No entanto, a coisa estritamente falando-correta de fazer é levar o mailer em sua palavra e realmente chamar a =?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=
arquivo!
Outras dicas
O valor do cabeçalho diz-lhe isto:
=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?= "=?" introduces an encoded value "gb2312" denotes the character encoding of the original value "B" denotes that B-encoding (equal to Base64) was used (the alternative is "Q", which refers to something close to quoted-printable) "?" functions as a separator "uLG..." is the actual value, encoded using the encoding specified before "?=" ends the encoded value
Assim, a divisão em "?" na verdade, você recebe este (notação JSON)
["=", "gb2312", "B", "uLGxvmhlbrixsb5nLnhscw==", "="]
Na matriz resultante, se "B" está na posição 2, você enfrenta uma base 64 string codificada na posição 3. Uma vez que você decodificado-lo, certifique-se de prestar atenção a codificação na posição 1, provavelmente seria melhor para converter a coisa toda para UTF-8 usando essa informação.
@gnud, @edg - A menos que eu entenda mal, ele está perguntando sobre o nome do arquivo, não o conteúdo do arquivo @setori -. o Content-trasfer-Encoding está lhe dizendo como o conteúdo do arquivo é codificado, e não o "nome do arquivo"
Eu não sou um especialista, mas esta parte aqui no nome do arquivo é dizendo-lhe sobre os personagens que se seguem:
=? GB2312? B?
Eu estou procurando a documentação nas RFCs ... Ah! aqui está: http://tools.ietf.org/html/rfc2047
O RFC diz:
Geralmente, uma "palavra-codificado" é uma seqüência de caracteres ASCII imprimíveis que começa com "=?", Termina com "? =", E tem dois "?" S no meio.
Outra coisa é olhar para o código no SharpMimeTools, um analisador MIME (em C #) que eu uso na minha bug rastreamento aplicativo, BugTracker.NET
Há uma maneira melhor do que o método de bobince para lidar com a saída do decode_header
. Eu encontrei-o aqui: http://mail.python.org /pipermail/email-sig/2007-March/000332.html
name = unicode(email.header.make_header(email.header.decode_header(x)))
Bem, você analisar o cabeçalho de e-mail em um dicionário. E então você verificar se Content-Transfer-Encoding é conjunto, e se ele = "base64" ou "base64".
Pergunta: "" "Também eu realmente preciso saber que tipo de arquivo é ie .xls ou .doc então eu faço necessidade de decodificar o nome do arquivo, a fim de processar corretamente o anexo, mas como acima, parece gb2312 não é suportado em jython, conhece algum rotundas? "" "
Data:
Content-Type: application/vnd.ms-excel;
name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="
Observações:
(1) A primeira linha indica Microsoft Excel, de modo .xls
está olhando melhor do que .doc
(2)
>>> import base64
>>> base64.b64decode("uLGxvmhlbrixsb5nLnhscw==")
'\xb8\xb1\xb1\xbehen\xb8\xb1\xb1\xbeg.xls'
>>>
(a) A extensão parece ser .xls
- sem necessidade de um gb2312
codec
(B) Se você quer um nome de arquivo file-system-safe, você poderia usar o "-_" variante de base64 ou você poderia por cento codificar-lo
(C) Por que vale a pena, o nome do arquivo é XYhenXYg.xls
onde X e Y são 2 caracteres chineses que, juntos média "cópia" e os restantes são caracteres ASCII literal.