2009-02-02 6 views
6

Wir müssen Received: E-Mail-Header nach RFC 5321 analysieren. Wir müssen Domain \ IPs extrahieren, durch die die Mail durchlaufen wurde. Auch müssen wir herausfinden, ob eine IP eine interne IP ist. Gibt es schon eine Bibliothek, die besonders in C \ C++ helfen kann?Parsing E-Mail "Received:" Header

Zum Beispiel

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) 

Wir brauchen den "von" Server zu extrahieren.

dank

+0

Sie erkennen, dass Sie sich nicht auf Received Header mit Ausnahme vielleicht der letzte Richtigkeit zählen kann, nicht wahr? –

Antwort

-2

Es ist nicht schwierig ist, solche Header, auch manuell line-by-line zu analysieren. Ein Regex könnte helfen, indem Sie by\s+(\w)+\( betrachten. Für C++ könnten Sie das library oder that one versuchen.

+1

Header können mehrzeilig sein –

1

Sie wollen Reguläre Ausdrücke verwenden, möglicherweise

(? < = by). * (? = Mit)

Dies wird Ihnen pilot01.cl.msu.edu (8.10.2/8.10.2)

Edit: Ich finde es amüsant, dass dies geändert wurde, wenn es tatsächlich bekommt, was das OP verlangt.

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(); 

ich nicht behaupten, dass es abgeschlossen war, aber frage mich, ob die Person, die es gab eine -1 sogar versucht. Meh ..

+0

Für zusätzliche Unterhaltung, überprüfen Sie ein paar Nachrichten in Ihrem Posteingang. Wahrscheinlich werden Sie ein halbes Dutzend allgemein gebräuchlicher Muster entdecken. Nur mit dem einzigen Beispiel in der Frage fertig zu werden, bringt dich nicht sehr weit. – tripleee

+0

@tripleee Sie wissen, was ich noch amüsanter finde, etwas im Jahr 2017 zu lesen, auf einen Kommentar, den Sie im Jahr 2016 gemacht haben von einem Beitrag, den ich im Jahr 2009 gemacht habe. 10/10 würde noch einmal antworten – kd7

-2

Haben Sie in Betracht gezogen, regular expressions zu verwenden?

ist eine Liste von internen, nicht routbaren Adressbereichen.

2

vmime sollte in Ordnung, unbefriedigend jede Mail-Bibliothek wird Ihnen dies ermöglichen.

0

Sie können reguläre Ausdrücke verwenden. Es würde wie folgt aussehen (nicht getestet):

#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'; 

Check ist ein Makro, das Sie helfen herauszufinden, ob es irgendwelche Probleme gibt:

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

Das Format von ‚Received‘ Linien verwendet wird definiert in RFC 2821 und Regex können es nicht analysieren.

(Sie können trotzdem versuchen, und für eine begrenzte Teilmenge von Headern durch bekannte Software erzeugen Sie Erfolg haben könnten, aber wenn man diese auf den Bereich von seltsamen Sachen befestigen in der realen Welt gefunden Mail wird es scheitern.)

Verwenden Sie einen vorhandenen RFC 2821-Parser und Sie sollten in Ordnung sein, aber ansonsten sollten Sie einen Fehler erwarten und die Software schreiben, um damit fertig zu werden. Machen Sie nichts Wichtiges wie ein Sicherheitssystem darum herum.

Wir müssen den "by" Server extrahieren.

'von' ist eher zu verwenden.Der in einer Zeile "by" angegebene Hostname wird vom Host selbst gesehen. Daher gibt es keine Garantie dafür, dass es sich um einen öffentlich auflösbaren FQDN handelt. Und natürlich tendierst du dort nicht dazu, gültig zu werden (TCP-Info).

3

Es gibt einen Perl Received module, der eine Verzweigung des SpamAssassin-Codes ist. Es gibt einen Hash für einen Received Header mit den relevanten Informationen zurück. Zum Beispiel

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

Dies ist die einzige Antwort hier, die sogar versucht zu bewältigen mit mehr als einer winzigen Teilmenge der Received: Header-Formate, die allgemein verwendet werden. Atmen Sie tief durch, bevor Sie versuchen, den Code zu lesen, aber es ist nicht schön. – 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

Sie sollten diesen Code wahrscheinlich etwas erklären. – StephenTG