2009-02-02 26 views
6

Tenemos que analizar los encabezados de correo electrónico Received: de acuerdo con RFC 5321. Necesitamos extraer dominio \ IP a través del cual se ha cruzado el correo. También debemos determinar si una IP es una IP interna. ¿Ya hay una biblioteca que puede ayudar, especialmente en C \ C++?Correo electrónico de análisis "Recibido:" encabezados

Por ejemplo,

Received: from server.mymailhost.com (mail.mymailhost.com [126.43.75.123]) 
    by pilot01.cl.msu.edu (8.10.2/8.10.2) with ESMTP id NAA23597; 
    Fri, 12 Jul 2002 16:11:20 -0400 (EDT) 

Tenemos que extraer el servidor "por".

gracias

+0

Te das cuenta de que no se puede contar con cualquiera de las cabeceras recibidos, excepto tal vez el último de los cuales correcta, ¿verdad? –

Respuesta

-2

No es difícil de analizar dichas cabeceras, incluso manualmente, línea por línea. Una expresión regular podría ayudar allí al mirar by\s+(\w)+\(. Para C++, puede intentar eso library o that one.

+1

Los encabezados pueden ser multilínea –

1

Usted querrá utilizar expresiones regulares posiblemente

(? = < por). * (? = Con)

Esto le dará pilot01.cl.msu.edu (8.10.2/8.10.2)

Edit: Me resulta divertido que esto se modificó cuando realmente obtiene lo que pidió el OP.

C#:

string header = "Received: from server.mymailhost.com (mail.mymailhost.com [126.43.75.123]) by pilot01.cl.msu.edu (8.10.2/8.10.2) with ESMTP id NAA23597; Fri, 12 Jul 2002 16:11:20 -0400 (EDT)"; 
     System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex(@"(?<=by).*(?=with)"); 
     System.Text.RegularExpressions.Match m = r.Match(header); 
     Console.WriteLine(m.Captures[0].Value); 
     Console.ReadKey(); 

yo no pretendo que era completa, pero estoy preguntando si la persona que le dio un -1 incluso trató. Meh ..

+0

Para entretenimientos adicionales, examine algunos mensajes en su bandeja de entrada. Lo más probable es que descubra media docena de patrones de uso común. Solo lidiar con el único ejemplo en la pregunta no te lleva muy lejos. – tripleee

+0

@tripleee sabes lo que encuentro aún más entretenido, leyendo algo en 2017, en un comentario que hiciste en 2016 de una publicación que hice en 2009. 10/10 respondería de nuevo – kd7

2

vmime debería estar bien, más aún cualquier biblioteca de correo le permitirá hacer eso.

0

Puede usar expresiones regulares. Se vería así (no probado):

#include <regex.h> 

regex_t *re = malloc(sizeof(regex_t)); 

const char *restr = "by ([A-Za-z.]+) \(([^\)]*)\)"; 

check(regcomp(re, restr, REG_EXTENDED | REG_ICASE), "regcomp"); 

size_t nmatch = 1; 

regmatch_t *matches = malloc(sizeof(regmatch_t) * nmatch); 

int ret = regexec(re, YOUR_STRING, nmatch, matches, 0); 

check(ret != 0, "regexec"); 

int size; 

size = matches[2].rm_eo - matches[2].rm_so; 
char *host = malloc(sizeof(char) * size); 
strncpy(host, YOUR_STRING + matches[2].rm_so, size); 
host[size] = '\0'; 

size = matches[3].rm_eo - matches[3].rm_so; 
char *ip = malloc(sizeof(char) * size); 
strncpy(ip, YOUR_STRING + matches[3].rm_so, size); 
ip[size] = '\0'; 

cheque es una macro para ayudar a determinar si hay algún problema:

#define check(condition, description) if (condition) { fprintf(stdout, "%s:%i - %s - %s\n", __FILE__, __LINE__, description, strerror(errno)); exit(1); } 
4

El formato utilizado por las líneas 'Recibido' se definen en RFC 2821, y regex no puede analizarlo.

(Puede intentarlo de todos modos, y para un subconjunto limitado de encabezados producidos por el software conocidos que puede tener éxito, pero cuando se conecta esto a la gama de cosas extrañas que se encuentra en el mundo real por correo fallará.)

Utilice un analizador RFC 2821 existente y debería estar bien, pero de lo contrario debería esperar una falla y escribir el software para hacer frente a esto. No base nada importante como un sistema de seguridad a su alrededor.

Tenemos que extraer el servidor "por".

'de' es más probable que sea de uso.El nombre de host dado en una línea 'por' es como lo ve el propio host, por lo que no hay garantía de que sea un FQDN que se pueda resolver públicamente. Y, por supuesto, no tiende a ser válido (TCP-Info) allí.

3

Hay un Perl Received module que es un tenedor del código SpamAssassin. Devuelve un hash para un encabezado Received con la información relevante. Por ejemplo

{ ip => '64.12.136.4', 
    id => '875522', 
    by => 'xxx.com', 
    helo => 'imo-m01.mx.aol.com' } 
+0

Esta es la única respuesta aquí que incluso intenta hacer frente con más de un subconjunto minúsculo de los formatos Received: header de uso común. Respira hondo antes de intentar leer el código, aunque no es bonito. – tripleee

0
typedef struct mailHeaders{ 
    char name[100]; 
    char value[2000]; 
}mailHeaders; 

int header_count = 0; 
mailHeaders headers[30]; // A struct to hold the name value pairs 

char *GetMailHeader(char *name) 
{ 
    char *value = NULL;; 
    int i; 

    for(i=0;i<header_count;i++){ 
     if(strcmp(name,headers[i].name) == 0){ 
      value = headers[i].value; 
      break; 
     } 
    } 
    return(value); 
} 


void ReadMail(void) 
{ 

    //Loop through the email message line by line to separate the headers. Then save the name value pairs to a linked list or struct. 
      char *Received = NULL // Received header 
    char *mail = NULL; // Buffer that has the email message. 
    char *line = NULL; // A line of text in the email. 
    char *name = NULL; // Header name 
    char *value = NULL; // Header value 

    int index = -1;  // Header index 


    memset(&headers,'\0',sizeof(mailHeaders)); 

    line = strtok(mail,"\n"); 
    while(line != NULL) 
    { 

     if(*line == '\t') // Tabbed headers 
     { 
      strcat(headers[index].value,line); // Concatenate the tabbed values 
     } 
     else 
     { 
      name = line; 
      value = strchr(line,':'); // Split the name value pairs. 
      if(value != NULL) 
      { 
       *value='\0'; // NULL the colon 
       value++;  // Move the pointer past the NULL character to separate the name and value 
       index++; 
       strcpy(headers[index].name,name); // Copy the name to the data structure 
       strcpy(headers[index].value,value); // Copy the value to the data structure 
      } 

     } 

     if(*line == '\r') // End of headers 
      break; 

     line = strtok(NULL,"\n"); // Get next header 
     header_count = index; 
    } 

      Received = GetMailHeader("Received"); 

} 
+2

Probablemente deberías dar un poco de explicación de este código. – StephenTG

Cuestiones relacionadas