#include "mail_decoder_util.h" #include "mail_decoder_module.h" #include "mail_decoder_email.h" #include "stellar/mq.h" #include "stellar/module.h" int is_eml_header_field(enum EML_LINE_TYPE field) { switch (field) { case EML_DATA_HEAD_IN: case EML_DATA_FROM: case EML_DATA_TO: case EML_DATA_CC: case EML_DATA_BCC: case EML_DATA_SUBJECT: case EML_DATA_RETURN_PATH: case EML_DATA_DELIVERED_TO: case EML_DATA_RECEIVED: case EML_DATA_DATE: case EML_DATA_REPLY_TO: return 1; default: break; } return 0; } static int process_srcdata_r(char **p_srcdata,int *p_srclen,char **output_line,int *plinelen,struct email_parser * eml_parser) { int len; char *poss_n = NULL; char *srcdata = *p_srcdata; int srclen = *p_srclen; poss_n = (char *)memchr(srcdata, '\n', srclen); if(poss_n != NULL && poss_n >= srcdata + srclen) { poss_n = NULL; } if(poss_n == NULL || poss_n + 1 >= srcdata + srclen) //�����Զ϶����۵��У��������� { while(eml_parser->pDataLineBuf.len >0 && (*((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len-1)=='\r' || *((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len-1)=='\n')) eml_parser->pDataLineBuf.len--; if(buf_cache_check_size(&eml_parser->pDataLineBuf, srclen)<0) { return MAIL_GETLINE_ERR; } memcpy((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len, srcdata, srclen); eml_parser->pDataLineBuf.len += srclen; return MAIL_INPUT_END; } else if(*(poss_n+1) != '\t' && *(poss_n+1) != ' ') //a fold line { len = poss_n - srcdata + 1; //�������з����� eml_parser->iDataPointer += len; if(eml_parser->pDataLineBuf.len > 0) { while(eml_parser->pDataLineBuf.len >0 && (*((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len-1)=='\r' || *((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len-1)=='\n')) eml_parser->pDataLineBuf.len--; if(buf_cache_check_size(&eml_parser->pDataLineBuf, len)<0) { return MAIL_GETLINE_ERR; } memcpy((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len, srcdata, len); eml_parser->pDataLineBuf.len += len; *output_line = (char *)eml_parser->pDataLineBuf.buf; *plinelen = eml_parser->pDataLineBuf.len; } else { *output_line = srcdata; *plinelen = len; } return MAIL_FOLD_LINE_END; } else //δ�ҵ����з������۵��У�����֮ { len = poss_n - srcdata + 1; while(eml_parser->pDataLineBuf.len>0 && (*((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len-1)=='\r' || *((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len-1)=='\n')) eml_parser->pDataLineBuf.len--; if(buf_cache_check_size(&eml_parser->pDataLineBuf, len)<0) { return MAIL_GETLINE_ERR; } memcpy((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len, srcdata, len); eml_parser->pDataLineBuf.len += len; srcdata += len; srclen -= len; eml_parser->iDataPointer += len; *p_srcdata = srcdata; *p_srclen = srclen; return MAIL_FOLD_LINE_START; } } int get_one_tcpline(struct email_parser * eml_parser, char *srcdata,int srclen,char **output_line,int *plinelen, int rn) { char *pos_n = NULL; int datalen; pos_n = (char *)memchr(srcdata, '\n', srclen); if(pos_n == NULL) //ֱ�ӻ��棬���ܴ�С����һ�л�û�����ꣻ { if(buf_cache_check_size(&eml_parser->pDataLineBuf, srclen)<0) { *output_line = (char *)eml_parser->pDataLineBuf.buf; *plinelen = eml_parser->pDataLineBuf.len; return MAIL_LINE_END; } memcpy((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len, srcdata, srclen); eml_parser->pDataLineBuf.len += srclen; eml_parser->iDataPointer += srclen; return MAIL_INPUT_END; } else //�ҵ���һ�������� { if(rn) { datalen = pos_n - srcdata + 1; eml_parser->iDataPointer += datalen; } else { datalen = pos_n - srcdata; eml_parser->iDataPointer += datalen + 1; //include \n } //��һ���������˲������ݣ������Ƚ���ƴ�� if(eml_parser->pDataLineBuf.len > 0) { if(buf_cache_check_size(&eml_parser->pDataLineBuf, datalen)<0) { *output_line = (char *)eml_parser->pDataLineBuf.buf; *plinelen = eml_parser->pDataLineBuf.len; eml_parser->iDataPointer -= rn?datalen:(datalen+1); return MAIL_LINE_END; } memcpy((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len, srcdata, datalen); eml_parser->pDataLineBuf.len += datalen; if(rn==0) { pos_n = (char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len - 1; if(*pos_n == '\r') //100% properly eml_parser->pDataLineBuf.len -= 1; } *output_line = (char *)eml_parser->pDataLineBuf.buf; *plinelen = eml_parser->pDataLineBuf.len; return MAIL_LINE_END; } if(rn==0 && datalen > 0) { if(*(srcdata+datalen-1) == '\r') datalen = datalen - 1; } *output_line = srcdata; *plinelen = datalen; return MAIL_LINE_END; } } static int get_complete_region(struct email_parser * eml_parser, char *srcdata,int srclen,char **output_line,int *plinelen) { char *pos_n = NULL; char *srcend = srcdata + srclen, *pc=srcdata; int datalen; //�ҽ�ֹ��: \r\n#, where # is '\r' or '-' while(pc < srcend && (pos_n = (char *)memchr(pc, '\n', srcend-pc)) != NULL) { eml_parser->iDataPointer += pos_n - pc + 1; pc = pos_n + 1; datalen = pc-srcdata; if(eml_parser->pDataLineBuf.len>0)//��ͷ�������ַ���������һ�β��������޻��� { if(buf_cache_check_size(&eml_parser->pDataLineBuf, datalen)<0) { *output_line = (char *)eml_parser->pDataLineBuf.buf; *plinelen = eml_parser->pDataLineBuf.len; eml_parser->iDataPointer -= datalen; return MAIL_LINE_END; } memcpy((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len, srcdata, datalen); eml_parser->pDataLineBuf.len += datalen; *output_line = (char *)eml_parser->pDataLineBuf.buf; *plinelen = eml_parser->pDataLineBuf.len; return MAIL_LINE_END; } //����BODY���¸�BOUNDARY֮�����û�п��У�����Ҫ�Ƚ�'-'�� //������"."��ǰ������������һ�������Ҫ��BODY�з������POP3������ //����')'��IMAP����Ϊ������ else if(pc < srcend && (*pc=='-' || (*pc=='.' && eml_parser->protocol!=MAIL_PROTOCOL_IMAP) || (*pc==')' && eml_parser->protocol==MAIL_PROTOCOL_IMAP))) //--BB\r\n)\r\n { *output_line = srcdata; *plinelen = datalen; return MAIL_LINE_END; } else if((srclen>=2 && *srcdata=='-' && *(srcdata+1)=='-') || ((pc-srcdata<=3) && (*srcdata=='.' || *srcdata==')'))) { *output_line = srcdata; *plinelen = datalen; return MAIL_LINE_END; } else if(pc-srcdata>=3 && *(pc-3)==')' && eml_parser->protocol==MAIL_PROTOCOL_IMAP) //')'֮ǰû�л��У�����һ��if���˳���ܱ䣬��Ϊ')'֮ǰ�����л��� { eml_parser->iDataPointer -= 3; //��')'���ڻ������ȴ��´δ��� pc = pc-3; //����')'������ᵱ��'\n'�����������;����POPͷ��Ҳ�� *output_line = srcdata; *plinelen = pc-srcdata; return MAIL_LINE_END; } } datalen = pc - srcdata; if(datalen > 0) //�ҵ���\n { eml_parser->iDataPointer += srcend - pc; *output_line = srcdata; *plinelen = srclen; return MAIL_PACKET_END; } else { //�ܳ���һ��ֱ�ӷ��أ��е�����û���� //�洢��ԭ���ǣ���ʱ�������β����ʣ�೤�Ƚ�С��Э��ȽϹؼ���ʱ���ܻ������� if(buf_cache_check_size(&eml_parser->pDataLineBuf, srclen)<0) { *output_line = (char *)eml_parser->pDataLineBuf.buf; *plinelen = eml_parser->pDataLineBuf.len; return MAIL_LINE_END; } memcpy((char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len, srcdata, srclen); eml_parser->pDataLineBuf.len += srclen; eml_parser->iDataPointer += srclen; *output_line = NULL; *plinelen = 0; return MAIL_INPUT_END; } return MAIL_INPUT_END; } static int get_fold_line(struct email_parser *eml_parser, char *srcdata,int srclen,char **output_line,int *plinelen) { char *posd_n = NULL; int ret, flag=0; if(srclen == 0) return MAIL_INPUT_END; while(srclen > 0) { if(eml_parser->pDataLineBuf.len > 0) { posd_n = (char *)memrchr(eml_parser->pDataLineBuf.buf, '\n', eml_parser->pDataLineBuf.len); if(posd_n != NULL && posd_n >= (char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len) { posd_n = NULL; } } else posd_n = NULL; if(posd_n != NULL) { if(posd_n+1 < (char *)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len && *(posd_n+1)=='\t') { eml_parser->pDataLineBuf.len -= 1;//\t ret = process_srcdata_r(&srcdata, &srclen, output_line, plinelen, eml_parser); if(ret == MAIL_FOLD_LINE_START) continue; else return ret; } else if(*srcdata != '\t' && *srcdata != ' ') { *output_line = (char *)eml_parser->pDataLineBuf.buf; *plinelen = eml_parser->pDataLineBuf.len; return MAIL_FOLD_LINE_END; } else { while(srclen>0 && (*srcdata == '\t' || *srcdata == ' ')) { srcdata++; srclen--; eml_parser->iDataPointer++; flag = 1; } if(srclen == 0) { if(flag) { if(buf_cache_check_size(&eml_parser->pDataLineBuf, 1)<0) return MAIL_GETLINE_ERR; *((char*)eml_parser->pDataLineBuf.buf + eml_parser->pDataLineBuf.len) = '\t'; eml_parser->pDataLineBuf.len += 1; } return MAIL_INPUT_END; } flag = 0; ret = process_srcdata_r(&srcdata, &srclen, output_line, plinelen, eml_parser); if(ret == MAIL_FOLD_LINE_START) continue; else return ret; } } else { if(eml_parser->pDataLineBuf.len == 0) { if(*srcdata=='\n') //һ��\n���� { eml_parser->iDataPointer += 1; *output_line = srcdata; *plinelen = 1; return MAIL_FOLD_LINE_END; } else if(srclen>=2 && *srcdata=='\r' && *(srcdata+1) == '\n') //һ��\r\n���� { eml_parser->iDataPointer += 2; *output_line = srcdata; *plinelen = 2; return MAIL_FOLD_LINE_END; } } ret = process_srcdata_r(&srcdata, &srclen, output_line, plinelen, eml_parser); if(ret == MAIL_FOLD_LINE_START) continue; else return ret; } } return MAIL_INPUT_END; } char *mail_message_to_json(struct mail_message *msg) { cJSON *json_msg = cJSON_CreateObject(); if (!json_msg) return NULL; cJSON_AddNumberToObject(json_msg, "type", msg ? msg->type : 0); cJSON_AddNumberToObject(json_msg, "mail_protocol", msg ? msg->mail_protocol : 0); cJSON_AddNumberToObject(json_msg, "mail_seq", msg ? msg->mail_seq : 0); if (msg->command) { cJSON *json_command = cJSON_CreateObject(); if (json_command) { cJSON_AddNumberToObject(json_command, "cmd", msg->command->cmd); cJSON_AddStringToObject(json_command, "arg", msg->command->arg && msg->command->arg_len ? msg->command->arg : ""); cJSON_AddNumberToObject(json_command, "arg_len", msg->command->arg_len); cJSON_AddStringToObject(json_command, "cmd_line", msg->command->cmd_line && msg->command->cmd_line_len ? msg->command->cmd_line : ""); cJSON_AddNumberToObject(json_command, "cmd_line_len", msg->command->cmd_line_len); } cJSON_AddItemToObject(json_msg, "command", json_command); } if (msg->header) { cJSON *json_header = cJSON_CreateObject(); if (json_header) { cJSON_AddStringToObject(json_header, "from", msg->header->from && msg->header->from->field_value ? msg->header->from->field_value : ""); cJSON_AddStringToObject(json_header, "to", msg->header->to && msg->header->to->field_value ? msg->header->to->field_value : ""); cJSON_AddStringToObject(json_header, "cc", msg->header->cc && msg->header->cc->field_value ? msg->header->cc->field_value : ""); cJSON_AddStringToObject(json_header, "bcc", msg->header->bcc && msg->header->bcc->field_value ? msg->header->bcc->field_value : ""); cJSON_AddStringToObject(json_header, "reply_to", msg->header->reply_to && msg->header->reply_to->field_value ? msg->header->reply_to->field_value : ""); cJSON_AddStringToObject(json_header, "date", msg->header->date && msg->header->date->field_value ? msg->header->date->field_value : ""); cJSON_AddStringToObject(json_header, "subject", msg->header->subject && msg->header->subject->field_value ? msg->header->subject->field_value : ""); if (msg->header->header_fields && msg->header->n_header_fields > 0) { cJSON *json_header_fields = cJSON_CreateArray(); for (size_t i = 0; i < msg->header->n_header_fields; i++) { cJSON *json_field = cJSON_CreateObject(); if (json_field) { cJSON_AddStringToObject(json_field, "field_name", msg->header->header_fields[i].field_name ? msg->header->header_fields[i].field_name : ""); cJSON_AddStringToObject(json_field, "field_value", msg->header->header_fields[i].field_value ? msg->header->header_fields[i].field_value : ""); cJSON_AddItemToArray(json_header_fields, json_field); } } cJSON_AddItemToObject(json_header, "header_fields", json_header_fields); } } cJSON_AddItemToObject(json_msg, "header", json_header); } if (msg->body) { cJSON *json_body = cJSON_CreateObject(); if (json_body) { cJSON_AddStringToObject(json_body, "body", msg->body->body && msg->body->body_len ? msg->body->body : ""); cJSON_AddNumberToObject(json_body, "body_len", msg->body->body_len); cJSON_AddNumberToObject(json_body, "body_offset", msg->body->body_offset); cJSON_AddBoolToObject(json_body, "is_body_finished", msg->body->is_body_finished); } cJSON_AddItemToObject(json_msg, "body", json_body); } if (msg->attachment) { cJSON *json_attachment = cJSON_CreateObject(); if (json_attachment) { cJSON_AddStringToObject(json_attachment, "attachment_name", msg->attachment->attachment_name && msg->attachment->attachment_name_len? msg->attachment->attachment_name : ""); cJSON_AddNumberToObject(json_attachment, "attachment_name_len", msg->attachment->attachment_name_len); cJSON_AddStringToObject(json_attachment, "attachment", msg->attachment->attachment && msg->attachment->attachment_len ? msg->attachment->attachment : ""); cJSON_AddNumberToObject(json_attachment, "attachment_len", msg->attachment->attachment_len); cJSON_AddNumberToObject(json_attachment, "attachment_offset", msg->attachment->attachment_offset); cJSON_AddBoolToObject(json_attachment, "is_attachment_finished", msg->attachment->is_attachment_finished); } cJSON_AddItemToObject(json_msg, "attachment", json_attachment); } if (msg->eml) { cJSON *json_eml = cJSON_CreateObject(); if (json_eml) { cJSON_AddStringToObject(json_eml, "eml", msg->eml->eml && msg->eml->eml_len ? msg->eml->eml : ""); cJSON_AddNumberToObject(json_eml, "eml_len", msg->eml->eml_len); cJSON_AddNumberToObject(json_eml, "eml_offset", msg->eml->eml_offset); cJSON_AddBoolToObject(json_eml, "is_eml_finished", msg->eml->is_eml_finished); } cJSON_AddItemToObject(json_msg, "eml", json_eml); } char *json_string = cJSON_Print(json_msg); cJSON_Delete(json_msg); return json_string; } int mail_command_update(struct mail_command *command, enum MAIL_COMMAND cmd, const char *cmd_arg, size_t cmd_arg_len, const char *cmd_line, size_t cmd_line_len) { command->cmd = cmd; if (cmd_arg && cmd_arg_len > 0) { cmd_arg_len = MIN(cmd_arg_len, MAIL_COMMAND_BUFFER_MAX); command->arg_len = cmd_arg_len; memcpy(command->arg, cmd_arg, cmd_arg_len); } if (cmd_line && cmd_line_len > 0) { cmd_line_len = MIN(cmd_line_len, MAIL_COMMAND_BUFFER_MAX); command->cmd_line_len = cmd_line_len; memcpy(command->cmd_line, cmd_line, cmd_line_len); } return 0; } struct mail_command *mail_command_clone(struct mail_command *cmd) { struct mail_command *clone; clone = (struct mail_command *)calloc(1, sizeof(struct mail_command)); clone->cmd = cmd->cmd; if (cmd->arg && cmd->arg_len > 0) { clone->arg = (char *)malloc(cmd->arg_len); clone->arg_len = cmd->arg_len; memcpy(clone->arg, cmd->arg, cmd->arg_len); } if (cmd->cmd_line && cmd->cmd_line_len > 0) { clone->cmd_line = (char *)malloc(cmd->cmd_line_len); clone->cmd_line_len = cmd->cmd_line_len; memcpy(clone->cmd_line, cmd->cmd_line, cmd->cmd_line_len); } return clone; } void mail_command_free(struct mail_command *cmd) { if (cmd) { if (cmd->arg) { free(cmd->arg); } if (cmd->cmd_line) { free(cmd->cmd_line); } free(cmd); } } struct mail_command * mail_command_new() { struct mail_command *command; command = (struct mail_command *)calloc(1, sizeof(struct mail_command)); command->cmd = MAIL_CMD_MAX; command->arg = (char *)calloc(1, MAIL_COMMAND_BUFFER_MAX); command->cmd_line = (char *)calloc(1, MAIL_COMMAND_BUFFER_MAX); return command; } void mail_header_free(struct mail_header *header) { int i; struct mail_header_field *field; if (header) { if (header->header_fields) { for (i = 0; i < (int)header->n_header_fields; i++) { field = &header->header_fields[i]; if (field->field_name) { free(field->field_name); } if (field->field_value) { free(field->field_value); } } free(header->header_fields); } free(header); } } struct mail_header *mail_header_new(void) { struct mail_header *header; header = (struct mail_header *)calloc(1, sizeof(struct mail_header)); header->header_fields = (struct mail_header_field *)calloc(MAIL_HEADER_FIELDS_MAX, sizeof(struct mail_header_field)); return header; } int mail_header_add_field(struct mail_header *header, const char *line, size_t len, int enable_mime_decode) { int ret; struct iovec *iov_name; struct iovec *iov_value; struct iovec split[MAIL_HEADER_FIELD_SPLIT_PART_MAX]; if (header->n_header_fields >= MAIL_HEADER_FIELDS_MAX) { return -1; } // delete line endding while(len > 0 && (*(line + len -1)=='\n' || *(line + len -1)=='\r')) { len -= 1; } ret = mail_strnsplit(split, MAIL_HEADER_FIELD_SPLIT_PART_MAX, ':', line, len); if (ret != MAIL_HEADER_FIELD_SPLIT_PART_MAX) { return -1; } iov_name = &split[MAIL_HEADER_FIELD_SPLIT_PART_NAME]; header->header_fields[header->n_header_fields].field_name = strndup(iov_name->iov_base, iov_name->iov_len); header->header_fields[header->n_header_fields].field_name_len = iov_name->iov_len; iov_value = &split[MAIL_HEADER_FIELD_SPLIT_PART_VALUE]; if (enable_mime_decode) { char decode_buf[MAX_ORDER_LINE_SIZE+1]; char charset_str_buf[MAIL_MAX_CHARSET_LEN]; int decoded_len; decoded_len = sizeof(decode_buf); mime_header_decode(iov_value->iov_base, iov_value->iov_len, decode_buf, &decoded_len, charset_str_buf, sizeof(charset_str_buf), NULL); header->header_fields[header->n_header_fields].field_value = strndup(decode_buf, decoded_len); header->header_fields[header->n_header_fields].field_value_len = decoded_len; } else { header->header_fields[header->n_header_fields].field_value = strndup(iov_value->iov_base, iov_value->iov_len); header->header_fields[header->n_header_fields].field_value_len = iov_value->iov_len; } header->n_header_fields++; return 0; } int mail_header_add_date(struct mail_header *header, const char *line, size_t len, int enable_mime_decode) { int ret; ret = mail_header_add_field(header, line, len, enable_mime_decode); if (ret != 0) { return -1; } header->date = &header->header_fields[header->n_header_fields - 1]; return 0; } int mail_header_add_from(struct mail_header *header, const char *line, size_t len, int enable_mime_decode) { int ret; ret = mail_header_add_field(header, line, len, enable_mime_decode); if (ret != 0) { return -1; } header->from = &header->header_fields[header->n_header_fields - 1]; return 0; } int mail_header_add_to(struct mail_header *header, const char *line, size_t len, int enable_mime_decode) { int ret; ret = mail_header_add_field(header, line, len, enable_mime_decode); if (ret != 0) { return -1; } header->to = &header->header_fields[header->n_header_fields - 1]; return 0; } int mail_header_add_cc(struct mail_header *header, const char *line, size_t len, int enable_mime_decode) { int ret; ret = mail_header_add_field(header, line, len, enable_mime_decode); if (ret != 0) { return -1; } header->cc = &header->header_fields[header->n_header_fields - 1]; return 0; } int mail_header_add_bcc(struct mail_header *header, const char *line, size_t len, int enable_mime_decode) { int ret; ret = mail_header_add_field(header, line, len, enable_mime_decode); if (ret != 0) { return -1; } header->bcc = &header->header_fields[header->n_header_fields - 1]; return 0; } int mail_header_add_reply_to(struct mail_header *header, const char *line, size_t len, int enable_mime_decode) { int ret; ret = mail_header_add_field(header, line, len, enable_mime_decode); if (ret != 0) { return -1; } header->reply_to = &header->header_fields[header->n_header_fields - 1]; return 0; } int mail_header_add_subject(struct mail_header *header, const char *line, size_t len, int enable_mime_decode) { int ret; ret = mail_header_add_field(header, line, len, enable_mime_decode); if (ret != 0) { return -1; } header->subject = &header->header_fields[header->n_header_fields - 1]; return 0; } struct mail_body * mail_body_clone(struct mail_body *body) { struct mail_body *clone; clone = (struct mail_body *)calloc(1, sizeof(struct mail_body)); if (body->body && body->body_len > 0) { clone->body = (char *)malloc(body->body_len); clone->body_len = body->body_len; memcpy(clone->body, body->body, body->body_len); } clone->body_offset = body->body_offset; clone->is_body_finished = body->is_body_finished; return clone; } int mail_body_update(struct mail_body *body, const char *line, size_t len, int is_finished) { len = MIN(len, MAIL_BODY_BUFFER_MAX); if (line) { memcpy(body->body, line, len); } body->body_len = len; body->body_offset += len; body->is_body_finished = is_finished; return 0; } int mail_body_reset(struct mail_body *body) { body->body_len = 0; body->body_offset = 0; body->is_body_finished = 0; return 0; } void mail_body_free(struct mail_body *body) { if (body) { if (body->body) { free(body->body); } free(body); } } struct mail_body * mail_body_new(void) { struct mail_body *body; body = (struct mail_body *)calloc(1, sizeof(struct mail_body)); body->body = (char *)calloc(1, MAIL_BODY_BUFFER_MAX); body->body_len = 0; body->body_offset = 0; return body; } int mail_attachment_set_filename(struct mail_attachment *attachment, const char *name, size_t len) { if (attachment->attachment_name_len == 0) { len = MIN(len, MAIL_ATTACHMENT_NAME_BUFFER_MAX); if (name) { memcpy(attachment->attachment_name, name, len); } attachment->attachment_name_len = len; } return 0; } struct mail_attachment *mail_attachment_clone(struct mail_attachment *attachment) { struct mail_attachment *clone; clone = (struct mail_attachment *)calloc(1, sizeof(struct mail_attachment)); if (attachment->attachment_name && attachment->attachment_name_len > 0) { clone->attachment_name = (char *)malloc(attachment->attachment_name_len); clone->attachment_name_len = attachment->attachment_name_len; memcpy(clone->attachment_name, attachment->attachment_name, attachment->attachment_name_len); } if (attachment->attachment && attachment->attachment_len > 0) { clone->attachment = (char *)malloc(attachment->attachment_len); clone->attachment_len = attachment->attachment_len; memcpy(clone->attachment, attachment->attachment, attachment->attachment_len); } clone->attachment_offset = attachment->attachment_offset; clone->is_attachment_finished = attachment->is_attachment_finished; return clone; } int mail_attachment_update(struct mail_attachment *attachment, const char *line, size_t len, int is_attachment_finished) { len = MIN(len, MAIL_ATTACHMENT_BUFFER_MAX); if (line) { memcpy(attachment->attachment, line, len); } attachment->attachment_len = len; attachment->attachment_offset += len; attachment->is_attachment_finished = is_attachment_finished; return 0; } int mail_attachment_reset(struct mail_attachment *attachment) { attachment->attachment_name_len = 0; attachment->attachment_len = 0; attachment->attachment_offset = 0; attachment->is_attachment_finished = 0; return 0; } void mail_attachment_free(struct mail_attachment *attachment) { if (attachment) { if (attachment->attachment) { free(attachment->attachment); } if (attachment->attachment_name) { free(attachment->attachment_name); } free(attachment); } } struct mail_attachment * mail_attachment_new(void) { struct mail_attachment *attachment; attachment = (struct mail_attachment *)calloc(1, sizeof(struct mail_attachment)); attachment->attachment_name = (char *)calloc(1, MAIL_ATTACHMENT_NAME_BUFFER_MAX); attachment->attachment = (char *)calloc(1, MAIL_BODY_BUFFER_MAX); return attachment; } struct mail_eml *mail_eml_clone(struct mail_eml *eml) { struct mail_eml *clone; clone = (struct mail_eml *)calloc(1, sizeof(struct mail_eml)); if (eml->eml && eml->eml_len > 0) { clone->eml = (char *)malloc(eml->eml_len); clone->eml_len = eml->eml_len; memcpy(clone->eml, eml->eml, eml->eml_len); } clone->eml_offset = eml->eml_offset; clone->is_eml_finished = eml->is_eml_finished; return clone; } int mail_eml_update(struct mail_eml *eml, const char *data, size_t len, int is_eml_finished) { len = MIN(len, MAIL_EML_BUFFER_MAX); if (data) { memcpy(eml->eml, data, len); } eml->eml_len = len; eml->eml_offset += len; eml->is_eml_finished = is_eml_finished; return 0; } int mail_eml_reset(struct mail_eml *eml) { eml->eml_len = 0; eml->eml_offset = 0; eml->is_eml_finished = 0; return 0; } void mail_eml_free(struct mail_eml *eml) { if (eml) { if (eml->eml) { free(eml->eml); } free(eml); } } struct mail_eml *mail_eml_new(void) { struct mail_eml *eml; eml = (struct mail_eml *)calloc(1, sizeof(struct mail_eml)); eml->eml = (char *)calloc(1, MAIL_EML_BUFFER_MAX); return eml; } int mail_publish_command(struct mq_runtime *mq, int topic_id, struct session *sess, enum MAIL_PROTOCOL protocol, size_t mail_seq, struct mail_command *cmd) { struct mail_message *msg; if ((cmd->arg == NULL && cmd->cmd_line == NULL) || (cmd->arg_len == 0 && cmd->cmd_line_len == 0)) { return -1; } msg = (struct mail_message *)calloc(1, sizeof(struct mail_message)); msg->sess_ref = sess; msg->mail_seq = mail_seq; msg->mail_protocol = protocol; msg->command = mail_command_clone(cmd); mq_runtime_publish_message(mq, topic_id, msg); return 0; } int mail_publish_header(struct mq_runtime *mq, int topic_id, struct session *sess, enum MAIL_PROTOCOL protocol, size_t mail_seq, struct mail_header *header) { struct mail_message *msg; if (header == NULL || header->n_header_fields == 0) { return -1; } msg = (struct mail_message *)calloc(1, sizeof(struct mail_message)); msg->sess_ref = sess; msg->mail_seq = mail_seq; msg->mail_protocol = protocol; msg->header = header; mq_runtime_publish_message(mq, topic_id, msg); return 0; } int mail_publish_body(struct mq_runtime *mq, int topic_id, struct session *sess, enum MAIL_PROTOCOL protocol, size_t mail_seq, struct mail_body *body) { struct mail_message *msg; if (body == NULL || body->body_offset == 0) { return -1; } msg = (struct mail_message *)calloc(1, sizeof(struct mail_message)); msg->sess_ref = sess; msg->mail_seq = mail_seq; msg->mail_protocol = protocol; msg->body = mail_body_clone(body); mq_runtime_publish_message(mq, topic_id, msg); return 0; } int mail_publish_attachment(struct mq_runtime *mq, int topic_id, struct session *sess, enum MAIL_PROTOCOL protocol, size_t mail_seq, struct mail_attachment *attachment) { struct mail_message *msg; if (attachment == NULL || attachment->attachment_name_len == 0 || attachment->attachment_offset == 0) { return -1; } msg = (struct mail_message *)calloc(1, sizeof(struct mail_message)); msg->sess_ref = sess; msg->mail_seq = mail_seq; msg->mail_protocol = protocol; msg->attachment = mail_attachment_clone(attachment); mq_runtime_publish_message(mq, topic_id, msg); return 0; } int mail_publish_eml(struct mq_runtime *mq, int topic_id, struct session *sess, enum MAIL_PROTOCOL protocol, struct mail_eml *eml) { struct mail_message *msg; if (eml == NULL || eml->eml_offset == 0) { return -1; } msg = (struct mail_message *)calloc(1, sizeof(struct mail_message)); msg->sess_ref = sess; msg->mail_protocol = protocol; msg->eml = mail_eml_clone(eml); mq_runtime_publish_message(mq, topic_id, msg); return 0; } void mail_message_free(void *msg, void *arg) { (void)(arg); struct mail_message *mail_msg; mail_msg = (struct mail_message *)msg; if (mail_msg) { if (mail_msg->command) { mail_command_free(mail_msg->command); } if (mail_msg->header) { mail_header_free(mail_msg->header); } if (mail_msg->body) { mail_body_free(mail_msg->body); } if (mail_msg->attachment) { mail_attachment_free(mail_msg->attachment); } if (mail_msg->eml) { mail_eml_free(mail_msg->eml); } free(mail_msg); } } static void mail_mailinfo_clear(tdMailInfo *plug_mailinfo) { if(plug_mailinfo->pMailInfo->username->buf) free(plug_mailinfo->pMailInfo->username->buf); if(plug_mailinfo->pMailInfo->password->buf) free(plug_mailinfo->pMailInfo->password->buf); if(plug_mailinfo->pMailInfo->sendaddr->buf) free(plug_mailinfo->pMailInfo->sendaddr->buf); if(plug_mailinfo->pMailInfo->recvaddr->buf) free(plug_mailinfo->pMailInfo->recvaddr->buf); if(plug_mailinfo->pMailInfo->subject->buf) free(plug_mailinfo->pMailInfo->subject->buf); if(plug_mailinfo->pMailInfo->date->buf) free(plug_mailinfo->pMailInfo->date->buf); if(plug_mailinfo->elem) free(plug_mailinfo->elem); } static int mail_mailinfo_init(struct email_parser *email) { tdMailInfo *pmailinfo = &email->plug_mailinfo; memset(pmailinfo, 0, sizeof(tdMailInfo)); pmailinfo->pMailInfo = &email->pMailinfo; pmailinfo->pMailInfo->username = &email->keyinfo.username; pmailinfo->pMailInfo->password = &email->keyinfo.password; pmailinfo->pMailInfo->sendaddr= &email->keyinfo.sendaddr; pmailinfo->pMailInfo->recvaddr = &email->keyinfo.recvaddr; pmailinfo->pMailInfo->subject = &email->keyinfo.subject; pmailinfo->pMailInfo->date = &email->keyinfo.date; pmailinfo->elem = (stFieldElem *)malloc(sizeof(stFieldElem)*MAIL_ELEM_NUM); email->max_elem_num = MAIL_ELEM_NUM; return 0; } static void mail_mailinfo_reset(tdMailInfo *pmailinfo) { /*if(pmailinfo->pMailInfo->username->buf != NULL) //ͬһ��������������û������룬�����ĻỰ���Լ�������� { pmailinfo->pMailInfo->username->buflen = 0; pmailinfo->pMailInfo->username->buf[0] = '\0'; } if(pmailinfo->pMailInfo->password->buf != NULL) { pmailinfo->pMailInfo->password->buflen = 0; pmailinfo->pMailInfo->password->buf[0] = '\0'; }*/ if(pmailinfo->pMailInfo->sendaddr->buf != NULL) { pmailinfo->pMailInfo->sendaddr->buflen = 0; pmailinfo->pMailInfo->sendaddr->buf[0] = '\0'; } if(pmailinfo->pMailInfo->recvaddr->buf != NULL) { pmailinfo->pMailInfo->recvaddr->buflen = 0; pmailinfo->pMailInfo->recvaddr->buf[0] = '\0'; } if(pmailinfo->pMailInfo->subject->buf != NULL) { pmailinfo->pMailInfo->subject->buflen = 0; pmailinfo->pMailInfo->subject->buf[0] = '\0'; } if(pmailinfo->pMailInfo->date->buf != NULL) { pmailinfo->pMailInfo->date->buflen = 0; pmailinfo->pMailInfo->date->buf[0] = '\0'; } pmailinfo->trans_enc = MAIL_TRANS_ENC_UNKNOWN; pmailinfo->session_seq++; pmailinfo->buflen = 0; pmailinfo->buf = NULL; pmailinfo->current_charset = NULL; pmailinfo->lostlen = 0; if(pmailinfo->elem_num > 0) { pmailinfo->elem_num = 0; } } static int email_process_body(char *a_mail_line, int datalen,struct email_parser * eml_parser) { int ret; MimeParse_t * mimeinfo = eml_parser->mimeinfo; mimeinfo->src = a_mail_line; mimeinfo->srcLen = datalen; if (buf_cache_check_size(&eml_parser->pMimeDecodeBuf, mimeinfo->srcLen+1) < 0) { return -1; } mimeinfo->dst = (char *)eml_parser->pMimeDecodeBuf.buf; mimeinfo->dstSize = eml_parser->pMimeDecodeBuf.max_len; eml_parser->pMimeDecodeBuf.len = 0; ret = mime_parse_feed(mimeinfo, 1); if (ret<0) { return -1; } if ((ret == MIME_LINE_CONT_TYPE || ret == MIME_LINE_CONT_DISP) && mimeinfo->filename != NULL) { eml_parser->MailInfoState = MAIL_GET_FILENAME; } else if (ret == MIME_LINE_CONT_BODY) { if (mimeinfo->is_attachment) { eml_parser->MailInfoState = MAIL_GET_FILECOUNT; } else { eml_parser->MailInfoState = MAIL_GET_COUNT; } } else if (ret == MIME_LINE_BOUNARY || ret == MIME_LINE_BOUNARY_END) { if (mimeinfo->is_attachment) { eml_parser->MailInfoState = MAIL_GET_FILECOUNT_END; } else { eml_parser->MailInfoState = MAIL_GET_COUNT_END; } } else { eml_parser->MailInfoState = MAIL_GET_OTHER; } return 0; } enum EML_LINE_TYPE email_parser_parse_line(const char *a_mail_line,int datalen,int EmlAnalyseState) { if (EmlAnalyseState == MAIL_STAT_BODY) return EML_DATA_BODY_IN; const char *pos_colon; pos_colon = (const char *)memchr(a_mail_line, ':', datalen>26?26:datalen); if (pos_colon != NULL) { datalen = pos_colon-a_mail_line; switch(datalen) { case 2: if (strcmp_one_word_mesa_equal_len("to", "TO", a_mail_line, 2)) return EML_DATA_TO; if (strcmp_one_word_mesa_equal_len("cc", "CC", a_mail_line, 2)) return EML_DATA_CC; break; case 3: if (strcmp_one_word_mesa_equal_len("bcc", "BCC", a_mail_line, 3)) return EML_DATA_BCC; break; case 4: if (strcmp_one_word_mesa_equal_len("date", "DATE", a_mail_line, 4)) return EML_DATA_DATE; if (strcmp_one_word_mesa_equal_len("from", "FROM", a_mail_line, 4)) return EML_DATA_FROM; break; case 7: if (strcmp_one_word_mesa_equal_len("subject", "SUBJECT", a_mail_line, 7)) return EML_DATA_SUBJECT; break; case 8: if (strcmp_one_word_mesa_equal_len("received", "RECEIVED", a_mail_line, 8)) return EML_DATA_RECEIVED; if (strcmp_one_word_mesa_equal_len("reply-to", "REPLY-TO", a_mail_line, 8)) return EML_DATA_REPLY_TO; break; case 11: if (strcmp_one_word_mesa_equal_len("return-path", "RETURN-PATH", a_mail_line, 11)) return EML_DATA_RETURN_PATH; break; case 12: if (strcmp_one_word_mesa_equal_len("delivered-to", "DELIVERED-TO", a_mail_line, 12)) return EML_DATA_DELIVERED_TO; if (MAIL_STAT_HEADER == EmlAnalyseState) { if (strcmp_one_word_mesa_equal_len("content-type", "CONTENT-TYPE", a_mail_line, 12)) return EML_DATA_CONTENTTYPE; return EML_DATA_HEAD_IN; } break; case 25: if (MAIL_STAT_HEADER == EmlAnalyseState) { if (strcmp_one_word_mesa_equal_len("content-transfer-encoding", "CONTENT-TRANSFER-ENCODING", a_mail_line, 25)) return EML_DATA_CONTENTTRANSFERENCODING; return EML_DATA_HEAD_IN; } break; default: if (MAIL_STAT_HEADER != EmlAnalyseState && strncmp_one_word_mesa("x-", "X-", 2, a_mail_line, datalen)) return EML_DATA_HEAD_IN; break; } if (MAIL_STAT_HEADER == EmlAnalyseState) { return EML_DATA_HEAD_IN; } } else if (MAIL_STAT_HEADER == EmlAnalyseState) { if ((datalen==2 && !strncmp(a_mail_line, "\r\n", 2))||(datalen==1 && *a_mail_line=='\n')) return EML_DATA_HEAD_BODY_BORDER; return EML_DATA_HEAD_IN; } return EML_UNKNOWN; } int email_parser_get_tcpdata(struct email_parser* eml_parser, const char *payload, size_t payload_len, int need_folding, char ** output_buf,int *output_len) { char* curpointer = (char*)(payload) + eml_parser->iDataPointer; if((unsigned int)(eml_parser->iDataPointer) >= (unsigned int)(payload_len)) return MAIL_INPUT_END; if(need_folding == 1) { return get_fold_line(eml_parser, curpointer, payload_len-eml_parser->iDataPointer, output_buf, output_len); } else if(eml_parser->EmlAnalyseState != MAIL_STAT_BODY || eml_parser->obtain_line) { if(eml_parser->obtain_line) eml_parser->obtain_line = 0; return get_one_tcpline(eml_parser, curpointer, payload_len-eml_parser->iDataPointer, output_buf, output_len, 1); } else { return get_complete_region(eml_parser, curpointer, payload_len-eml_parser->iDataPointer, output_buf, output_len); } } int email_parser_get_atcpline_c2s(struct email_parser* eml_parser, const char *payload, size_t payload_len, char ** output_buf,int *output_len) { char* curpointer = (char*)(payload) + eml_parser->iDataPointer; if((unsigned int)(eml_parser->iDataPointer) >= (unsigned int)(payload_len)) return MAIL_INPUT_END; return get_one_tcpline(eml_parser, curpointer, payload_len-eml_parser->iDataPointer, output_buf, output_len, 0); } void email_parser_set_drop(struct email_parser* eml_parser) { eml_parser->is_drop = 1; eml_parser->EmlAnalyseState = MAIL_STAT_BODY; eml_parser->mimeinfo->text_begin = 1; } size_t email_parser_get_seq(struct email_parser *eml_parser) { return eml_parser->mail_seq; } int email_parser_reset(struct email_parser * eml_parser) { mail_eml_reset(eml_parser->eml); mail_body_reset(eml_parser->body); mail_attachment_reset(eml_parser->current_attachment); mail_mailinfo_reset(&eml_parser->plug_mailinfo); reset_mime_info(eml_parser->mimeinfo, 0); eml_parser->pDataLineBuf.len = 0; eml_parser->pOriginalData.len = 0; eml_parser->pMimeDecodeBuf.len = 0; eml_parser->pBizRegion.len = 0; eml_parser->subject_charset[0] = '\0'; eml_parser->EmlAnalyseState = MAIL_STAT_INIT; eml_parser->MailInfoState = MAIL_NO_USER; eml_parser->maybe_end = 0; //IMAPЭ�飬��һ��MAYBE_END����һ����FETCH����������Ҫ��ո�״̬ eml_parser->is_drop = 0; eml_parser->is_called = 0; eml_parser->pending_state = 1; return 0; } void email_parser_free(struct email_parser *eml_parser) { if (eml_parser->is_called) { eml_parser->plug_mailinfo.buf = (char *)eml_parser->pOriginalData.buf; eml_parser->plug_mailinfo.buflen = eml_parser->pOriginalData.len; } mail_mailinfo_clear(&eml_parser->plug_mailinfo); clear_mime_info(eml_parser->mimeinfo); mail_header_free(eml_parser->header); mail_body_free(eml_parser->body); mail_attachment_free(eml_parser->current_attachment); mail_eml_free(eml_parser->eml); if (eml_parser->pDataLineBuf.buf) free(eml_parser->pDataLineBuf.buf); if (eml_parser->pOriginalData.buf) free(eml_parser->pOriginalData.buf); if (eml_parser->pMimeDecodeBuf.buf) free(eml_parser->pMimeDecodeBuf.buf); if (eml_parser->pBizRegion.buf) free(eml_parser->pBizRegion.buf); free(eml_parser); } struct email_parser *email_parser_new(struct mq_runtime *mq, struct mail_topics *topics, enum MAIL_PROTOCOL protocol, int is_c2s) { struct email_parser* eml_parser = NULL; eml_parser = (struct email_parser *)calloc(1, sizeof(struct email_parser)); //session_info->app_info: eml_parser->plug_mailinfo if (mail_mailinfo_init(eml_parser)) { free(eml_parser); return NULL; } //mimeinfo if (init_mime_info(&eml_parser->mimeinfo, NULL) < 0) { mail_mailinfo_clear(&eml_parser->plug_mailinfo); free(eml_parser); return NULL; } //other info eml_parser->EmlAnalyseState=MAIL_STAT_INIT; eml_parser->MailInfoState=MAIL_NO_USER; eml_parser->pre_dir = is_c2s; eml_parser->pending_state = 1; eml_parser->mail_seq = 0; eml_parser->protocol = protocol; eml_parser->header = mail_header_new(); eml_parser->body = mail_body_new(); eml_parser->current_attachment = mail_attachment_new(); eml_parser->eml = mail_eml_new(); eml_parser->header_topic_id = topics->topic_ids[MAIL_TOPIC_HEADER]; eml_parser->body_topic_id = topics->topic_ids[MAIL_TOPIC_BODY]; eml_parser->attachment_topic_id = topics->topic_ids[MAIL_TOPIC_ATTACHMENT]; eml_parser->eml_topic_id = topics->topic_ids[MAIL_TOPIC_EML]; eml_parser->mq = mq; return eml_parser; } int email_parser_entry(struct email_parser *eml_parser, struct session *sess, const char *email_line, size_t line_len, enum EML_LINE_TYPE line_type) { int ret; if (line_type != EML_DATA_END) { mail_eml_update(eml_parser->eml, email_line, line_len, 0); } else { mail_eml_update(eml_parser->eml, NULL, 0, 1); } mail_publish_eml(eml_parser->mq, eml_parser->eml_topic_id, sess, eml_parser->protocol, eml_parser->eml); if (is_eml_header_field(line_type) && eml_parser->header == NULL) { eml_parser->header = mail_header_new(); eml_parser->mail_seq++; } switch (line_type) { case EML_DATA_DATE: if (eml_parser->EmlAnalyseState != MAIL_STAT_HEADER) { eml_parser->EmlAnalyseState = MAIL_STAT_HEADER; } eml_parser->MailInfoState = MAIL_GET_DATE; mail_header_add_date(eml_parser->header, email_line, line_len, 1); break; case EML_DATA_FROM: if (eml_parser->EmlAnalyseState != MAIL_STAT_HEADER) { eml_parser->EmlAnalyseState = MAIL_STAT_HEADER; } eml_parser->MailInfoState = MAIL_GET_FROM; mail_header_add_from(eml_parser->header, email_line, line_len, 1); break; case EML_DATA_TO: if (eml_parser->EmlAnalyseState != MAIL_STAT_HEADER) { eml_parser->EmlAnalyseState = MAIL_STAT_HEADER; } eml_parser->MailInfoState = MAIL_GET_TO; mail_header_add_to(eml_parser->header, email_line, line_len, 1); break; case EML_DATA_CC: if (eml_parser->EmlAnalyseState != MAIL_STAT_HEADER) { eml_parser->EmlAnalyseState = MAIL_STAT_HEADER; } eml_parser->MailInfoState = MAIL_GET_TO; //TODO mail_header_add_cc(eml_parser->header, email_line, line_len, 1); break; case EML_DATA_BCC: if (eml_parser->EmlAnalyseState != MAIL_STAT_HEADER) { eml_parser->EmlAnalyseState = MAIL_STAT_HEADER; } eml_parser->MailInfoState = MAIL_GET_TO; //TODO mail_header_add_bcc(eml_parser->header, email_line, line_len, 1); break; case EML_DATA_REPLY_TO: if (eml_parser->EmlAnalyseState != MAIL_STAT_HEADER) { eml_parser->EmlAnalyseState = MAIL_STAT_HEADER; } eml_parser->MailInfoState = MAIL_GET_TO; mail_header_add_to(eml_parser->header, email_line, line_len, 1); break; case EML_DATA_SUBJECT: if (eml_parser->EmlAnalyseState != MAIL_STAT_HEADER) { eml_parser->EmlAnalyseState = MAIL_STAT_HEADER; } eml_parser->MailInfoState = MAIL_GET_SUB; mail_header_add_subject(eml_parser->header, email_line, line_len, 1); break; case EML_DATA_CONTENTTYPE: case EML_DATA_CONTENTTRANSFERENCODING: case EML_DATA_BODY_IN: ret = email_process_body((char *)email_line, line_len, eml_parser); if (ret < 0) { return -1; } // body if (eml_parser->MailInfoState == MAIL_GET_COUNT) { mail_body_update(eml_parser->body, eml_parser->mimeinfo->dst, eml_parser->mimeinfo->actLen, 0); mail_publish_body(eml_parser->mq, eml_parser->body_topic_id, sess, eml_parser->protocol, eml_parser->mail_seq, eml_parser->body); } if (eml_parser->MailInfoState == MAIL_GET_COUNT_END) { mail_body_update(eml_parser->body, NULL, 0, 1); mail_publish_body(eml_parser->mq, eml_parser->body_topic_id, sess, eml_parser->protocol, eml_parser->mail_seq,eml_parser->body); mail_body_reset(eml_parser->body); } // attachment if (eml_parser->MailInfoState == MAIL_GET_FILENAME) { if (eml_parser->mimeinfo->filenameLen > 0) { mail_attachment_set_filename(eml_parser->current_attachment, eml_parser->mimeinfo->filename, eml_parser->mimeinfo->filenameLen); } } if (eml_parser->MailInfoState == MAIL_GET_FILECOUNT) { mail_attachment_update(eml_parser->current_attachment, eml_parser->mimeinfo->dst, eml_parser->mimeinfo->actLen, 0); mail_publish_attachment(eml_parser->mq, eml_parser->attachment_topic_id, sess, eml_parser->protocol, eml_parser->mail_seq, eml_parser->current_attachment); } if (eml_parser->MailInfoState == MAIL_GET_FILECOUNT_END) { mail_attachment_update(eml_parser->current_attachment, NULL, 0, 1); mail_publish_attachment(eml_parser->mq, eml_parser->attachment_topic_id, sess, eml_parser->protocol, eml_parser->mail_seq, eml_parser->current_attachment); mail_attachment_reset(eml_parser->current_attachment); } break; case EML_DATA_HEAD_BODY_BORDER: mail_publish_header(eml_parser->mq, eml_parser->header_topic_id, sess, eml_parser->protocol, eml_parser->mail_seq, eml_parser->header); eml_parser->header = NULL; eml_parser->EmlAnalyseState = MAIL_STAT_BODY; body_update_text_begin(eml_parser->mimeinfo); break; case EML_DATA_RETURN_PATH: case EML_DATA_RECEIVED: case EML_DATA_DELIVERED_TO: case EML_DATA_HEAD_IN: if (eml_parser->EmlAnalyseState != MAIL_STAT_HEADER) { eml_parser->EmlAnalyseState = MAIL_STAT_HEADER; } mail_header_add_field(eml_parser->header, email_line, line_len, 1); break; case EML_DATA_END: email_parser_reset(eml_parser); break; default: break; } return 0; }