2009-02-02 39 views
6

Chúng tôi cần phân tích Received: tiêu đề email theo RFC 5321. Chúng tôi cần trích xuất các miền \ IP mà qua đó thư đã đi qua. Ngoài ra, chúng tôi cần tìm hiểu xem IP có phải là IP nội bộ hay không. Đã có một thư viện có thể giúp đỡ, đặc biệt là trong C \ C++.Email phân tích cú pháp "Đã nhận:" tiêu đề

Ví dụ,

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) 

Chúng ta cần phải giải nén "bởi" máy chủ.

cảm ơn

+0

Bạn nhận ra rằng bạn không thể dựa vào bất kỳ tiêu đề nhận ngoại trừ có lẽ là người cuối cùng là đúng, phải không? –

Trả lời

-2

Không khó để phân tích cú pháp tiêu đề như vậy, thậm chí theo từng dòng một cách thủ công. Một regex có thể trợ giúp bằng cách xem by\s+(\w)+\(. Đối với C++, bạn có thể thử rằng library hoặc that one.

+1

Tiêu đề có thể nhiều dòng –

1

Bạn sẽ muốn sử dụng Regular Expressions thể

(? < = bằng). * (= Với)

này sẽ cung cấp cho bạn pilot01.cl.msu.edu (8.10.2/8.10.2)

Chỉnh sửa: Tôi thấy thật thú vị khi điều này được sửa đổi khi thực sự nhận được những gì OP yêu cầu.

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

tôi didnt tuyên bố rằng nó đã được hoàn tất, nhưng tôi tự hỏi nếu người đó đã cho nó một -1 thậm chí đã cố gắng. Meh ..

+0

Để giải trí thêm, hãy kiểm tra một vài thư trong hộp thư đến của bạn. Rất có thể bạn sẽ khám phá ra một nửa tá mẫu sử dụng phổ biến. Chỉ cần đối phó với ví dụ duy nhất trong câu hỏi không giúp bạn đi xa. – tripleee

+0

@tripleee bạn biết những gì tôi thấy thú vị hơn, đọc một cái gì đó vào năm 2017, trên một bình luận bạn đã thực hiện trong năm 2016 từ một bài đăng tôi thực hiện trong năm 2009. 10/10 sẽ trả lời một lần nữa – kd7

-2

Bạn đã cân nhắc sử dụng regular expressions?

Here là danh sách các dải địa chỉ nội bộ, không thể định tuyến.

2

vmime sẽ ổn, không có bất kỳ thư viện thư nào cho phép bạn thực hiện điều đó.

0

Bạn có thể sử dụng cụm từ thông dụng. Nó sẽ giống như thế này (không kiểm tra):

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

kiểm tra là một vĩ mô để giúp bạn tìm ra nếu có bất kỳ vấn đề:

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

Định dạng được sử dụng bởi dòng 'nhận' được định nghĩa trong RFC 2821 và regex không thể phân tích cú pháp.

(Bạn có thể thử dù sao, và cho một tập hợp con hạn chế về tiêu đề được tạo ra bởi phần mềm được biết bạn có thể thành công, nhưng khi bạn đính kèm này đến phạm vi của những thứ kỳ lạ được tìm thấy trong thực tế mail nó sẽ thất bại.)

Sử dụng trình phân tích cú pháp RFC 2821 hiện có và bạn nên OK, nhưng nếu không bạn sẽ gặp sự cố và viết phần mềm để đối phó với nó. Không căn cứ bất cứ điều gì quan trọng như một hệ thống an ninh xung quanh nó.

Chúng tôi cần trích xuất máy chủ "theo".

'từ' có nhiều khả năng được sử dụng hơn.Tên máy chủ được đưa ra trong một dòng 'by' được xem bởi chính máy chủ, vì vậy không có gì đảm bảo rằng nó sẽ là một FQDN có thể phân giải công khai. Và tất nhiên bạn không có xu hướng để có được hợp lệ (TCP-Info) ở đó.

3

Có một Perl Received module là một nhánh của mã SpamAssassin. Nó trả về giá trị băm cho tiêu đề Received với thông tin có liên quan. Ví dụ

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

Đây là câu trả lời duy nhất ở đây mà thậm chí cố gắng để đối phó với nhiều hơn một tập hợp con nhỏ của các định dạng tiêu đề Đã nhận: sử dụng phổ biến. Hít thật sâu trước khi cố gắng đọc mã, mặc dù - nó không đẹp. – 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

Bạn có lẽ nên đưa ra một chút giải thích về mã này. – StephenTG

Các vấn đề liên quan