Разбор электронной почты "Получено:" заголовки - PullRequest
8 голосов
/ 02 февраля 2009

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

Например,

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)

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

спасибо

Ответы [ 8 ]

5 голосов
/ 02 февраля 2009

Формат, используемый строками 'Received', определен в RFC 2821, и регулярное выражение не может его проанализировать.

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

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

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

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

4 голосов
/ 10 февраля 2012

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

{ ip => '64.12.136.4', 
  id => '875522', 
  by => 'xxx.com',
  helo => 'imo-m01.mx.aol.com' }
2 голосов
/ 02 февраля 2009

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

1 голос
/ 02 февраля 2009

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

(? <= BY). * (? = С) </p>

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

Edit: Я нахожу забавным, что это было модернизировано, когда оно фактически получает то, о чем просил ОП.

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. Мех ..

0 голосов
/ 19 августа 2013
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");

}
0 голосов
/ 02 февраля 2009

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

#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 - это макрос, который поможет вам выяснить, есть ли какие-либо проблемы:

#define check(condition, description) if (condition) { fprintf(stdout, "%s:%i - %s - %s\n", __FILE__, __LINE__, description, strerror(errno)); exit(1); }
0 голосов
/ 02 февраля 2009

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

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

0 голосов
/ 02 февраля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...