2009-02-02 108 views
6

根据RFC 5321,我们需要解析Received:电子邮件标题。我们需要提取邮件已遍历的域\ IP。此外,我们需要确定IP是否为内部IP。是否已经有一个库可以帮助您,特别是在C \ C++中。解析电子邮件“Received:”标题

例如,

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

你一定要明白,你不能对任何接收头数也许除了最后一个是正确的,对不对? – 2009-02-02 17:57:29

回答

-2

不难解析这样的头部,甚至手动线由行。正则表达式可以通过查看by\s+(\w)+\(来实现。对于C++,您可以尝试使用librarythat one

+1

标题可以多行 – 2010-06-18 12:52:19

1

你要使用正则表达式可能

(?< =通过)。*(?=含)

这会给你pilot01.cl.msu.edu(8.10.2/8.10.2)

编辑: 我觉得这很有趣,当它实际上得到了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(); 

我没有声称它是完整的,但如果把它的人-1甚至试图想知道。呃..

+0

如需更多娱乐信息,请查看收件箱中的一些消息。有可能你会发现六种常用模式。只是在问题中处理单个示例并不能让你走得很远。 – tripleee 2016-02-08 10:43:40

+0

@tripleee你知道我发现什么更有趣,2017年阅读了一些东西,关于你在2016年从我在2009年发布的帖子所做的评论。10/10会再次回答 – kd7 2017-10-27 00:57:24

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

通过“收到”线所使用的格式定义的RFC 2821和正则表达式无法解析它。

(你可以想试试,并通过你可能会成功的已知软件制作标题的有限的子集,但是当你连接这奇怪的东西,在现实世界中发现的范围邮件就会失败。)

使用现有的RFC 2821解析器,您应该可以,但否则您应该期望失败,并编写软件以应对此问题。不要将任何重要的安全系统作为基础。

我们需要提取“by”服务器。

'from'更有可能被使用。'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 2016-02-08 10:44:51

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

}