aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Hoà V. DINH <dinh.viet.hoa@gmail.com>2013-07-20 21:50:10 -0700
committerGravatar Hoà V. DINH <dinh.viet.hoa@gmail.com>2013-07-20 21:50:10 -0700
commitbe49d5c6ecba1d06e4969b0a3895bd840fb3f480 (patch)
tree8e8fd5100a410bee1085f9d147c4db80e5c42af1 /src/core
parent1e319987c2d5f533aac37831026aab22d84a6ebd (diff)
parentc2141d30d2feecd694620efc01692934816b4968 (diff)
Merge pull request #204 from thusfresh/CustomReceiveHeaders
Allows for requesting optional headers when fetching messages.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/abstract/MCMessageConstants.h3
-rw-r--r--src/core/abstract/MCMessageHeader.cc286
-rw-r--r--src/core/imap/MCIMAPSession.cc62
-rw-r--r--src/core/imap/MCIMAPSession.h32
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);
};
}