/// <summary>begins to send APPEND command</summary> /// <remarks>valid in authenticated state</remarks> public IAsyncResult BeginAppend(Stream messageBodyStream, DateTimeOffset? internalDate, IImapMessageFlagSet flags, string mailboxName) { RejectNonAuthenticatedState(); RejectTransactionProceeding(); if (messageBodyStream == null) throw new ArgumentNullException("messageBodyStream"); RejectInvalidMailboxNameArgument(mailboxName); // append message var messagesToUpload = new List<ImapString>(1); // flag-list if (flags != null && 0 < flags.Count) messagesToUpload.Add(new ImapParenthesizedString(flags.GetNonApplicableFlagsRemoved().ToArray())); // date-time if (internalDate.HasValue) messagesToUpload.Add(ImapDateTimeFormat.ToDateTimeString(internalDate.Value)); // append-data messagesToUpload.Add(new ImapLiteralStream(messageBodyStream, ImapLiteralOptions.Synchronizing)); AppendTransaction t = null; try { t = new AppendTransaction(connection, false); // mailbox name t.RequestArguments["mailbox name"] = new ImapMailboxNameString(mailboxName); // messages to upload t.RequestArguments["messages to upload"] = new ImapStringList(messagesToUpload.ToArray()); var asyncResult = BeginProcessTransaction(t, handlesIncapableAsException); // wait for started (or completed) for (;;) { if (asyncResult.IsCompleted) break; else if (IsTransactionProceeding) break; else System.Threading.Thread.Sleep(10); } return asyncResult; } catch { if (t != null) { t.Dispose(); t = null; } throw; } }
private ImapCommandResult AppendInternal(IEnumerable<IImapAppendMessage> messages, bool binary, string mailboxName, bool tryCreate, out ImapAppendedUidSet appendedUids, out ImapMailbox createdMailbox) { RejectNonAuthenticatedState(); if (messages == null) throw new ArgumentNullException("messages"); RejectInvalidMailboxNameArgument(mailboxName); appendedUids = null; createdMailbox = null; // append message var messagesToUpload = new List<ImapString>(); var messageCount = 0; var literalOptions = ImapLiteralOptions.NonSynchronizingIfCapable | (binary ? ImapLiteralOptions.Literal8 : ImapLiteralOptions.Literal); foreach (var message in messages) { if (message == null) throw new ArgumentException("contains null", "messages"); /* * RFC 4466 - Collected Extensions to IMAP4 ABNF * http://tools.ietf.org/html/rfc4466 * * append = "APPEND" SP mailbox 1*append-message * ;; only a single append-message may appear * ;; if MULTIAPPEND [MULTIAPPEND] capability * ;; is not present * append-message = append-opts SP append-data * append-ext = append-ext-name SP append-ext-value * ;; This non-terminal define extensions to * ;; to message metadata. * append-ext-name = tagged-ext-label * append-ext-value= tagged-ext-val * ;; This non-terminal shows recommended syntax * ;; for future extensions. * append-data = literal / literal8 / append-data-ext * append-data-ext = tagged-ext * ;; This non-terminal shows recommended syntax * ;; for future extensions, * ;; i.e., a mandatory label followed * ;; by parameters. * append-opts = [SP flag-list] [SP date-time] *(SP append-ext) * ;; message metadata */ // flag-list if (message.Flags != null && 0 < message.Flags.Count) messagesToUpload.Add(new ImapParenthesizedString(message.Flags.GetNonApplicableFlagsRemoved().ToArray())); // date-time if (message.InternalDate.HasValue) messagesToUpload.Add(ImapDateTimeFormat.ToDateTimeString(message.InternalDate.Value)); // append-data messagesToUpload.Add(new ImapLiteralStream(message.GetMessageStream(), literalOptions)); messageCount++; } if (messageCount == 0) throw new ArgumentException("at least 1 message must be specified", "messages"); ImapCommandResult failedResult = null; for (var i = 0; i < 2; i++) { var respTryCreate = false; using (var t = new AppendTransaction(connection, 1 < messageCount)) { // mailbox name t.RequestArguments["mailbox name"] = new ImapMailboxNameString(mailboxName); // messages to upload t.RequestArguments["messages to upload"] = new ImapStringList(messagesToUpload.ToArray()); if (ProcessTransaction(t).Succeeded) { appendedUids = t.Result.Value; return t.Result; } else { if (ProcessMailboxRefferalResponse(t.Result.TaggedStatusResponse) || !tryCreate) return t.Result; } failedResult = t.Result; // 6.3.11. APPEND Command // If the destination mailbox does not exist, a server MUST return an // error, and MUST NOT automatically create the mailbox. Unless it // is certain that the destination mailbox can not be created, the // server MUST send the response code "[TRYCREATE]" as the prefix of // the text of the tagged NO response. This gives a hint to the // client that it can attempt a CREATE command and retry the APPEND // if the CREATE is successful. respTryCreate = (t.Result.GetResponseCode(ImapResponseCode.TryCreate) is ImapTaggedStatusResponse); } // try create if (i == 0 && respTryCreate) if (Create(mailboxName, out createdMailbox).Failed) return failedResult; } return failedResult; }