我们需要根据RFC 5321解析Received:
电子邮件标头。我们需要提取邮件已遍历的域\ 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”服务器。
感谢
答案 0 :(得分:5)
“已接收”行使用的格式在RFC 2821中定义,正则表达式无法解析它。
(无论如何,您可以尝试,对于由已知软件生成的有限的标题子集,您可能会成功,但当您将其附加到真实邮件中发现的奇怪内容时,它将会失败。)
使用现有的RFC 2821解析器,你应该没问题,否则你应该期望失败,并编写软件来应对它。不要像安全系统那样重要的东西。
我们需要提取“by”服务器。
'from'更有可能被使用。 “by”行中给出的主机名是由主机本身看到的,因此无法保证它将是一个可公开解析的FQDN。当然,你不会在那里获得有效的(TCP-Info)。
答案 1 :(得分:4)
有一个Perl Received module,它是SpamAssassin代码的一个分支。它返回带有相关信息的Received
标头的哈希值。例如
{ ip => '64.12.136.4',
id => '875522',
by => 'xxx.com',
helo => 'imo-m01.mx.aol.com' }
答案 2 :(得分:2)
vmime应该没问题,任何邮件库都可以让你这么做。
答案 3 :(得分: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的人甚至尝试过。 MEH ..
答案 4 :(得分: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';
check是一个宏,可以帮助您确定是否存在任何问题:
#define check(condition, description) if (condition) { fprintf(stdout, "%s:%i - %s - %s\n", __FILE__, __LINE__, description, strerror(errno)); exit(1); }
答案 5 :(得分: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");
}
答案 6 :(得分:-2)
答案 7 :(得分:-2)
您是否考虑过使用regular expressions?
Here是一个内部的,不可路由的地址范围列表。