Foro de elhacker.net

Programación => Programación Visual Basic => Mensaje iniciado por: adla en 5 Noviembre 2020, 20:27 pm



Título: extraer adjuntos de correos EML
Publicado por: adla en 5 Noviembre 2020, 20:27 pm
hola, tengo una carpeta con correos en eml, ¿como puedo hacer un programa para extraerlos todos por lotes en una nueva carpeta?, por favor si teneis algun codigo en vb6 que haga esto o me vale una aplicacion compilada en otro lenguaje que se elija una carpeta y extraiga todos los eml en otra. Gracias


Título: Re: extraer adjuntos de correos EML
Publicado por: adla en 10 Noviembre 2020, 11:07 am
doy mas información, porque no consigo hacerlo, creo que la idea la tengo pero no me centro, estoy con una medicación fuerte para la ansiedad y la depresión que no me deja pensar.

1. la idea es abrir el fichero .eml y recorrerlo hasta encontrar "filename=" que contiene el nombre del adjunto, algo asi:

Private Sub VerContenido(Fichero As String)
    Dim Canal As Integer
    Dim Cadena As String
    Dim NombreArchivo As String
    Dim Contenido As String
    Dim Adjunto As String
    Dim t As Integer
 
    If Len(Fichero) = 0 Then Exit Sub
 
    NombreArchivo = ""
    Contenido = ""
    Adjunto = ""
 
    Canal = FreeFile()
    Open Fichero For Input As #Canal
 
    Do While Not EOF(Canal)
        'lee una linea del fichero origen
        Line Input #Canal, Cadena
 
   ' Si la variable NombreArchivo esta vacia el contenido se añade a Contenido
        ' Aqui se guarda todo el mensaje del correo menos los adjuntos en txt
        If NombreArchivo = "" Then Contenido = Contenido + Cadena + Chr$(13) + Chr$(10)
        ' Si se ha encontrado el nombre de un adjunto
        ' el contenido del adjunto se guarda en la variable Adjunto
        If NombreArchivo <> "" Then
            If Cadena <> "" Then
                Adjunto = Adjunto + Cadena
            End If
        End If
 
   ' Si encontramos "filename=" quiere decir que hay un adjunto
        t = InStr(LCase(Cadena), "filename=")
        If t > 0 Then
            NombreArchivo = Mid$(Cadena, t + 10)
            NombreArchivo = Left(NombreArchivo, Len(NombreArchivo) - 1)
        End If
    Loop
    Close #Canal    ' Cierra el archivo.
 
End Sub

2. Ahora tenemos dos variables, Contenido con todo el mensaje menos los adjuntos que se guardaria como aguaococacola.txt y la variable Adjunto que contiene el adjunto codificado en Base64, habria que pasar esa codificación a binario y guardarla como aguaococacola.pps, para eso he encontrado estas funciones:

' Codificar y Decodificar en BASE64
 
Public Function DecodeBase64(ByVal strData As String) As Byte()
    Dim objXML As Object
    Dim objNode As Object
 
    Set objXML = CreateObject("MSXML2.DOMDocument")
    Set objNode = objXML.createElement("b64")
    objNode.dataType = "bin.base64"
    objNode.Text = strData
    DecodeBase64 = objNode.nodeTypedValue
 
    Set objNode = Nothing
    Set objXML = Nothing
 
End Function
 
 
Public Function EnecodeBase64(ByVal strData As String) As Byte()
    Dim objStream As Object
    Dim objNode As Object
    Dim objXML As Object
    Dim bArray() As Byte
 
    Set objStream = CreateObject("ADODB.Stream")
 
    With objStream
        .Type = 2
        .Open
        .Charset = "unicode"
        .WriteText strData
        .Flush
        .Position = 0
        .Type = 1
        .read (2)
        bArray = .read
        .Close
    End With
 
    Set objXML = CreateObject("MSXML2.DOMDocument")
    Set objNode = objXML.createElement("b64")
 
    objNode.dataType = "bin.base64"
    objNode.nodeTypedValue = bArray
    EnecodeBase64 = objNode.Text
 
    Set objStream = Nothing
    Set objNode = Nothing
    Set objXML = Nothing
 
