diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/abstract/MCMessageConstants.h | 3 | ||||
-rw-r--r-- | src/core/abstract/MCMessageHeader.cc | 286 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSession.cc | 62 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSession.h | 32 |
4 files changed, 253 insertions, 130 deletions
diff --git a/src/core/abstract/MCMessageConstants.h b/src/core/abstract/MCMessageConstants.h index de68e767..a245eac3 100644 --- a/src/core/abstract/MCMessageConstants.h +++ b/src/core/abstract/MCMessageConstants.h @@ -68,6 +68,7 @@ namespace mailcore { IMAPMessagesRequestKindGmailLabels = 1 << 6, IMAPMessagesRequestKindGmailMessageID = 1 << 7, IMAPMessagesRequestKindGmailThreadID = 1 << 8, + IMAPMessagesRequestKindExtraHeaders = 1 << 9, }; enum IMAPFetchRequestType { @@ -227,4 +228,4 @@ namespace mailcore { #endif -#endif
\ No newline at end of file +#endif diff --git a/src/core/abstract/MCMessageHeader.cc b/src/core/abstract/MCMessageHeader.cc index bdeb6907..b45b0a4e 100644 --- a/src/core/abstract/MCMessageHeader.cc +++ b/src/core/abstract/MCMessageHeader.cc @@ -155,6 +155,11 @@ String * MessageHeader::description() if (mUserAgent != NULL) { result->appendUTF8Format("X-Mailer: %s\n", mUserAgent->UTF8Characters()); } + if (mExtraHeaders != NULL) { + mc_foreachdictionaryKeyAndValue(String, header, String, value, mExtraHeaders) { + result->appendUTF8Format("%s: %s\n", header->UTF8Characters(), value->UTF8Characters()); + } + } result->appendUTF8Format(">"); return result; @@ -355,127 +360,178 @@ void MessageHeader::importHeadersData(Data * data) } importIMFFields(fields); - + mailimf_fields_free(fields); } void MessageHeader::importIMFFields(struct mailimf_fields * fields) { - struct mailimf_single_fields single_fields; - - mailimf_single_fields_init(&single_fields, fields); - - /* date */ - - if (single_fields.fld_orig_date != NULL) { - time_t timestamp; - timestamp = timestamp_from_date(single_fields.fld_orig_date->dt_date_time); - setDate(timestamp); - setReceivedDate(timestamp); - //MCLog("%lu %lu", (unsigned long) timestamp, date()); - } - - /* subject */ - if (single_fields.fld_subject != NULL) { - char * subject; - - subject = single_fields.fld_subject->sbj_value; - setSubject(String::stringByDecodingMIMEHeaderValue(subject)); - } - - /* sender */ - if (single_fields.fld_sender != NULL) { - struct mailimf_mailbox * mb; - Address * address; - - mb = single_fields.fld_sender->snd_mb; - if (mb != NULL) { - address = Address::addressWithIMFMailbox(mb); - setSender(address); - } - } + clistiter * cur; + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + + field = (mailimf_field *)clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_ORIG_DATE: + // Set only if date is not set + if (date() == (time_t) -1) { + time_t timestamp; + + timestamp = timestamp_from_date(field->fld_data.fld_orig_date->dt_date_time); + setDate(timestamp); + setReceivedDate(timestamp); + } + break; + case MAILIMF_FIELD_SUBJECT: + // Set only if subject is not set + if (subject() == NULL) { + char * subject; + + subject = field->fld_data.fld_subject->sbj_value; + setSubject(String::stringByDecodingMIMEHeaderValue(subject)); + } + break; + case MAILIMF_FIELD_SENDER: + // Set only if sender is not set + if (sender() == NULL) { + struct mailimf_mailbox * mb; + Address * address; + + mb = field->fld_data.fld_sender->snd_mb; + if (mb != NULL) { + address = Address::addressWithIMFMailbox(mb); + setSender(address); + } + } + break; + case MAILIMF_FIELD_FROM: + // Set only if from is not set + if (from() == NULL) { + struct mailimf_mailbox_list * mb_list; + Array * addresses; + + mb_list = field->fld_data.fld_from->frm_mb_list; + addresses = lep_address_list_from_lep_mailbox(mb_list); + if (addresses->count() > 0) { + setFrom((Address *) (addresses->objectAtIndex(0))); + } + } + break; + case MAILIMF_FIELD_REPLY_TO: + // Set only if reply-to is not set + if (replyTo() == NULL) { + struct mailimf_address_list * addr_list; + Array * addresses; + + addr_list = field->fld_data.fld_reply_to->rt_addr_list; + addresses = lep_address_list_from_lep_addr(addr_list); + setReplyTo(addresses); + } + break; + case MAILIMF_FIELD_TO: + // Set only if to is not set + if (to() == NULL) { + struct mailimf_address_list * addr_list; + Array * addresses; + + addr_list = field->fld_data.fld_to->to_addr_list; + addresses = lep_address_list_from_lep_addr(addr_list); + setTo(addresses); + } + break; + case MAILIMF_FIELD_CC: + // Set only if cc is not set + if (cc() == NULL) { + struct mailimf_address_list * addr_list; + Array * addresses; + + addr_list = field->fld_data.fld_cc->cc_addr_list; + addresses = lep_address_list_from_lep_addr(addr_list); + setCc(addresses); + } + break; + case MAILIMF_FIELD_BCC: + // Set only if bcc is not set + if (bcc() == NULL) { + struct mailimf_address_list * addr_list; + Array * addresses; + + addr_list = field->fld_data.fld_bcc->bcc_addr_list; + addresses = lep_address_list_from_lep_addr(addr_list); + setBcc(addresses); + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + // message-id has a default value set by the constructor, so we can't check for NULL here + char * msgid; + String * str; + + msgid = field->fld_data.fld_message_id->mid_value; + str = String::stringWithUTF8Characters(msgid); + setMessageID(str); + break; + case MAILIMF_FIELD_REFERENCES: + // Set only if references is not set + if (references() == NULL) { + clist * msg_id_list; + Array * msgids; + + msg_id_list = field->fld_data.fld_references->mid_list; + msgids = msg_id_to_string_array(msg_id_list); + setReferences(msgids); + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + // Set only if in-reply-to is not set + if (inReplyTo() == NULL) { + clist * msg_id_list; + Array * msgids; + + msg_id_list = field->fld_data.fld_references->mid_list; + msgids = msg_id_to_string_array(msg_id_list); + setReferences(msgids); + } + break; + case MAILIMF_FIELD_COMMENTS: + // Set only if comments is not set + // TODO: Per RFC5322, multiple comments fields are allowed, should that here + if (headerValueForName(MCSTR("Comments")) == NULL) { + char * comments; + String * str; + + comments = field->fld_data.fld_comments->cm_value; + str = String::stringWithUTF8Characters(comments); + addHeader(MCSTR("Comments"), str); + } + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + char * fieldName; + String * fieldNameStr; + + fieldName = field->fld_data.fld_optional_field->fld_name; + fieldNameStr = String::stringWithUTF8Characters(fieldName); + // Set only if this optional-field is not set + if (headerValueForName(fieldNameStr) == NULL) { + char * fieldValue; + String * fieldValueStr; + + fieldValue = field->fld_data.fld_optional_field->fld_value; + fieldValueStr = String::stringWithUTF8Characters(fieldValue); + addHeader(fieldNameStr, fieldValueStr); + } + break; + case MAILIMF_FIELD_KEYWORDS: + // TODO: need deal with non-string headers in mExtraHeaders since Keywords is a list + break; + default: + break; + } + cur = clist_next(cur); + - /* from */ - if (single_fields.fld_from != NULL) { - struct mailimf_mailbox_list * mb_list; - Array * addresses; - - mb_list = single_fields.fld_from->frm_mb_list; - addresses = lep_address_list_from_lep_mailbox(mb_list); - if (addresses->count() > 0) { - setFrom((Address *) (addresses->objectAtIndex(0))); - } - } - - /* replyto */ - if (single_fields.fld_reply_to != NULL) { - struct mailimf_address_list * addr_list; - Array * addresses; - - addr_list = single_fields.fld_reply_to->rt_addr_list; - addresses = lep_address_list_from_lep_addr(addr_list); - setReplyTo(addresses); - } - - /* to */ - if (single_fields.fld_to != NULL) { - struct mailimf_address_list * addr_list; - Array * addresses; - - addr_list = single_fields.fld_to->to_addr_list; - addresses = lep_address_list_from_lep_addr(addr_list); - setTo(addresses); - } - - /* cc */ - if (single_fields.fld_cc != NULL) { - struct mailimf_address_list * addr_list; - Array * addresses; - - addr_list = single_fields.fld_cc->cc_addr_list; - addresses = lep_address_list_from_lep_addr(addr_list); - setCc(addresses); - } - - /* bcc */ - if (single_fields.fld_bcc != NULL) { - struct mailimf_address_list * addr_list; - Array * addresses; - - addr_list = single_fields.fld_bcc->bcc_addr_list; - addresses = lep_address_list_from_lep_addr(addr_list); - setBcc(addresses); - } - - /* msgid */ - if (single_fields.fld_message_id != NULL) { - char * msgid; - String * str; - - msgid = single_fields.fld_message_id->mid_value; - str = String::stringWithUTF8Characters(msgid); - setMessageID(str); - } - - /* references */ - if (single_fields.fld_references != NULL) { - clist * msg_id_list; - Array * msgids; - - msg_id_list = single_fields.fld_references->mid_list; - msgids = msg_id_to_string_array(msg_id_list); - setReferences(msgids); - } - - /* inreplyto */ - if (single_fields.fld_in_reply_to != NULL) { - clist * msg_id_list; - Array * msgids; - - msg_id_list = single_fields.fld_in_reply_to->mid_list; - msgids = msg_id_to_string_array(msg_id_list); - setInReplyTo(msgids); - } + } } static time_t timestamp_from_date(struct mailimf_date_time * date_time) diff --git a/src/core/imap/MCIMAPSession.cc b/src/core/imap/MCIMAPSession.cc index f4069b7d..fb82cea1 100644 --- a/src/core/imap/MCIMAPSession.cc +++ b/src/core/imap/MCIMAPSession.cc @@ -1722,7 +1722,8 @@ static void msg_att_handler(struct mailimap_msg_att * msg_att, void * context) hasHeader = true; } else if (att_static->att_type == MAILIMAP_MSG_ATT_BODY_SECTION) { - if ((requestKind & IMAPMessagesRequestKindFullHeaders) != 0) { + if ((requestKind & IMAPMessagesRequestKindFullHeaders) != 0 || + (requestKind & IMAPMessagesRequestKindExtraHeaders) != 0) { char * bytes; size_t length; @@ -1849,7 +1850,7 @@ static void msg_att_handler(struct mailimap_msg_att * msg_att, void * context) IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, bool fetchByUID, struct mailimap_set * imapset, uint64_t modseq, HashMap * mapping, uint32_t startUid, - IMAPProgressCallback * progressCallback, ErrorCode * pError) + IMAPProgressCallback * progressCallback, Array * extraHeaders, ErrorCode * pError) { struct mailimap_fetch_type * fetch_type; clist * fetch_result; @@ -1986,6 +1987,28 @@ IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequest fetch_att = mailimap_fetch_att_new_internaldate(); mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); } + if ((requestKind & IMAPMessagesRequestKindExtraHeaders) != 0) { + // custom header request + clist * hdrlist; + char * header; + struct mailimap_header_list * imap_hdrlist; + struct mailimap_section * section; + + if (extraHeaders && extraHeaders->count() > 0) { + hdrlist = clist_new(); + for (unsigned int i = 0; i < extraHeaders->count(); i++) { + String *headerString = (String *)extraHeaders->objectAtIndex(i); + header = strdup(headerString->UTF8Characters()); + clist_append(hdrlist, header); + } + + imap_hdrlist = mailimap_header_list_new(hdrlist); + section = mailimap_section_new_header_fields(imap_hdrlist); + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + needsHeader = true; + } + } struct msg_att_handler_data msg_att_data; @@ -2086,7 +2109,7 @@ IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequest requestKind = (IMAPMessagesRequestKind) (requestKind | IMAPMessagesRequestKindFullHeaders); result = fetchMessages(folder, requestKind, fetchByUID, - imapset, modseq, NULL, startUid, progressCallback, pError); + imapset, modseq, NULL, startUid, progressCallback, extraHeaders, pError); if (result != NULL) { if (result->modifiedOrAddedMessages() != NULL) { if (result->modifiedOrAddedMessages()->count() > 0) { @@ -2107,9 +2130,17 @@ IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequest Array * IMAPSession::fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, IndexSet * uids, IMAPProgressCallback * progressCallback, ErrorCode * pError) { + return fetchMessagesByUIDWithExtraHeaders(folder, requestKind, uids, progressCallback, NULL, pError); +} + + +Array * IMAPSession::fetchMessagesByUIDWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError) +{ struct mailimap_set * imapset = setFromIndexSet(uids); IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, true, imapset, 0, NULL, 0, - progressCallback, pError); + progressCallback, extraHeaders, pError); if (syncResult == NULL) return NULL; Array * result = syncResult->modifiedOrAddedMessages(); @@ -2119,11 +2150,19 @@ Array * IMAPSession::fetchMessagesByUID(String * folder, IMAPMessagesRequestKind } Array * IMAPSession::fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * numbers, IMAPProgressCallback * progressCallback, ErrorCode * pError) + IndexSet * numbers, IMAPProgressCallback * progressCallback, + ErrorCode * pError) +{ + return fetchMessagesByNumberWithExtraHeaders(folder, requestKind, numbers, progressCallback, NULL, pError); +} + +Array * IMAPSession::fetchMessagesByNumberWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * numbers, IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError) { struct mailimap_set * imapset = setFromIndexSet(numbers); IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, false, imapset, 0, NULL, 0, - progressCallback, pError); + progressCallback, extraHeaders, pError); if (syncResult == NULL) return NULL; Array * result = syncResult->modifiedOrAddedMessages(); @@ -2916,13 +2955,22 @@ IMAPSyncResult * IMAPSession::syncMessagesByUID(String * folder, IMAPMessagesReq IndexSet * uids, uint64_t modseq, IMAPProgressCallback * progressCallback, ErrorCode * pError) { + return syncMessagesByUIDWithExtraHeaders(folder, requestKind, uids, modseq, progressCallback, NULL, pError); +} + +IMAPSyncResult * IMAPSession::syncMessagesByUIDWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, Array * extraHeaders, + ErrorCode * pError) +{ MCAssert(uids->rangesCount() > 0); struct mailimap_set * imapset = setFromIndexSet(uids); IMAPSyncResult * result = fetchMessages(folder, requestKind, true, imapset, modseq, NULL, (uint32_t) uids->allRanges()[0].location, - progressCallback, pError); + progressCallback, extraHeaders, pError); mailimap_set_free(imapset); return result; + } IndexSet * IMAPSession::capability(ErrorCode * pError) diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h index 2ea3443b..4128b516 100644 --- a/src/core/imap/MCIMAPSession.h +++ b/src/core/imap/MCIMAPSession.h @@ -88,10 +88,22 @@ namespace mailcore { virtual void expunge(String * folder, ErrorCode * pError); virtual Array * /* IMAPMessage */ fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * uids, IMAPProgressCallback * progressCallback, ErrorCode * pError); + IndexSet * uids, IMAPProgressCallback * progressCallback, + ErrorCode * pError); + virtual Array * /* IMAPMessage */ fetchMessagesByUIDWithExtraHeaders(String * folder, + IMAPMessagesRequestKind requestKind, + IndexSet * uids, + IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError); virtual Array * /* IMAPMessage */ fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * numbers, IMAPProgressCallback * progressCallback, ErrorCode * pError); - + IndexSet * numbers, IMAPProgressCallback * progressCallback, + ErrorCode * pError); + virtual Array * /* IMAPMessage */ fetchMessagesByNumberWithExtraHeaders(String * folder, + IMAPMessagesRequestKind requestKind, + IndexSet * numbers, + IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError); + virtual Data * fetchMessageByUID(String * folder, uint32_t uid, IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual Data * fetchMessageAttachmentByUID(String * folder, uint32_t uid, String * partID, @@ -103,7 +115,12 @@ namespace mailcore { virtual IMAPSyncResult * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, IndexSet * uids, uint64_t modseq, IMAPProgressCallback * progressCallback, ErrorCode * pError); - + /* Same as syncMessagesByUID, allows for extra headers */ + virtual IMAPSyncResult * syncMessagesByUIDWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError); + virtual void storeFlags(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, ErrorCode * pError); virtual void storeLabels(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError); @@ -209,9 +226,10 @@ namespace mailcore { void unsetup(); void selectIfNeeded(String * folder, ErrorCode * pError); char fetchDelimiterIfNeeded(char defaultDelimiter, ErrorCode * pError); - IMAPSyncResult * fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, bool fetchByUID, - struct mailimap_set * imapset, uint64_t modseq, HashMap * mapping, uint32_t startUid, - IMAPProgressCallback * progressCallback, ErrorCode * pError); + IMAPSyncResult * fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, + bool fetchByUID, struct mailimap_set * imapset, uint64_t modseq, + HashMap * mapping, uint32_t startUid, IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError); }; } |