Pregunta

Tengo muchos correos electrónicos provenientes de diferentes fuentes. todos tienen archivos adjuntos, muchos de ellos tienen nombres de archivos adjuntos en chino, por lo que estos los nombres se convierten a base64 por sus clientes de correo electrónico.

Cuando recibo estos correos electrónicos, deseo decodificar el nombre. pero hay otros nombres que son no base64. ¿Cómo puedo diferenciar si una cadena es base64 o no, usando el lenguaje de programación jython ?

Es decir.

Primer archivo adjunto:

------=_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 archivo adjunto:

------=_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==?="  

Tenga en cuenta tanto " Codificación de transferencia de contenido " tener base64

¿Fue útil?

Solución

  

Tenga en cuenta que ambos Content-Transfer-Encoding tienen base64

No relevante en este caso, el Content-Transfer-Encoding solo se aplica a la carga útil del cuerpo, no a los encabezados.

=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

Es un átomo de encabezado codificado con RFC2047 . La función stdlib para decodificarlo es email.header.decode_header . Sin embargo, todavía necesita un poco de procesamiento posterior para interpretar el resultado de esa función:

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

Sin embargo ...

Content-Type: application/vnd.ms-excel;
 name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="

Esto es simplemente incorrecto. ¿Qué anuncio publicitario lo creó? La codificación RFC2047 solo puede ocurrir en átomos, y una cadena entre comillas no es un átomo. RFC2047 §5 niega explícitamente esto:

  
      
  • Una 'palabra codificada' NO DEBE aparecer dentro de una 'cadena entre comillas'.
  •   

La forma aceptada de codificar encabezados de parámetros cuando están presentes cadenas largas o caracteres Unicode es RFC2231 , que es una bolsa de daño completamente nueva. Pero debe usar una biblioteca estándar de análisis de correo que se encargará de eso por usted.

Por lo tanto, puede detectar el '=?' en los parámetros del nombre de archivo si lo desea, e intente decodificarlo a través de RFC2047. Sin embargo, lo más estrictamente correcto es tomar el correo en su palabra y realmente llamar al archivo =? Gb2312? B? ULGxvmhlbrixsb5nLnhscw ==? = !

Otros consejos

El valor del encabezado le dice esto:

=?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

¿Entonces dividirse en "? " en realidad te da esto (notación JSON)

["=", "gb2312", "B", "uLGxvmhlbrixsb5nLnhscw==", "="]

En la matriz resultante, si " B " está en la posición 2, enfrenta una cadena codificada en base 64 en la posición 3. Una vez que la decodificó, asegúrese de prestar atención a la codificación en la posición 1, probablemente sería mejor convertir todo a UTF-8 usando eso info.

@gnud, @edg: a menos que haya entendido mal, me pregunta sobre el nombre del archivo, no el contenido del archivo @setori: Content-Trasfer-Encoding le indica cómo se codifica el CONTENIDO del archivo, no el " nombre de archivo " ;.

No soy un experto, pero esta parte aquí en el nombre del archivo le dice sobre los caracteres que siguen:

=? gb2312? B?

Estoy buscando la documentación en los RFC ... ¡Ah! aquí está: http://tools.ietf.org/html/rfc2047

El RFC dice:

Generalmente, una " palabra codificada " es una secuencia de caracteres ASCII imprimibles que comienza con " =? " ;, termina con "? = " ;, y tiene dos ''? '' s en el medio.

Algo más a tener en cuenta es el código en SharpMimeTools, un analizador MIME (en C #) que uso en mi error aplicación de seguimiento , BugTracker.NET

Hay una mejor manera que el método de bobince para manejar la salida de decode_header . Lo encontré aquí: http://mail.python.org /pipermail/email-sig/2007-March/000332.html

name = unicode(email.header.make_header(email.header.decode_header(x)))

Bueno, analiza el encabezado del correo electrónico en un diccionario. Y luego verifica si Content-Transfer-Encoding está configurado y si es = " base64 " o "base-64".

Pregunta: " " " También necesito saber qué tipo de archivo es, es decir .xls o .doc, así que necesito decodificar el nombre de archivo para procesar correctamente el archivo adjunto, pero como se muestra arriba, parece gb2312 no es compatible con jython, ¿conoce alguna rotonda? " " "

Datos:

Content-Type: application/vnd.ms-excel;
 name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="

Observaciones:

(1) La primera línea indica Microsoft Excel, por lo que .xls se ve mejor que .doc

(2)

>>> import base64
>>> base64.b64decode("uLGxvmhlbrixsb5nLnhscw==")
'\xb8\xb1\xb1\xbehen\xb8\xb1\xb1\xbeg.xls'
>>>

(a) La extensión parece ser .xls ; no es necesario un códec gb2312
(b) Si desea un nombre de archivo seguro para el sistema de archivos, puede usar el " -_ " variante de base64 O podrías codificarla en porcentaje
(c) Para lo que vale, el nombre del archivo es XYhenXYg.xls donde X e Y son 2 caracteres chinos que juntos significan "copiar". y el resto son caracteres ASCII literales.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top