// common construction method
        private static ImapStoreDataItem FlagsCommon(ImapString itemName, IImapMessageFlagSet flags)
        {
            if (flags == null)
            throw new ArgumentNullException("flags");
              else if (flags.Count == 0)
            throw new ArgumentException("must contain at least one keyword or flag", "flags");

              return new ImapStoreDataItem(itemName, flags.GetNonApplicableFlagsRemoved().ToArray());
        }
        /// <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;
              }
        }