diff options
author | Dmitry Isaikin <isaikin@corp.mail.ru> | 2016-02-02 19:23:58 +0300 |
---|---|---|
committer | Dmitry Isaikin <isaikin@corp.mail.ru> | 2016-02-09 15:53:40 +0300 |
commit | f9cdd2e6193cddfa405723eb70dda9261b26848d (patch) | |
tree | 0448dfc39864b9d52b55d5ad7a91d16d15bb2c71 /src | |
parent | 908b7d4b8fdd7be43687450a36d56a6fb905ca25 (diff) |
Add file-based interface for sending messages via SMTP (reduce memory usage)
Diffstat (limited to 'src')
-rw-r--r-- | src/async/imap/MCIMAPAppendMessageOperation.cpp | 19 | ||||
-rw-r--r-- | src/async/imap/MCIMAPAppendMessageOperation.h | 6 | ||||
-rwxr-xr-x | src/async/imap/MCIMAPAsyncSession.cpp | 12 | ||||
-rwxr-xr-x | src/async/imap/MCIMAPAsyncSession.h | 3 | ||||
-rw-r--r-- | src/async/smtp/MCSMTPAsyncSession.cpp | 11 | ||||
-rw-r--r-- | src/async/smtp/MCSMTPAsyncSession.h | 2 | ||||
-rw-r--r-- | src/async/smtp/MCSMTPSendWithDataOperation.cpp | 16 | ||||
-rw-r--r-- | src/async/smtp/MCSMTPSendWithDataOperation.h | 7 | ||||
-rwxr-xr-x | src/core/imap/MCIMAPSession.cpp | 12 | ||||
-rwxr-xr-x | src/core/imap/MCIMAPSession.h | 4 | ||||
-rw-r--r-- | src/core/smtp/MCSMTPSession.cpp | 51 | ||||
-rw-r--r-- | src/core/smtp/MCSMTPSession.h | 4 | ||||
-rwxr-xr-x | src/objc/imap/MCOIMAPSession.h | 18 | ||||
-rwxr-xr-x | src/objc/imap/MCOIMAPSession.mm | 12 | ||||
-rw-r--r-- | src/objc/smtp/MCOSMTPSession.h | 18 | ||||
-rw-r--r-- | src/objc/smtp/MCOSMTPSession.mm | 13 |
16 files changed, 189 insertions, 19 deletions
diff --git a/src/async/imap/MCIMAPAppendMessageOperation.cpp b/src/async/imap/MCIMAPAppendMessageOperation.cpp index 23eaaea0..69ed5c5f 100644 --- a/src/async/imap/MCIMAPAppendMessageOperation.cpp +++ b/src/async/imap/MCIMAPAppendMessageOperation.cpp @@ -16,6 +16,7 @@ using namespace mailcore; IMAPAppendMessageOperation::IMAPAppendMessageOperation() { mMessageData = NULL; + mMessageFilepath = NULL; mFlags = MessageFlagNone; mCustomFlags = NULL; mDate = (time_t) -1; @@ -25,6 +26,7 @@ IMAPAppendMessageOperation::IMAPAppendMessageOperation() IMAPAppendMessageOperation::~IMAPAppendMessageOperation() { MC_SAFE_RELEASE(mMessageData); + MC_SAFE_RELEASE(mMessageFilepath); MC_SAFE_RELEASE(mCustomFlags); } @@ -38,6 +40,16 @@ Data * IMAPAppendMessageOperation::messageData() return mMessageData; } +void IMAPAppendMessageOperation::setMessageFilepath(String * path) +{ + MC_SAFE_REPLACE_RETAIN(String, mMessageFilepath, path); +} + +String * IMAPAppendMessageOperation::messageFilepath() +{ + return mMessageFilepath; +} + void IMAPAppendMessageOperation::setFlags(MessageFlag flags) { mFlags = flags; @@ -76,7 +88,12 @@ uint32_t IMAPAppendMessageOperation::createdUID() void IMAPAppendMessageOperation::main() { ErrorCode error; - session()->session()->appendMessageWithCustomFlagsAndDate(folder(), mMessageData, mFlags, mCustomFlags, mDate, this, &mCreatedUID, &error); + if (mMessageFilepath != NULL) { + session()->session()->appendMessageWithCustomFlagsAndDate(folder(), mMessageFilepath, mFlags, mCustomFlags, mDate, this, &mCreatedUID, &error); + } + else { + session()->session()->appendMessageWithCustomFlagsAndDate(folder(), mMessageData, mFlags, mCustomFlags, mDate, this, &mCreatedUID, &error); + } setError(error); } diff --git a/src/async/imap/MCIMAPAppendMessageOperation.h b/src/async/imap/MCIMAPAppendMessageOperation.h index ca3033a6..f711c988 100644 --- a/src/async/imap/MCIMAPAppendMessageOperation.h +++ b/src/async/imap/MCIMAPAppendMessageOperation.h @@ -24,7 +24,10 @@ namespace mailcore { virtual void setMessageData(Data * messageData); virtual Data * messageData(); - + + virtual void setMessageFilepath(String * path); + virtual String * messageFilepath(); + virtual void setFlags(MessageFlag flags); virtual MessageFlag flags(); @@ -41,6 +44,7 @@ namespace mailcore { private: Data * mMessageData; + String * mMessageFilepath; MessageFlag mFlags; Array * mCustomFlags; time_t mDate; diff --git a/src/async/imap/MCIMAPAsyncSession.cpp b/src/async/imap/MCIMAPAsyncSession.cpp index 7f00d105..676d9bc5 100755 --- a/src/async/imap/MCIMAPAsyncSession.cpp +++ b/src/async/imap/MCIMAPAsyncSession.cpp @@ -443,6 +443,18 @@ IMAPAppendMessageOperation * IMAPAsyncSession::appendMessageOperation(String * f return op; } +IMAPAppendMessageOperation * IMAPAsyncSession::appendMessageOperation(String * folder, String * messagePath, MessageFlag flags, Array * customFlags) +{ + IMAPAppendMessageOperation * op = new IMAPAppendMessageOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setMessageFilepath(messagePath); + op->setFlags(flags); + op->setCustomFlags(customFlags); + op->autorelease(); + return op; +} + IMAPCopyMessagesOperation * IMAPAsyncSession::copyMessagesOperation(String * folder, IndexSet * uids, String * destFolder) { IMAPCopyMessagesOperation * op = new IMAPCopyMessagesOperation(); diff --git a/src/async/imap/MCIMAPAsyncSession.h b/src/async/imap/MCIMAPAsyncSession.h index bbffacbd..b92d8017 100755 --- a/src/async/imap/MCIMAPAsyncSession.h +++ b/src/async/imap/MCIMAPAsyncSession.h @@ -120,7 +120,8 @@ namespace mailcore { virtual IMAPOperation * unsubscribeFolderOperation(String * folder); virtual IMAPAppendMessageOperation * appendMessageOperation(String * folder, Data * messageData, MessageFlag flags, Array * customFlags = NULL); - + virtual IMAPAppendMessageOperation * appendMessageOperation(String * folder, String * messagePath, MessageFlag flags, Array * customFlags = NULL); + virtual IMAPCopyMessagesOperation * copyMessagesOperation(String * folder, IndexSet * uids, String * destFolder); virtual IMAPMoveMessagesOperation * moveMessagesOperation(String * folder, IndexSet * uids, String * destFolder); diff --git a/src/async/smtp/MCSMTPAsyncSession.cpp b/src/async/smtp/MCSMTPAsyncSession.cpp index d2f645da..46b25184 100644 --- a/src/async/smtp/MCSMTPAsyncSession.cpp +++ b/src/async/smtp/MCSMTPAsyncSession.cpp @@ -240,6 +240,17 @@ SMTPOperation * SMTPAsyncSession::sendMessageOperation(Address * from, Array * r return (SMTPOperation *) op->autorelease(); } +SMTPOperation * SMTPAsyncSession::sendMessageOperation(Address * from, Array * recipients, + String * filename) +{ + SMTPSendWithDataOperation * op = new SMTPSendWithDataOperation(); + op->setSession(this); + op->setMessageFilepath(filename); + op->setFrom(from); + op->setRecipients(recipients); + return (SMTPOperation *) op->autorelease(); +} + SMTPOperation * SMTPAsyncSession::checkAccountOperation(Address * from) { SMTPCheckAccountOperation * op = new SMTPCheckAccountOperation(); diff --git a/src/async/smtp/MCSMTPAsyncSession.h b/src/async/smtp/MCSMTPAsyncSession.h index 90849797..961df6ef 100644 --- a/src/async/smtp/MCSMTPAsyncSession.h +++ b/src/async/smtp/MCSMTPAsyncSession.h @@ -68,6 +68,8 @@ namespace mailcore { virtual SMTPOperation * sendMessageOperation(Data * messageData); virtual SMTPOperation * sendMessageOperation(Address * from, Array * recipients, Data * messageData); + virtual SMTPOperation * sendMessageOperation(Address * from, Array * recipients, + String * filename); virtual SMTPOperation * checkAccountOperation(Address * from); virtual SMTPOperation * noopOperation(); diff --git a/src/async/smtp/MCSMTPSendWithDataOperation.cpp b/src/async/smtp/MCSMTPSendWithDataOperation.cpp index 03f6a530..4561b5d8 100644 --- a/src/async/smtp/MCSMTPSendWithDataOperation.cpp +++ b/src/async/smtp/MCSMTPSendWithDataOperation.cpp @@ -16,6 +16,7 @@ using namespace mailcore; SMTPSendWithDataOperation::SMTPSendWithDataOperation() { mMessageData = NULL; + mMessageFilepath = NULL; mFrom = NULL; mRecipients = NULL; } @@ -24,6 +25,7 @@ SMTPSendWithDataOperation::~SMTPSendWithDataOperation() { MC_SAFE_RELEASE(mFrom); MC_SAFE_RELEASE(mRecipients); + MC_SAFE_RELEASE(mMessageFilepath); MC_SAFE_RELEASE(mMessageData); } @@ -37,6 +39,16 @@ Data * SMTPSendWithDataOperation::messageData() return mMessageData; } +void SMTPSendWithDataOperation::setMessageFilepath(String * path) +{ + MC_SAFE_REPLACE_RETAIN(String, mMessageFilepath, path); +} + +String * SMTPSendWithDataOperation::messageFilepath() +{ + return mMessageFilepath; +} + void SMTPSendWithDataOperation::setFrom(Address * from) { MC_SAFE_REPLACE_COPY(Address, mFrom, from); @@ -60,6 +72,10 @@ Array * SMTPSendWithDataOperation::recipients() void SMTPSendWithDataOperation::main() { ErrorCode error; + if (mMessageFilepath != NULL) { + session()->session()->sendMessage(mFrom, mRecipients, mMessageFilepath, this, &error); + } + else if ((mFrom != NULL) && (mRecipients != NULL)) { session()->session()->sendMessage(mFrom, mRecipients, mMessageData, this, &error); } diff --git a/src/async/smtp/MCSMTPSendWithDataOperation.h b/src/async/smtp/MCSMTPSendWithDataOperation.h index a8ee2515..768adda9 100644 --- a/src/async/smtp/MCSMTPSendWithDataOperation.h +++ b/src/async/smtp/MCSMTPSendWithDataOperation.h @@ -31,15 +31,18 @@ namespace mailcore { virtual void setMessageData(Data * data); virtual Data * messageData(); - + + virtual void setMessageFilepath(String * path); + virtual String * messageFilepath(); + public: // subclass behavior virtual void main(); private: Data * mMessageData; + String * mMessageFilepath; Array * mRecipients; Address * mFrom; - }; } diff --git a/src/core/imap/MCIMAPSession.cpp b/src/core/imap/MCIMAPSession.cpp index c1209c9d..bc522896 100755 --- a/src/core/imap/MCIMAPSession.cpp +++ b/src/core/imap/MCIMAPSession.cpp @@ -1655,6 +1655,18 @@ void IMAPSession::appendMessageWithCustomFlagsAndDate(String * folder, Data * me * pError = ErrorNone; } +void IMAPSession::appendMessageWithCustomFlagsAndDate(String * folder, String * messagePath, MessageFlag flags, Array * customFlags, time_t date, + IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError) +{ + Data * messageData = Data::dataWithContentsOfFile(messagePath); + if (!messageData) { + * pError = ErrorFile; + return; + } + + return appendMessageWithCustomFlagsAndDate(folder, messageData, flags, customFlags, date, progressCallback, createdUID, pError); +} + void IMAPSession::copyMessages(String * folder, IndexSet * uidSet, String * destFolder, HashMap ** pUidMapping, ErrorCode * pError) { diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h index c122e546..578350ac 100755 --- a/src/core/imap/MCIMAPSession.h +++ b/src/core/imap/MCIMAPSession.h @@ -85,7 +85,9 @@ namespace mailcore { IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError); virtual void appendMessageWithCustomFlagsAndDate(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, time_t date, IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError); - + virtual void appendMessageWithCustomFlagsAndDate(String * folder, String * messagePath, MessageFlag flags, Array * customFlags, time_t date, + IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError); + virtual void copyMessages(String * folder, IndexSet * uidSet, String * destFolder, HashMap ** pUidMapping, ErrorCode * pError); diff --git a/src/core/smtp/MCSMTPSession.cpp b/src/core/smtp/MCSMTPSession.cpp index d0711c65..8bcaefff 100644 --- a/src/core/smtp/MCSMTPSession.cpp +++ b/src/core/smtp/MCSMTPSession.cpp @@ -617,7 +617,7 @@ void SMTPSession::sendMessage(Address * from, Array * recipients, Data * message } messageData = dataWithFilteredBcc(messageData); - + mProgressCallback = callback; bodyProgress(0, messageData->length()); @@ -717,13 +717,28 @@ void SMTPSession::sendMessage(Address * from, Array * recipients, Data * message mProgressCallback = NULL; } +void SMTPSession::sendMessage(Address * from, Array * recipients, String * messagePath, + SMTPProgressCallback * callback, ErrorCode * pError) +{ + Data * messageData = Data::dataWithContentsOfFile(messagePath); + if (!messageData) { + * pError = ErrorFile; + return; + } + + return sendMessage(from, recipients, messageData, callback, pError); +} + +static void mmapStringDeallocator(char * bytes, unsigned int length) { + mmap_string_unref(bytes); +} + Data * SMTPSession::dataWithFilteredBcc(Data * data) { int r; size_t idx; struct mailimf_message * msg; - MMAPString * str; - + idx = 0; r = mailimf_message_parse(data->bytes(), data->length(), &idx, &msg); if (r != MAILIMF_NO_ERROR) { @@ -734,15 +749,16 @@ Data * SMTPSession::dataWithFilteredBcc(Data * data) int col = 0; int hasRecipient = 0; - str = mmap_string_new(""); + bool bccWasActuallyRemoved = false; for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimf_field * field = (struct mailimf_field *) clist_content(cur); if (field->fld_type == MAILIMF_FIELD_BCC) { mailimf_field_free(field); clist_delete(fields->fld_list, cur); + bccWasActuallyRemoved = true; break; } - else if ((field->fld_type == MAILIMF_FIELD_TO) || (field->fld_type == MAILIMF_FIELD_CC) || (field->fld_type == MAILIMF_FIELD_BCC)) { + else if ((field->fld_type == MAILIMF_FIELD_TO) || (field->fld_type == MAILIMF_FIELD_CC)) { hasRecipient = 1; } } @@ -754,13 +770,24 @@ Data * SMTPSession::dataWithFilteredBcc(Data * data) struct mailimf_field * field = mailimf_field_new(MAILIMF_FIELD_TO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, toField, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); mailimf_fields_add(fields, field); } - mailimf_fields_write_mem(str, &col, fields); - mmap_string_append(str, "\n"); - mmap_string_append_len(str, msg->msg_body->bd_text, msg->msg_body->bd_size); - - Data * result = Data::dataWithBytes(str->str, (unsigned int) str->len); - - mmap_string_free(str); + + Data * result; + if (!hasRecipient || bccWasActuallyRemoved) { + MMAPString * str = mmap_string_new(""); + mailimf_fields_write_mem(str, &col, fields); + mmap_string_append(str, "\n"); + mmap_string_append_len(str, msg->msg_body->bd_text, msg->msg_body->bd_size); + + mmap_string_ref(str); + + result = Data::data(); + result->takeBytesOwnership(str->str, (unsigned int) str->len, mmapStringDeallocator); + } + else { + // filter Bcc and modify To: only if necessary. + result = data; + } + mailimf_message_free(msg); return result; diff --git a/src/core/smtp/MCSMTPSession.h b/src/core/smtp/MCSMTPSession.h index 05571bfb..64ff30d0 100644 --- a/src/core/smtp/MCSMTPSession.h +++ b/src/core/smtp/MCSMTPSession.h @@ -60,7 +60,9 @@ namespace mailcore { virtual void sendMessage(Data * messageData, SMTPProgressCallback * callback, ErrorCode * pError); virtual void sendMessage(Address * from, Array * /* Address */ recipients, Data * messageData, SMTPProgressCallback * callback, ErrorCode * pError); - + virtual void sendMessage(Address * from, Array * /* Address */ recipients, String * messagePath, + SMTPProgressCallback * callback, ErrorCode * pError); + virtual void setConnectionLogger(ConnectionLogger * logger); virtual ConnectionLogger * connectionLogger(); diff --git a/src/objc/imap/MCOIMAPSession.h b/src/objc/imap/MCOIMAPSession.h index bab3be7f..6fd5f76e 100755 --- a/src/objc/imap/MCOIMAPSession.h +++ b/src/objc/imap/MCOIMAPSession.h @@ -305,6 +305,24 @@ customFlags:(NSArray *)customFlags; /** + Returns an operation to add a message with custom flags to a folder. + + MCOIMAPOperation * op = [session appendMessageOperationWithFolder:@"Sent Mail" + contentsAtPath:rfc822DataFilename + flags:MCOMessageFlagNone + customFlags:@[@"$CNS-Greeting-On"]]; + [op start:^(NSError * __nullable error, uint32_t createdUID) { + if (error == nil) { + NSLog(@"created message with UID %lu", (unsigned long) createdUID); + } + }]; + */ +- (MCOIMAPAppendMessageOperation *)appendMessageOperationWithFolder:(NSString *)folder + contentsAtPath:(NSString *)path + flags:(MCOMessageFlag)flags + customFlags:(NSArray *)customFlags; + +/** Returns an operation to copy messages to a folder. MCOIMAPCopyMessagesOperation * op = [session copyMessagesOperationWithFolder:@"INBOX" diff --git a/src/objc/imap/MCOIMAPSession.mm b/src/objc/imap/MCOIMAPSession.mm index 32dd1119..c245cdc3 100755 --- a/src/objc/imap/MCOIMAPSession.mm +++ b/src/objc/imap/MCOIMAPSession.mm @@ -264,6 +264,18 @@ MCO_OBJC_SYNTHESIZE_SCALAR(dispatch_queue_t, dispatch_queue_t, setDispatchQueue, return MCO_TO_OBJC_OP(coreOp); } +- (MCOIMAPAppendMessageOperation *)appendMessageOperationWithFolder:(NSString *)folder + contentsAtPath:(NSString *)path + flags:(MCOMessageFlag)flags + customFlags:(NSArray *)customFlags +{ + IMAPAppendMessageOperation * coreOp = MCO_NATIVE_INSTANCE->appendMessageOperation([folder mco_mcString], + MCO_FROM_OBJC(String, path), + (MessageFlag) flags, + MCO_FROM_OBJC(Array, customFlags)); + return MCO_TO_OBJC_OP(coreOp); +} + - (MCOIMAPCopyMessagesOperation *)copyMessagesOperationWithFolder:(NSString *)folder uids:(MCOIndexSet *)uids destFolder:(NSString *)destFolder diff --git a/src/objc/smtp/MCOSMTPSession.h b/src/objc/smtp/MCOSMTPSession.h index 31055335..84d6949d 100644 --- a/src/objc/smtp/MCOSMTPSession.h +++ b/src/objc/smtp/MCOSMTPSession.h @@ -154,6 +154,24 @@ from:(MCOAddress *)from recipients:(NSArray *)recipients; + +/** + Returns an operation that will send the message from the given file through SMTP. + It will use the sender and recipient set from the parameters. + It will also filter out Bcc from the content of the message. + + MCOSMTPOperation * op = [session sendOperationWithContentsOfFile:rfc822DataFilename + from:[MCOAddress addressWithMailbox:@"hoa@etpan.org"] + recipients:[NSArray arrayWithObject: + [MCOAddress addressWithMailbox:@"laura@etpan.org"]]]; + [op start:^(NSError * __nullable error) { + ... + }]; + */ +- (MCOSMTPSendOperation *) sendOperationWithContentsOfFile:(NSString *)path + from:(MCOAddress *)from + recipients:(NSArray *)recipients; + /** Returns an operation that will check whether the SMTP account is valid. diff --git a/src/objc/smtp/MCOSMTPSession.mm b/src/objc/smtp/MCOSMTPSession.mm index 9bcbd48e..9406a719 100644 --- a/src/objc/smtp/MCOSMTPSession.mm +++ b/src/objc/smtp/MCOSMTPSession.mm @@ -170,6 +170,19 @@ MCO_OBJC_SYNTHESIZE_SCALAR(dispatch_queue_t, dispatch_queue_t, setDispatchQueue, return result; } +- (MCOSMTPSendOperation *) sendOperationWithContentsOfFile:(NSString *)path + from:(MCOAddress *)from + recipients:(NSArray *)recipients +{ + mailcore::SMTPOperation * coreOp = + MCO_NATIVE_INSTANCE->sendMessageOperation(MCO_FROM_OBJC(Address, from), + MCO_FROM_OBJC(Array, recipients), + MCO_FROM_OBJC(String, path)); + MCOSMTPSendOperation * result = [[[MCOSMTPSendOperation alloc] initWithMCOperation:coreOp] autorelease]; + [result setSession:self]; + return result; +} + - (MCOSMTPOperation *) checkAccountOperationWithFrom:(MCOAddress *)from { mailcore::SMTPOperation *coreOp = MCO_NATIVE_INSTANCE->checkAccountOperation(MCO_FROM_OBJC(mailcore::Address, from)); |