2008-11-07 14 views
6

Tengo muchos correos electrónicos procedentes de diferentes fuentes. todos tienen archivos adjuntos, muchos de ellos tienen nombres de archivos adjuntos en chino, por lo que los nombres se convierten a base64 por sus clientes de correo electrónico.cómo saber si una cadena es base64 o no

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?

Ie.

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 elemento de sujeción:

------=_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 "Content-Transfer-Encoding" tienen base 64

Respuesta

12

Tenga en cuenta tanto Content-Transfer-Encoding tienen base 64

No es relevante en este caso, el Content-Transfer-Encoding sólo se aplica a la carga útil del cuerpo, no a las cabeceras.

=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?= 

Eso es un átomo de cabecera codificados en RFC2047. La función stdlib para decodificar es email.header.decode_header. Todavía necesita un poco de post-procesamiento para interpretar el resultado de esa función sin embargo:

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 errónea. ¿Qué correo lo creó? La codificación RFC2047 solo puede ocurrir en átomos, y una cadena citada no es un átomo. § 5 RFC2047 niega explícitamente esta:

  • Una 'palabra codificada' no debe aparecer dentro de un 'quoted-cadena'.

La forma aceptada para codificar las cabeceras de parámetros cuando larga cadena de caracteres Unicode o están presentes es RFC2231, que es una bolsa completamente nueva de dolor. Pero deberías estar usando una biblioteca estándar de análisis de correo electrónico que hará frente a eso por ti.

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

+0

Supongo que las perspectivas lo crearon .... no estoy seguro – Setori

+0

Intenté simplemente llamar al archivo adjunto simplemente por '=? Gb2312? B? ULGxvmhlbrixsb5nLnhscw ==? =' Pero desafortunadamente simplemente se cae y se queja amargamente, no tengo idea de por qué , tal vez investigar esa queja resolvería el problema más rápido, gracias bobince lo aprecio – Setori

+0

¿Qué se queja y cuándo? El sistema operativo probablemente se molestará si intentas guardar realmente un archivo con ese nombre, claro, pero cada vez que tomes un nombre de archivo de la entrada del usuario necesitarás un filtro muy estricto para mantener fuera a los personajes peligrosos: lo mejor es que solo permita [a -zA-Z0-9_] (y atrapa una cadena vacía también). – bobince

0

bueno, ya analizar la cabecera de correo electrónico en un diccionario. Y luego comprueba si se ha configurado Content-Transfer-Encoding, y si es = "base64" o "base-64".

7

@gnud, @edg - A menos que malinterprete, él pregunta por el nombre del archivo, no por 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 está diciendo acerca de 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.

Otra cosa a tener en cuenta es el código en SharpMimeTools, un analizador MIME (en C#) que yo uso en mi bug tracking aplicación, BugTracker.NET

+0

correcto preguntando después del nombre de archivo no el contenido, nunca he tenido problemas con eso, a pesar de que tiene caracteres chinos en él. como es todo base64 – Setori

21

El valor de encabezado te 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 dividir en "?" en realidad te lleva este JSON (notación)

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

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

+0

bueno, contando a partir de 0 –

+2

¿Hay alguna otra manera? ;-) – Tomalak

+0

¿Está basada esta respuesta en la documentación de autoría? – Deestan

0

pregunta: "" "También realmente se necesita saber qué tipo de archivo es decir, .xls o .doc por lo que es necesario para decodificar el nombre del archivo con el fin de procesar correctamente el archivo adjunto, pero como se muestra arriba, parece que 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 .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 la variante "-_" de base64 O puede codificar por ciento
(c) Para lo que vale, el nombre del archivo es XYhenXYg.xls donde X e Y son 2 caracteres chinos que en conjunto significan "copiar" y el resto son caracteres ASCII literales.

Cuestiones relacionadas