aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Hoà V. DINH <dinh.viet.hoa@gmail.com>2016-02-26 07:43:33 -0800
committerGravatar Hoà V. DINH <dinh.viet.hoa@gmail.com>2016-02-26 07:43:33 -0800
commiteac836a9858e765e0fb07f1b1f4b325893666fe6 (patch)
tree42b328e5b80752776658de78cea84a38afec4c3e /src
parentdbd4f63735beab5f2014597d3b1e0d67af03fe97 (diff)
parent38cae4a0a329da2618c212f545d3d8e10417af72 (diff)
Merge pull request #1367 from CTMacUser/NNTPSendOperation
Add upload functionality to NNTP sessions.
Diffstat (limited to 'src')
-rw-r--r--src/async/nntp/MCAsyncNNTP.h1
-rw-r--r--src/async/nntp/MCNNTPAsyncSession.cpp19
-rw-r--r--src/async/nntp/MCNNTPAsyncSession.h4
-rw-r--r--src/async/nntp/MCNNTPPostOperation.cpp58
-rw-r--r--src/async/nntp/MCNNTPPostOperation.h44
-rw-r--r--src/cmake/async.cmake1
-rw-r--r--src/cmake/objc.cmake1
-rw-r--r--src/cmake/public-headers.cmake2
-rw-r--r--src/core/nntp/MCNNTPSession.cpp135
-rw-r--r--src/core/nntp/MCNNTPSession.h7
-rw-r--r--src/objc/nntp/MCONNTP.h1
-rw-r--r--src/objc/nntp/MCONNTPFetchArticleOperation.h4
-rw-r--r--src/objc/nntp/MCONNTPOperation.h4
-rw-r--r--src/objc/nntp/MCONNTPPostOperation.h37
-rw-r--r--src/objc/nntp/MCONNTPPostOperation.mm116
-rw-r--r--src/objc/nntp/MCONNTPSession.h27
-rw-r--r--src/objc/nntp/MCONNTPSession.mm12
17 files changed, 469 insertions, 4 deletions
diff --git a/src/async/nntp/MCAsyncNNTP.h b/src/async/nntp/MCAsyncNNTP.h
index 914cc754..326138dc 100644
--- a/src/async/nntp/MCAsyncNNTP.h
+++ b/src/async/nntp/MCAsyncNNTP.h
@@ -18,6 +18,7 @@
#include <MailCore/MCNNTPListNewsgroupsOperation.h>
#include <MailCore/MCNNTPFetchOverviewOperation.h>
#include <MailCore/MCNNTPFetchServerTimeOperation.h>
+#include <MailCore/MCNNTPPostOperation.h>
#include <MailCore/MCNNTPOperationCallback.h>
#endif
diff --git a/src/async/nntp/MCNNTPAsyncSession.cpp b/src/async/nntp/MCNNTPAsyncSession.cpp
index ad74f7a9..eeed1244 100644
--- a/src/async/nntp/MCNNTPAsyncSession.cpp
+++ b/src/async/nntp/MCNNTPAsyncSession.cpp
@@ -16,6 +16,7 @@
#include "MCNNTPFetchOverviewOperation.h"
#include "MCNNTPCheckAccountOperation.h"
#include "MCNNTPFetchServerTimeOperation.h"
+#include "MCNNTPPostOperation.h"
#include "MCNNTPDisconnectOperation.h"
#include "MCOperationQueueCallback.h"
#include "MCConnectionLogger.h"
@@ -236,6 +237,24 @@ NNTPListNewsgroupsOperation * NNTPAsyncSession::listDefaultNewsgroupsOperation()
return op;
}
+NNTPPostOperation * NNTPAsyncSession::postMessageOperation(Data * messageData)
+{
+ NNTPPostOperation * op = new NNTPPostOperation();
+ op->setSession(this);
+ op->setMessageData(messageData);
+ op->autorelease();
+ return op;
+}
+
+NNTPPostOperation * NNTPAsyncSession::postMessageOperation(String * filename)
+{
+ NNTPPostOperation * op = new NNTPPostOperation();
+ op->setSession(this);
+ op->setMessageFilepath(filename);
+ op->autorelease();
+ return op;
+}
+
NNTPOperation * NNTPAsyncSession::disconnectOperation()
{
NNTPDisconnectOperation * op = new NNTPDisconnectOperation();
diff --git a/src/async/nntp/MCNNTPAsyncSession.h b/src/async/nntp/MCNNTPAsyncSession.h
index b3e40ea8..eb2531a4 100644
--- a/src/async/nntp/MCNNTPAsyncSession.h
+++ b/src/async/nntp/MCNNTPAsyncSession.h
@@ -16,6 +16,7 @@ namespace mailcore {
class NNTPFetchOverviewOperation;
class NNTPListNewsgroupsOperation;
class NNTPFetchServerTimeOperation;
+ class NNTPPostOperation;
class NNTPOperationQueueCallback;
class NNTPConnectionLogger;
@@ -72,6 +73,9 @@ namespace mailcore {
virtual NNTPListNewsgroupsOperation * listAllNewsgroupsOperation();
virtual NNTPListNewsgroupsOperation * listDefaultNewsgroupsOperation();
+ virtual NNTPPostOperation * postMessageOperation(Data * messageData);
+ virtual NNTPPostOperation * postMessageOperation(String * filename);
+
virtual NNTPOperation * disconnectOperation();
virtual NNTPOperation * checkAccountOperation();
diff --git a/src/async/nntp/MCNNTPPostOperation.cpp b/src/async/nntp/MCNNTPPostOperation.cpp
new file mode 100644
index 00000000..c5b586f5
--- /dev/null
+++ b/src/async/nntp/MCNNTPPostOperation.cpp
@@ -0,0 +1,58 @@
+//
+// MCNNTPPostOperation.cpp
+// mailcore2
+//
+// Created by Daryle Walker on 2/21/16.
+// Copyright © 2016 MailCore. All rights reserved.
+//
+
+#include "MCNNTPPostOperation.h"
+
+#include "MCNNTPAsyncSession.h"
+#include "MCNNTPSession.h"
+
+using namespace mailcore;
+
+NNTPPostOperation::NNTPPostOperation()
+{
+ mMessageData = NULL;
+ mMessageFilepath = NULL;
+}
+
+NNTPPostOperation::~NNTPPostOperation()
+{
+ MC_SAFE_RELEASE(mMessageFilepath);
+ MC_SAFE_RELEASE(mMessageData);
+}
+
+void NNTPPostOperation::setMessageData(Data * data)
+{
+ MC_SAFE_REPLACE_RETAIN(Data, mMessageData, data);
+}
+
+Data * NNTPPostOperation::messageData()
+{
+ return mMessageData;
+}
+
+void NNTPPostOperation::setMessageFilepath(String * path)
+{
+ MC_SAFE_REPLACE_RETAIN(String, mMessageFilepath, path);
+}
+
+String * NNTPPostOperation::messageFilepath()
+{
+ return mMessageFilepath;
+}
+
+void NNTPPostOperation::main()
+{
+ ErrorCode error;
+ if (mMessageFilepath != NULL) {
+ session()->session()->postMessage(mMessageFilepath, this, &error);
+ }
+ else {
+ session()->session()->postMessage(mMessageData, this, &error);
+ }
+ setError(error);
+}
diff --git a/src/async/nntp/MCNNTPPostOperation.h b/src/async/nntp/MCNNTPPostOperation.h
new file mode 100644
index 00000000..9255dafd
--- /dev/null
+++ b/src/async/nntp/MCNNTPPostOperation.h
@@ -0,0 +1,44 @@
+//
+// MCNNTPPostOperation.h
+// mailcore2
+//
+// Created by Daryle Walker on 2/21/16.
+// Copyright © 2016 MailCore. All rights reserved.
+//
+
+#ifndef MAILCORE_MCNNTPPOSTOPERATION_H
+
+#define MAILCORE_MCNNTPPOSTOPERATION_H
+
+#include <MailCore/MCBaseTypes.h>
+#include <MailCore/MCAbstract.h>
+#include <MailCore/MCNNTPOperation.h>
+
+#ifdef __cplusplus
+
+namespace mailcore {
+
+ class MAILCORE_EXPORT NNTPPostOperation : public NNTPOperation {
+ public:
+ NNTPPostOperation();
+ virtual ~NNTPPostOperation();
+
+ 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;
+ };
+
+}
+
+#endif
+
+#endif
diff --git a/src/cmake/async.cmake b/src/cmake/async.cmake
index 329c958e..1c213a33 100644
--- a/src/cmake/async.cmake
+++ b/src/cmake/async.cmake
@@ -67,6 +67,7 @@ set(async_nntp_files
async/nntp/MCNNTPListNewsgroupsOperation.cpp
async/nntp/MCNNTPFetchOverviewOperation.cpp
async/nntp/MCNNTPFetchServerTimeOperation.cpp
+ async/nntp/MCNNTPPostOperation.cpp
async/nntp/MCNNTPOperation.cpp
)
diff --git a/src/cmake/objc.cmake b/src/cmake/objc.cmake
index 12a06bd1..aeb01d3b 100644
--- a/src/cmake/objc.cmake
+++ b/src/cmake/objc.cmake
@@ -88,6 +88,7 @@ set(objc_nntp_files
objc/nntp/MCONNTPListNewsgroupsOperation.mm
objc/nntp/MCONNTPFetchOverviewOperation.mm
objc/nntp/MCONNTPFetchServerTimeOperation.mm
+ objc/nntp/MCONNTPPostOperation.mm
objc/nntp/MCONNTPOperation.mm
objc/nntp/MCONNTPSession.mm
)
diff --git a/src/cmake/public-headers.cmake b/src/cmake/public-headers.cmake
index db0ebd71..bcbdb0b6 100644
--- a/src/cmake/public-headers.cmake
+++ b/src/cmake/public-headers.cmake
@@ -118,6 +118,7 @@ async/nntp/MCNNTPFetchAllArticlesOperation.h
async/nntp/MCNNTPListNewsgroupsOperation.h
async/nntp/MCNNTPFetchOverviewOperation.h
async/nntp/MCNNTPFetchServerTimeOperation.h
+async/nntp/MCNNTPPostOperation.h
async/nntp/MCNNTPOperationCallback.h
objc/MCObjC.h
objc/utils/MCOUtils.h
@@ -201,6 +202,7 @@ objc/nntp/MCONNTPFetchAllArticlesOperation.h
objc/nntp/MCONNTPListNewsgroupsOperation.h
objc/nntp/MCONNTPFetchOverviewOperation.h
objc/nntp/MCONNTPFetchServerTimeOperation.h
+objc/nntp/MCONNTPPostOperation.h
objc/nntp/MCONNTPGroupInfo.h
objc/provider/MCOProvider.h
objc/provider/MCONetService.h
diff --git a/src/core/nntp/MCNNTPSession.cpp b/src/core/nntp/MCNNTPSession.cpp
index 933f10f2..e5004432 100644
--- a/src/core/nntp/MCNNTPSession.cpp
+++ b/src/core/nntp/MCNNTPSession.cpp
@@ -15,6 +15,7 @@
#include "MCNNTPGroupInfo.h"
#include "MCMessageHeader.h"
+#include "MCNNTPProgressCallback.h"
#include "MCConnectionLoggerUtils.h"
#include "MCCertificateUtils.h"
#include "MCLibetpan.h"
@@ -45,6 +46,7 @@ void NNTPSession::init()
mTimeout = 30;
mNNTP = NULL;
+ mProgressCallback = NULL;
mState = STATE_DISCONNECTED;
mConnectionLogger = NULL;
}
@@ -138,6 +140,21 @@ bool NNTPSession::checkCertificate()
return mailcore::checkCertificate(mNNTP->nntp_stream, hostname());
}
+void NNTPSession::body_progress(size_t current, size_t maximum, void * context)
+{
+ NNTPSession * session;
+
+ session = (NNTPSession *) context;
+ session->bodyProgress((unsigned int) current, (unsigned int) maximum);
+}
+
+void NNTPSession::bodyProgress(unsigned int current, unsigned int maximum)
+{
+ if (mProgressCallback != NULL) {
+ mProgressCallback->bodyProgress(this, current, maximum);
+ }
+}
+
static void logger(newsnntp * nntp, int log_type, const char * buffer, size_t size, void * context)
{
NNTPSession * session = (NNTPSession *) context;
@@ -605,6 +622,124 @@ Array * NNTPSession::fetchOverArticlesInRange(Range range, String * groupName, E
return result;
}
+void NNTPSession::postMessage(Data * messageData, NNTPProgressCallback * callback, ErrorCode * pError)
+{
+ int r;
+
+ messageData = dataWithFilteredBcc(messageData);
+
+ mProgressCallback = callback;
+ bodyProgress(0, messageData->length());
+
+ MCLog("setup");
+
+ MCLog("connect");
+ loginIfNeeded(pError);
+ if (* pError != ErrorNone) {
+ goto err;
+ }
+
+ MCLog("send");
+ r = newsnntp_post(mNNTP, messageData->bytes(), messageData->length());
+
+ String * response;
+
+ response = NULL;
+ if (mNNTP->nntp_response != NULL) {
+ response = String::stringWithUTF8Characters(mNNTP->nntp_response);
+ }
+
+ if (r == NEWSNNTP_ERROR_STREAM) {
+ * pError = ErrorConnection;
+ goto err;
+ }
+ else if (r != NEWSNNTP_NO_ERROR) {
+ * pError = ErrorSendMessage;
+ goto err;
+ }
+
+ bodyProgress(messageData->length(), messageData->length());
+ * pError = ErrorNone;
+
+err:
+ mProgressCallback = NULL;
+}
+
+void NNTPSession::postMessage(String * messagePath, NNTPProgressCallback * callback, ErrorCode * pError)
+{
+ Data * messageData = Data::dataWithContentsOfFile(messagePath);
+ if (!messageData) {
+ * pError = ErrorFile;
+ return;
+ }
+
+ return postMessage(messageData, callback, pError);
+}
+
+static void mmapStringDeallocator(char * bytes, unsigned int length) {
+ mmap_string_unref(bytes);
+}
+
+Data * NNTPSession::dataWithFilteredBcc(Data * data)
+{
+ int r;
+ size_t idx;
+ struct mailimf_message * msg;
+
+ idx = 0;
+ r = mailimf_message_parse(data->bytes(), data->length(), &idx, &msg);
+ if (r != MAILIMF_NO_ERROR) {
+ return Data::data();
+ }
+
+ struct mailimf_fields * fields = msg->msg_fields;
+ int col = 0;
+
+ int hasRecipient = 0;
+ 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)) {
+ hasRecipient = 1;
+ }
+ }
+ if (!hasRecipient) {
+ struct mailimf_address_list * imfTo;
+ imfTo = mailimf_address_list_new_empty();
+ mailimf_address_list_add_parse(imfTo, (char *) "Undisclosed recipients:;");
+ struct mailimf_to * toField = mailimf_to_new(imfTo);
+ 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);
+ }
+
+ 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;
+}
+
void NNTPSession::selectGroup(String * folder, ErrorCode * pError)
{
int r;
diff --git a/src/core/nntp/MCNNTPSession.h b/src/core/nntp/MCNNTPSession.h
index ec0080ed..22734f2d 100644
--- a/src/core/nntp/MCNNTPSession.h
+++ b/src/core/nntp/MCNNTPSession.h
@@ -57,6 +57,9 @@ namespace mailcore {
virtual time_t fetchServerDate(ErrorCode * pError);
+ virtual void postMessage(Data * messageData, NNTPProgressCallback * callback, ErrorCode * pError);
+ virtual void postMessage(String * messagePath, NNTPProgressCallback * callback, ErrorCode * pError);
+
virtual void setConnectionLogger(ConnectionLogger * logger);
virtual ConnectionLogger * connectionLogger();
@@ -70,11 +73,15 @@ namespace mailcore {
time_t mTimeout;
newsnntp * mNNTP;
+ NNTPProgressCallback * mProgressCallback;
int mState;
ConnectionLogger * mConnectionLogger;
void init();
+ Data * dataWithFilteredBcc(Data * data);
+ static void body_progress(size_t current, size_t maximum, void * context);
+ void bodyProgress(unsigned int current, unsigned int maximum);
bool checkCertificate();
void setup();
void unsetup();
diff --git a/src/objc/nntp/MCONNTP.h b/src/objc/nntp/MCONNTP.h
index 71979dfa..62442c2a 100644
--- a/src/objc/nntp/MCONNTP.h
+++ b/src/objc/nntp/MCONNTP.h
@@ -18,6 +18,7 @@
#include <MailCore/MCONNTPListNewsgroupsOperation.h>
#include <MailCore/MCONNTPFetchOverviewOperation.h>
#include <MailCore/MCONNTPFetchServerTimeOperation.h>
+#include <MailCore/MCONNTPPostOperation.h>
#include <MailCore/MCONNTPGroupInfo.h>
#endif
diff --git a/src/objc/nntp/MCONNTPFetchArticleOperation.h b/src/objc/nntp/MCONNTPFetchArticleOperation.h
index 170f594b..78a974f4 100644
--- a/src/objc/nntp/MCONNTPFetchArticleOperation.h
+++ b/src/objc/nntp/MCONNTPFetchArticleOperation.h
@@ -13,10 +13,6 @@
#import <Foundation/Foundation.h>
#import <MailCore/MCONNTPOperation.h>
-/** Fetch a message from NNTP3 */
-
-typedef void (^MCONNTPOperationProgressBlock)(unsigned int current, unsigned int maximum);
-
NS_ASSUME_NONNULL_BEGIN
@interface MCONNTPFetchArticleOperation : MCONNTPOperation
diff --git a/src/objc/nntp/MCONNTPOperation.h b/src/objc/nntp/MCONNTPOperation.h
index bed8874e..0c35970f 100644
--- a/src/objc/nntp/MCONNTPOperation.h
+++ b/src/objc/nntp/MCONNTPOperation.h
@@ -13,6 +13,10 @@
#import <Foundation/Foundation.h>
#import <MailCore/MCOOperation.h>
+/** Transmit a message using NNTP3 */
+
+typedef void (^MCONNTPOperationProgressBlock)(unsigned int current, unsigned int maximum);
+
/**
This is a generic asynchronous NNTP3 operation.
@see MCONNTPSession
diff --git a/src/objc/nntp/MCONNTPPostOperation.h b/src/objc/nntp/MCONNTPPostOperation.h
new file mode 100644
index 00000000..a2447e70
--- /dev/null
+++ b/src/objc/nntp/MCONNTPPostOperation.h
@@ -0,0 +1,37 @@
+//
+// MCONNTPPostOperation.h
+// mailcore2
+//
+// Created by Daryle Walker on 2/21/16.
+// Copyright © 2016 MailCore. All rights reserved.
+//
+
+#ifndef MAILCORE_MCONNTPPOSTOPERATION_H
+
+#define MAILCORE_MCONNTPPOSTOPERATION_H
+
+#import <Foundation/Foundation.h>
+#import <MailCore/MCONNTPOperation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+@interface MCONNTPPostOperation : MCONNTPOperation
+
+/** This block will be called as data is downloaded from the network */
+@property (nonatomic, copy) MCONNTPOperationProgressBlock progress;
+
+/**
+ Starts the asynchronous send operation.
+
+ @param completionBlock Called when the operation is finished.
+
+ - On success `error` will be nil
+
+ - On failure, `error` will be set with `MCOErrorDomain` as domain and an
+ error code available in MCOConstants.h
+ */
+- (void) start:(void (^)(NSError * __nullable error))completionBlock;
+
+@end
+NS_ASSUME_NONNULL_END
+
+#endif
diff --git a/src/objc/nntp/MCONNTPPostOperation.mm b/src/objc/nntp/MCONNTPPostOperation.mm
new file mode 100644
index 00000000..f5009afa
--- /dev/null
+++ b/src/objc/nntp/MCONNTPPostOperation.mm
@@ -0,0 +1,116 @@
+//
+// MCONNTPPostOperation.mm
+// mailcore2
+//
+// Created by Daryle Walker on 2/21/16.
+// Copyright © 2016 MailCore. All rights reserved.
+//
+
+#import "MCONNTPPostOperation.h"
+
+#import "MCAsyncNNTP.h"
+
+#import "MCOUtils.h"
+#import "MCOOperation+Private.h"
+
+#define nativeType mailcore::NNTPPostOperation
+
+typedef void (^CompletionType)(NSError *error);
+
+@interface MCONNTPPostOperation ()
+
+- (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum;
+
+@end
+
+class MCONNTPPostOperationCallback : public mailcore::NNTPOperationCallback {
+public:
+ MCONNTPPostOperationCallback(MCONNTPPostOperation * op)
+ {
+ mOperation = op;
+ }
+ virtual ~MCONNTPPostOperationCallback()
+ {
+ }
+
+ virtual void bodyProgress(mailcore::NNTPOperation * session, unsigned int current, unsigned int maximum) {
+ [mOperation bodyProgress:current maximum:maximum];
+ }
+
+private:
+ MCONNTPPostOperation * mOperation;
+};
+
+@implementation MCONNTPPostOperation {
+ CompletionType _completionBlock;
+ MCONNTPPostOperationCallback * _popCallback;
+ MCONNTPOperationProgressBlock _progress;
+}
+
+@synthesize progress = _progress;
+
++ (void) load
+{
+ MCORegisterClass(self, &typeid(nativeType));
+}
+
++ (NSObject *) mco_objectWithMCObject:(mailcore::Object *)object
+{
+ nativeType * op = (nativeType *) object;
+ return [[[self alloc] initWithMCOperation:op] autorelease];
+}
+
+- (instancetype) initWithMCOperation:(mailcore::Operation *)op
+{
+ self = [super initWithMCOperation:op];
+
+ _popCallback = new MCONNTPPostOperationCallback(self);
+ ((mailcore::NNTPOperation *) op)->setNNTPCallback(_popCallback);
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [_progress release];
+ [_completionBlock release];
+ delete _popCallback;
+ [super dealloc];
+}
+
+- (void) start:(void (^)(NSError *error))completionBlock
+{
+ _completionBlock = [completionBlock copy];
+ [self start];
+}
+
+- (void) cancel
+{
+ [_completionBlock release];
+ _completionBlock = nil;
+ [super cancel];
+}
+
+- (void) operationCompleted
+{
+ if (_completionBlock == NULL)
+ return;
+
+ nativeType *op = MCO_NATIVE_INSTANCE;
+ if (op->error() == mailcore::ErrorNone) {
+ _completionBlock(nil);
+ } else {
+ _completionBlock([NSError mco_errorWithErrorCode:op->error()]);
+ }
+ [_completionBlock release];
+ _completionBlock = nil;
+}
+
+- (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum
+{
+ if (_progress != NULL) {
+ _progress(current, maximum);
+ }
+}
+
+@end
diff --git a/src/objc/nntp/MCONNTPSession.h b/src/objc/nntp/MCONNTPSession.h
index 29fe18af..19fe5ff4 100644
--- a/src/objc/nntp/MCONNTPSession.h
+++ b/src/objc/nntp/MCONNTPSession.h
@@ -20,6 +20,7 @@
@class MCONNTPListNewsgroupsOperation;
@class MCONNTPFetchOverviewOperation;
@class MCONNTPFetchServerTimeOperation;
+@class MCONNTPPostOperation;
@class MCONNTPOperation;
@class MCOIndexSet;
@@ -182,6 +183,32 @@ NS_ASSUME_NONNULL_BEGIN
- (MCONNTPListNewsgroupsOperation *) listDefaultNewsgroupsOperation;
/**
+ Returns an operation that will post the given message through NNTP.
+ It will use the newsgroups set in the message data.
+ It will also filter out Bcc from the content of the message.
+
+ Generate RFC 822 data using MCOMessageBuilder
+
+ MCONNTPOperation * op = [session postOperationWithData:rfc822Data];
+ [op start:^(NSError * __nullable error) {
+ ...
+ }];
+ */
+- (MCONNTPPostOperation *) postOperationWithData:(NSData *)messageData;
+
+/**
+ Returns an operation that will post the message from the given file through NNTP.
+ It will use the newsgroups set in the message data.
+ It will also filter out Bcc from the content of the message.
+
+ MCONNTPOperation * op = [session postOperationWithContentsOfFile:rfc822DataFilename];
+ [op start:^(NSError * __nullable error) {
+ ...
+ }];
+ */
+- (MCONNTPPostOperation *) postOperationWithContentsOfFile:(NSString *)path;
+
+/**
Returns an operation that will disconnect the session.
MCONNTPOperation * op = [session disconnectOperation];
diff --git a/src/objc/nntp/MCONNTPSession.mm b/src/objc/nntp/MCONNTPSession.mm
index 8237145c..f873cff9 100644
--- a/src/objc/nntp/MCONNTPSession.mm
+++ b/src/objc/nntp/MCONNTPSession.mm
@@ -14,6 +14,7 @@
#import "MCONNTPOperation.h"
#import "MCOOperation+Private.h"
#import "MCONNTPFetchAllArticlesOperation.h"
+#import "MCONNTPPostOperation.h"
#import "MCONNTPOperation+Private.h"
#include "MCOperationQueueCallback.h"
@@ -205,6 +206,17 @@ MCO_OBJC_SYNTHESIZE_SCALAR(dispatch_queue_t, dispatch_queue_t, setDispatchQueue,
return MCO_TO_OBJC_OP(coreOp);
}
+- (MCONNTPPostOperation *) postOperationWithData:(NSData *)messageData {
+ mailcore::NNTPPostOperation * coreOp = MCO_NATIVE_INSTANCE->postMessageOperation(MCO_FROM_OBJC(mailcore::Data, messageData));
+ return MCO_TO_OBJC_OP(coreOp);
+}
+
+- (MCONNTPPostOperation *) postOperationWithContentsOfFile:(NSString *)path
+{
+ mailcore::NNTPPostOperation * coreOp = MCO_NATIVE_INSTANCE->postMessageOperation(MCO_FROM_OBJC(mailcore::String, path));
+ return MCO_TO_OBJC_OP(coreOp);
+}
+
- (MCONNTPOperation *) disconnectOperation
{
mailcore::NNTPOperation * coreOp = MCO_NATIVE_INSTANCE->disconnectOperation();