End Function

3. Si hay varios adjuntos se tiene que repetir el proceso.

a). Tengo problemas para encontrar el final del adjunto.
b). No sé como pasar la variable Adjunto para que funcione la decodificacion Base64
c). No sé como guardar el archivo Adjunto una vez pasado a binario.

He intentado varias cosas pero todas me dan error. Alguien me puede ayudar  :-(

Gracias, un saludo.


Título: Re: extraer adjuntos de correos EML
Publicado por: AlbertoBSD en 10 Noviembre 2020, 15:59 pm
Te puedo ayudar , pero no tengo compilador de VB ni de tecnologías Microsoft en este momento, pasame un archivo EML y con gusto le hecho un ojo para extraer todas los adjuntos, por cierto que ya debería de existir un programa que haga eso no?



Edito ya vi la estructura del archivo y no esta tan complicada.

Pregunta:

Quieres todos los adjuntos incluidos los que aparecen en el body del mensaje como imagenes y demas o solo considerados realmente "attachment" ?

Las imágenes del body y demás tienen un "inline" en el código ejemplo
Código:
Content-Disposition: inline; filename="background.gif"

O solo los "attachment"
Código:
Content-Disposition: attachment; filename="attachment.txt"


Saludos!


Título: Re: extraer adjuntos de correos EML
Publicado por: adla en 10 Noviembre 2020, 17:25 pm
Te puedo ayudar , pero no tengo compilador de VB ni de tecnologías Microsoft en este momento, pasame un archivo EML y con gusto le hecho un ojo para extraer todas los adjuntos, por cierto que ya debería de existir un programa que haga eso no?



Edito ya vi la estructura del archivo y no esta tan complicada.

Pregunta:

Quieres todos los adjuntos incluidos los que aparecen en el body del mensaje como imagenes y demas o solo considerados realmente "attachment" ?

Las imágenes del body y demás tienen un "inline" en el código ejemplo
Código:
Content-Disposition: inline; filename="background.gif"

O solo los "attachment"
Código:
Content-Disposition: attachment; filename="attachment.txt"


Saludos!

he encontrado esto: https://www.enmimaquinafunciona.com/pregunta/51267/como-extraer-los-datos-adjuntos-de-archivos-eml-con-la-linea-de-comandos-de-windows
pero no funcionan los enlaces..

aqui puedes descargar un zip que contiene un eml con un solo adjunto.. la idea es que extraiga todos los adjuntos, aunque este solo contiene uno. Solo los adjuntos pero si son imagenes tambien, no los logos que tenga el cuerpo.

Muchas gracias Alberto.



Título: Re: extraer adjuntos de correos EML
Publicado por: AlbertoBSD en 10 Noviembre 2020, 18:20 pm
Lo hice pero actualmente solo para un solo archivo eml, ya que me da flojera hacerlo para todo un directorio y que busque los archivos eml etc etc etc...

Lo hice en C. se que este es el subforo de VB, pero la verdad VB no me gusta mucho para este tipo de operaciones, de hechos me gusta el VBA para automatizar trabajos en Excel

Imagen de prueba que funciona:
(https://albertobsd.dev/uploads/1605028351_eml_dump_salida.png)

Y el archivo se crea en el directorio pasado como segundo parametro.

(https://albertobsd.dev/uploads/1605028869_salida_eml.png)

Por cierto si el siguiente código fuente si se compila en algunos compiladores de Windows puede dar muchos warning, pero con gcc de MinGW no me tira ningun warning ni error como esta en la imagen.

Código
  1. /*
  2. gcc -o dump_eml.exe dump_eml_attachments.c
  3. */
  4.  
  5. #include<stdio.h>
  6. #include<stdlib.h>
  7. #include<string.h>
  8. #include<stdint.h>
  9.  
  10. static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  11.                                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  12.                                'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  13.                                'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  14.                                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  15.                                'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  16.                                'w', 'x', 'y', 'z', '0', '1', '2', '3',
  17.                                '4', '5', '6', '7', '8', '9', '+', '/'};
  18. static char *decoding_table = NULL;
  19. static int mod_table[] = {0, 2, 1};
  20.  
  21. unsigned char *base64_decode(const char *data,
  22.                             size_t input_length,
  23.                             size_t *output_length);
  24. void build_decoding_table();
  25. void base64_cleanup();
  26.  
  27. int open_and_extract_from_eml(char *filename,char *path_destino);
  28. int isEmptyLine(char *line);
  29. char *content_disposition = "Content-Disposition: attachment;";
  30.  
  31. int main(int argc, char **argv ) {
  32. if(argc != 3) {
  33. printf("Uso: %s <Carpeta_con_EMLs> <Carpeta_destino_adjuntos>\n",argv[0]);
  34. exit(0);
  35. }
  36. open_and_extract_from_eml(argv[1],argv[2]);
  37. return 0;
  38. }
  39.  
  40. int  open_and_extract_from_eml(char *filename,char *path_destino) {
  41. FILE *eml_file, *temp_file;
  42. char *dest_file,*temp0,*temp1;
  43. char *line,*buffer_base64 = NULL,*buffer_decoded;
  44. char *full_writen_file;
  45. int len_dest_file_name,offset,len_content_disposition,len_base64_line,len_base64_buffer, len_output,len_path_destino,entrar;
  46. len_content_disposition = strlen(content_disposition);
  47. len_path_destino = strlen(path_destino);
  48. line = malloc(1024);
  49. eml_file = fopen(filename,"rb");
  50. offset = 0;
  51. while(!feof(eml_file) && fgets(line,1024,eml_file) != NULL) {
  52. if(memcmp(line,content_disposition,len_content_disposition) == 0) {
  53. printf("Encontrado: %s",line);
  54. temp0 = strstr(line,"filename=");
  55. if(temp0 ==NULL ) {
  56. //tal vez la proxima linea?
  57. memset(line,0,1024);
  58. fgets(line,1024,eml_file);
  59. }
  60.  
  61. temp0 = strstr(line,"filename=");
  62. if(temp0 !=NULL ) {
  63. temp1 = strstr(temp0 +10,"\"");
  64. if(temp1 == NULL) {
  65. //No hay " finales
  66. exit(0);
  67. }
  68. len_dest_file_name = temp1 - (line + (temp0 - line) + 10 );
  69. //printf("len_dest_file_name %i\n",len_dest_file_name);
  70. dest_file = malloc(len_dest_file_name+1);
  71. strncpy(dest_file,(line + (temp0 - line) + 10),len_dest_file_name);
  72. dest_file[len_dest_file_name] = '\0';
  73.  
  74. memset(line,0,1024);
  75. fgets(line,1024,eml_file);
  76. //printf("Nueva linea leida \"%s\"",line);
  77. if(!isEmptyLine(line)) {
  78. //Deberia de ser una linea vacia;
  79. exit(0);
  80. }
  81. buffer_base64 = NULL;
  82. offset = 0;
  83. memset(line,0,1024);
  84. entrar = 1;
  85. while(entrar && fgets(line,1024,eml_file) != NULL &&  !isEmptyLine(line) ) { //leemos hasta la proxima linea vacia o hasta encontrar un '=' al final de la linea
  86. len_base64_line = strlen(line);
  87. buffer_base64 = realloc(buffer_base64,offset+len_base64_line+1);
  88. if(line[len_base64_line-1] == '\n'  || line[len_base64_line-1] == '\r'){
  89. line[len_base64_line-1] ='\0';
  90. len_base64_line--;
  91. }
  92. if(line[len_base64_line-1] == '\n'  || line[len_base64_line-1] == '\r'){
  93. line[len_base64_line-1] ='\0';
  94. len_base64_line--;
  95. }
  96.  
  97. memcpy(buffer_base64+offset,line,len_base64_line);
  98. offset+=len_base64_line;
  99. if(line[len_base64_line-1] == '=') {
  100. entrar = 0;
  101. }
  102. memset(line,0,1024);
  103. }
  104. buffer_base64[offset] = '\0';
  105. //printf("Encoded buffer: %s\n",buffer_base64);
  106. len_base64_buffer = strlen(buffer_base64);
  107. buffer_decoded = base64_decode(buffer_base64,len_base64_buffer,&len_output);
  108. buffer_decoded[len_output] = '\0';
  109. /*
  110. printf("OK\n");
  111. printf("Decoded buffer: %s\n",buffer_decoded);
  112. printf("Path destino: %s\n",path_destino);
  113. printf("len_dest_file_name: %i\n",len_dest_file_name);
  114. printf("len_path_destino: %i\n",len_path_destino);
  115. */
  116. full_writen_file = malloc(len_dest_file_name + len_path_destino+10);
  117. sprintf(full_writen_file,"%s/%s",path_destino,dest_file);
  118. printf("Destino: %s\n",full_writen_file);
  119. temp_file = fopen(full_writen_file,"wb");
  120. fwrite(buffer_decoded,1,len_output,temp_file);
  121. fclose(temp_file);
  122.  
  123. free(buffer_base64);
  124. free(dest_file);
  125. free(full_writen_file);
  126. }
  127. else {
  128. printf("Se encontro %s, pero no se encontro Filename omitiendo!\n",content_disposition);
  129. }
  130. }
  131. memset(line,0,1024);
  132. }
  133. free(line);
  134. }
  135.  
  136. int isEmptyLine(char *line) {
  137. if(line[0] == '\0' || line[0] == '\n' || line[0] == '\r')
  138. return 1;
  139. return 0;
  140. }
  141.  
  142. unsigned char *base64_decode(const char *data,
  143.                             size_t input_length,
  144.                             size_t *output_length) {
  145.  
  146.    if (decoding_table == NULL) build_decoding_table();
  147.  
  148.    if (input_length % 4 != 0) return NULL;
  149.  
  150.    *output_length = input_length / 4 * 3;
  151.    if (data[input_length - 1] == '=') (*output_length)--;
  152.    if (data[input_length - 2] == '=') (*output_length)--;
  153.  
  154.    unsigned char *decoded_data = malloc(*output_length);
  155.    if (decoded_data == NULL) return NULL;
  156.  
  157.    for (int i = 0, j = 0; i < input_length;) {
  158.  
  159.        uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
  160.        uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
  161.        uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
  162.        uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
  163.  
  164.        uint32_t triple = (sextet_a << 3 * 6)
  165.        + (sextet_b << 2 * 6)
  166.        + (sextet_c << 1 * 6)
  167.        + (sextet_d << 0 * 6);
  168.  
  169.        if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
  170.        if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
  171.        if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
  172.    }
  173.  
  174.    return decoded_data;
  175. }
  176.  
  177. void build_decoding_table() {
  178.    decoding_table = malloc(256);
  179.    for (int i = 0; i < 64; i++)
  180.        decoding_table[(unsigned char) encoding_table[i]] = i;
  181. }
  182.  
  183.  
  184. void base64_cleanup() {
  185.    free(decoding_table);
  186. }

El programa lo puedes utilizar para todo un directorio pero con ayuda de batch creo recordar que existe una instrucción for que te ayuda a procesar todos los archivos de un subdirectorio y pasarlos a un programa.

Saludos!


Título: Re: extraer adjuntos de correos EML
Publicado por: adla en 11 Noviembre 2020, 09:05 am
hola, muchas gracias por todo, pero no consigo que me extraiga el adjunto..

(http://www.franci.es/tmp/eml-no.jpg)

no aparece la imagen adjunta, esta aqui http://www.franci.es/tmp/eml-no.jpg


Título: Re: extraer adjuntos de correos EML
Publicado por: Danielㅤ en 11 Noviembre 2020, 13:49 pm
Hola, en el primer parámetro tenes que pasar un directorio y vos estás pasando un solo archivo, tenés que indicar un directorio donde estén todos esos archivos que querés procesar.

Además el segundo parámetro le estás indicando una unidad como ubicación pero no una carpeta y es recomendable que crees una carpeta para alojar todos los archivos destinos, por ejemplo el comando podría ser:

Código:
"D:\agua o cocacola" "D:\Adjuntos de correos EML"


Saludos


Título: Re: extraer adjuntos de correos EML
Publicado por: AlbertoBSD en 11 Noviembre 2020, 15:07 pm
hola, muchas gracias por todo, pero no consigo que me extraiga el adjunto..

Que tal ya veo algo no esta bien pero no puedo saber que es si no veo el eml que le pasas, si gustas puedes mandarme el EML a mi correo, mi informacion esta por ahi publica


Título: Re: extraer adjuntos de correos EML
Publicado por: adla en 12 Noviembre 2020, 11:15 am

Hola, en el primer parámetro tenes que pasar un directorio y vos estás pasando un solo archivo, tenés que indicar un directorio donde estén todos esos archivos que querés procesar.

Además el segundo parámetro le estás indicando una unidad como ubicación pero no una carpeta y es recomendable que crees una carpeta para alojar todos los archivos destinos, por ejemplo el comando podría ser:

Código:
"D:\agua o cocacola" "D:\Adjuntos de correos EML"


Saludos

no le paso la ruta porque el ejecutable y el archivo estan en la misma carpeta de hecho lo encuentra. He probado poniendo la ruta entera, con la carpeta creada, con la misma carpeta de entrada y con todo lo que se me ha pasado por la cabeza pero he subido solo una imagen. Gracias, Saludos


Título: Re: extraer adjuntos de correos EML
Publicado por: AlbertoBSD en 14 Noviembre 2020, 06:28 am
No se si todos tus eml tengan algún detalle, uno de ellos como te comente por correo estaba "dañado", se supone que deberia de estar X cantidad de información en una línea y en tu archivo tenia un salto de linea en medio eso colgó el programa.

Ya funciona para los ejemplos que me pasaste mira las imágenes

(https://albertobsd.dev/uploads/1605331471_eml_dump_salida_4.png)

(https://albertobsd.dev/uploads/1605331457_eml_dump_salida_3.png)

El codigo esta actualizado en el post donde lo publique, en este mismo Hilo.

Saludos


Título: Re: extraer adjuntos de correos EML
Publicado por: adla en 16 Noviembre 2020, 19:54 pm
No se si todos tus eml tengan algún detalle, uno de ellos como te comente por correo estaba "dañado", se supone que deberia de estar X cantidad de información en una línea y en tu archivo tenia un salto de linea en medio eso colgó el programa.

Ya funciona para los ejemplos que me pasaste mira las imágenes

(https://albertobsd.dev/uploads/1605331471_eml_dump_salida_4.png)

(https://albertobsd.dev/uploads/1605331457_eml_dump_salida_3.png)

El codigo esta actualizado en el post donde lo publique, en este mismo Hilo.

Saludos


hola, gracias por todo, lo he compilado pero cuando lo ejecuto se rompe y da este error, no sé si será un problema puntual de mi máquina..

Firma con problemas:
  Nombre del evento de problema:   APPCRASH
  Nombre de la aplicación:   extrae_eml.exe
  Versión de la aplicación:   0.0.0.0
  Marca de tiempo de la aplicación:   5fb22c7c
  Nombre del módulo con errores:   extrae_eml.exe
  Versión del módulo con errores:   0.0.0.0
  Marca de tiempo del módulo con errores:   5fb22c7c
  Código de excepción:   c0000005
  Desplazamiento de excepción:   000018fd
  Versión del sistema operativo:   6.1.7601.2.1.0.256.48
  Id. de configuración regional:   3082
  Información adicional 1:   0a9e
  Información adicional 2:   0a9e372d3b4ad19135b953a78882e789
  Información adicional 3:   0a9e
  Información adicional 4:   0a9e372d3b4ad19135b953a78882e789

Lea nuestra declaración de privacidad en línea:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0c0a

Si la declaración de privacidad en línea no está disponible, lea la declaración de privacidad sin conexión:
  C:\Windows\system32\es-ES\erofflps.txt


Título: Re: extraer adjuntos de correos EML
Publicado por: adla en 16 Noviembre 2020, 20:35 pm
creo que se produce porque hay caracteres raros bien en el archivo.eml o bien en el archivo embebido..