2009-02-02 2 views
6

Нам нужно разобрать Received: заголовки электронной почты в соответствии с RFC 5321. Нам нужно извлечь домен \ IP, через который была пройдена почта. Также нам нужно выяснить, является ли IP внутренним IP-адресом. Есть ли уже библиотека, которая может помочь, особенно в C \ C++.Разбор электронной почты «Received:» headers

Например,

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) 

Мы должны извлечь "с помощью" сервер.

благодаря

+0

Вы понимаете, что вы не можете рассчитывать на любые Received заголовки, за исключением, может быть, последний из которых является правильным, верно? –

ответ

-2

Это не трудно разобрать такие заголовки, даже вручную строка за строкой. Регулярное выражение могло помочь там, посмотрев на by\s+(\w)+\(. Для C++ вы можете попробовать это library или that one.

+1

Заголовки могут быть многострочными –

1

Вы хотите использовать регулярные выражения, возможно,

(? < = от). * (? = С)

Это даст вам pilot01.cl.msu.edu (8.10.2/8.10.2)

Редактировать: Мне показалось забавным, что это было изменено, когда оно фактически получило то, о чем попросил ОП.

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

я не утверждаю, что это был полной, но мне интересно, если человек, который дал ему -1 даже пытался. Meh ..

+0

Для дополнительного развлечения просмотрите несколько сообщений в папке «Входящие». Скорее всего, вы откроете для себя полдюжины моделей. Просто справиться с одним примером в вопросе не очень далеко. – tripleee

+0

@tripleee, вы знаете, что я нахожу еще более забавным, читаю что-то в 2017 году, на комментарий, сделанный вами в 2016 году из поста, который я сделал в 2009 году. 10/10 ответит снова – kd7

-2

Считаете ли вы использование regular expressions?

Here - это список внутренних, немаршрутизированных диапазонов адресов.

2

vmime должно быть в порядке, бездействия любая почтовая библиотека позволит вам это сделать.

0

Вы можете использовать регулярные выражения. Это будет выглядеть следующим образом (не проверено):

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

проверка макросы, чтобы помочь вам понять, если есть какие-либо проблемы:

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

формат, используемый «Received» линий, определенные в RFC 2821 и regex не могут его проанализировать.

(Вы можете попробовать в любом случае, и для ограниченного подмножества заголовков, полученных известным программным обеспечением вы можете добиться успеха, но когда вы приложите это к ряду странных вещей, найденного в реальном мире по почте он не сможет.)

Используйте существующий анализатор RFC 2821, и вы должны быть в порядке, но в противном случае вы должны ожидать отказа и написать программное обеспечение, чтобы справиться с ним. Не создавайте ничего важного, как система безопасности вокруг него.

Нам нужно извлечь сервер «by».

«от», скорее всего, будет полезен.Имя хоста, указанное в строке 'by', рассматривается самим хостом, поэтому нет гарантии, что это будет полное разрешаемое FQDN. И, конечно же, вы не склонны к действию (TCP-Info).

3

Существует Perl Received module, который является вилкой кода SpamAssassin. Он возвращает хеш для заголовка Received с соответствующей информацией. Например

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

Это единственный ответ здесь, который даже пытается справиться с более чем небольшим подмножеством форматов заголовков Received:. Сделайте глубокий вдох, прежде чем пытаться прочитать код, хотя - это некрасиво. – 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

Возможно, вы должны дать немного объяснения этому коду. – StephenTG

Смежные вопросы