Repository: jstedfast/MailKit
Branch: master
Commit: 8967eebe1abe
Files: 1080
Total size: 19.0 MB
Directory structure:
gitextract_1og2imlt/
├── .config/
│ └── dotnet-tools.json
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── aot-compatibility.yml
│ ├── codeql.yml
│ └── main.yml
├── .gitignore
├── .gitmodules
├── AotCompatibility/
│ ├── AotCompatibility.csproj
│ └── Program.cs
├── Documentation/
│ ├── Content/
│ │ ├── Creating-Messages.aml
│ │ ├── Frequently-Asked-Questions.aml
│ │ ├── Getting-Started.aml
│ │ ├── Introduction.aml
│ │ ├── License.aml
│ │ ├── Parsing-Messages.aml
│ │ ├── Working-With-Messages.aml
│ │ ├── Working-With-OpenPGP.aml
│ │ └── Working-With-SMime.aml
│ ├── ContentLayout.content
│ ├── Documentation.shfbproj
│ └── Examples/
│ ├── ArcSignerExample.cs
│ ├── ArcVerifierExample.cs
│ ├── AttachmentExamples.cs
│ ├── BodyBuilder.cs
│ ├── CreateMultipartAlternative.cs
│ ├── CreateMultipartMixed.cs
│ ├── CreateSimpleMessage.cs
│ ├── DecodingContent.cs
│ ├── DkimExamples.cs
│ ├── DkimVerifierExample.cs
│ ├── ForwardExamples.cs
│ ├── ImapBodyPartExamples.cs
│ ├── ImapExamples.cs
│ ├── ImapIdleExample.cs
│ ├── InlinePGPExample.txt
│ ├── MessageDeliveryStatusExamples.cs
│ ├── MimeIterator.cs
│ ├── MimeMessageLoad.cs
│ ├── MimeParserExamples.cs
│ ├── MimeVisitorExamples.cs
│ ├── MultipartFormDataExamples.cs
│ ├── OAuth2ExchangeExample.cs
│ ├── OAuth2GMailExample.cs
│ ├── OpenPGPExamples.cs
│ ├── OpeningContent.cs
│ ├── ParameterExamples.cs
│ ├── Pop3Examples.cs
│ ├── ProxyExamples.cs
│ ├── RecursivelyTraverse.cs
│ ├── SMimeExamples.cs
│ ├── SmtpExamples.cs
│ ├── SslCertificateValidation.cs
│ └── VerifySignature.cs
├── ExchangeOAuth2.md
├── FAQ.md
├── GMailOAuth2.md
├── LICENSE
├── MailKit/
│ ├── AccessControl.cs
│ ├── AccessControlList.cs
│ ├── AccessRight.cs
│ ├── AccessRights.cs
│ ├── AlertEventArgs.cs
│ ├── Annotation.cs
│ ├── AnnotationAccess.cs
│ ├── AnnotationAttribute.cs
│ ├── AnnotationEntry.cs
│ ├── AnnotationScope.cs
│ ├── AnnotationsChangedEventArgs.cs
│ ├── AppendRequest.cs
│ ├── AuthenticatedEventArgs.cs
│ ├── BodyPart.cs
│ ├── BodyPartBasic.cs
│ ├── BodyPartCollection.cs
│ ├── BodyPartMessage.cs
│ ├── BodyPartMultipart.cs
│ ├── BodyPartText.cs
│ ├── BodyPartVisitor.cs
│ ├── ByteArrayBuilder.cs
│ ├── CommandException.cs
│ ├── CompressedStream.cs
│ ├── ConnectedEventArgs.cs
│ ├── DeliveryStatusNotification.cs
│ ├── DeliveryStatusNotificationType.cs
│ ├── DisconnectedEventArgs.cs
│ ├── DuplexStream.cs
│ ├── Envelope.cs
│ ├── FetchRequest.cs
│ ├── FolderAccess.cs
│ ├── FolderAttributes.cs
│ ├── FolderCreatedEventArgs.cs
│ ├── FolderFeature.cs
│ ├── FolderNamespace.cs
│ ├── FolderNamespaceCollection.cs
│ ├── FolderNotFoundException.cs
│ ├── FolderNotOpenException.cs
│ ├── FolderQuota.cs
│ ├── FolderRenamedEventArgs.cs
│ ├── HeaderSet.cs
│ ├── IAppendRequest.cs
│ ├── IAuthenticationSecretDetector.cs
│ ├── IFetchRequest.cs
│ ├── IMailFolder.cs
│ ├── IMailFolderAppendExtensions.cs
│ ├── IMailFolderFetchExtensions.cs
│ ├── IMailFolderStoreExtensions.cs
│ ├── IMailService.cs
│ ├── IMailSpool.cs
│ ├── IMailStore.cs
│ ├── IMailTransport.cs
│ ├── IMessageSummary.cs
│ ├── IProtocolLogger.cs
│ ├── IReplaceRequest.cs
│ ├── IStoreFlagsRequest.cs
│ ├── IStoreLabelsRequest.cs
│ ├── IStoreRequest.cs
│ ├── ITransferProgress.cs
│ ├── MailFolder.cs
│ ├── MailKit.csproj
│ ├── MailKitLite.csproj
│ ├── MailService.cs
│ ├── MailSpool.cs
│ ├── MailStore.cs
│ ├── MailTransport.cs
│ ├── MessageEventArgs.cs
│ ├── MessageFlags.cs
│ ├── MessageFlagsChangedEventArgs.cs
│ ├── MessageLabelsChangedEventArgs.cs
│ ├── MessageNotFoundException.cs
│ ├── MessageSentEventArgs.cs
│ ├── MessageSorter.cs
│ ├── MessageSummary.cs
│ ├── MessageSummaryFetchedEventArgs.cs
│ ├── MessageSummaryItems.cs
│ ├── MessageThread.cs
│ ├── MessageThreader.cs
│ ├── MessagesVanishedEventArgs.cs
│ ├── Metadata.cs
│ ├── MetadataChangedEventArgs.cs
│ ├── MetadataCollection.cs
│ ├── MetadataOptions.cs
│ ├── MetadataTag.cs
│ ├── ModSeqChangedEventArgs.cs
│ ├── Net/
│ │ ├── ClientMetrics.cs
│ │ ├── IChannelBindingContext.cs
│ │ ├── Imap/
│ │ │ ├── AsyncImapClient.cs
│ │ │ ├── IImapClient.cs
│ │ │ ├── IImapFolder.cs
│ │ │ ├── ImapAuthenticationSecretDetector.cs
│ │ │ ├── ImapCallbacks.cs
│ │ │ ├── ImapCapabilities.cs
│ │ │ ├── ImapClient.cs
│ │ │ ├── ImapCommand.cs
│ │ │ ├── ImapCommandException.cs
│ │ │ ├── ImapCommandResponse.cs
│ │ │ ├── ImapCommandStatus.cs
│ │ │ ├── ImapEncoding.cs
│ │ │ ├── ImapEngine.cs
│ │ │ ├── ImapEventGroup.cs
│ │ │ ├── ImapFolder.cs
│ │ │ ├── ImapFolderAnnotations.cs
│ │ │ ├── ImapFolderConstructorArgs.cs
│ │ │ ├── ImapFolderFetch.cs
│ │ │ ├── ImapFolderFlags.cs
│ │ │ ├── ImapFolderSearch.cs
│ │ │ ├── ImapIdleContext.cs
│ │ │ ├── ImapImplementation.cs
│ │ │ ├── ImapLiteral.cs
│ │ │ ├── ImapProtocolException.cs
│ │ │ ├── ImapResponseCode.cs
│ │ │ ├── ImapSearchQueryOptimizer.cs
│ │ │ ├── ImapStream.cs
│ │ │ ├── ImapToken.cs
│ │ │ └── ImapUtils.cs
│ │ ├── NetworkOperation.cs
│ │ ├── NetworkStream.cs
│ │ ├── Pop3/
│ │ │ ├── AsyncPop3Client.cs
│ │ │ ├── IPop3Client.cs
│ │ │ ├── Pop3AuthenticationSecretDetector.cs
│ │ │ ├── Pop3Capabilities.cs
│ │ │ ├── Pop3Client.cs
│ │ │ ├── Pop3Command.cs
│ │ │ ├── Pop3CommandException.cs
│ │ │ ├── Pop3Engine.cs
│ │ │ ├── Pop3Language.cs
│ │ │ ├── Pop3ProtocolException.cs
│ │ │ └── Pop3Stream.cs
│ │ ├── Proxy/
│ │ │ ├── HttpProxyClient.cs
│ │ │ ├── HttpsProxyClient.cs
│ │ │ ├── IProxyClient.cs
│ │ │ ├── ProxyClient.cs
│ │ │ ├── ProxyProtocolException.cs
│ │ │ ├── Socks4Client.cs
│ │ │ ├── Socks4aClient.cs
│ │ │ ├── Socks5Client.cs
│ │ │ ├── SocksClient.cs
│ │ │ └── WebProxyClient.cs
│ │ ├── SelectMode.cs
│ │ ├── Smtp/
│ │ │ ├── AsyncSmtpClient.cs
│ │ │ ├── ISmtpClient.cs
│ │ │ ├── SmtpAuthenticationSecretDetector.cs
│ │ │ ├── SmtpCapabilities.cs
│ │ │ ├── SmtpClient.cs
│ │ │ ├── SmtpCommandException.cs
│ │ │ ├── SmtpDataFilter.cs
│ │ │ ├── SmtpErrorCode.cs
│ │ │ ├── SmtpProtocolException.cs
│ │ │ ├── SmtpResponse.cs
│ │ │ ├── SmtpStatusCode.cs
│ │ │ └── SmtpStream.cs
│ │ ├── SocketMetrics.cs
│ │ ├── SocketUtils.cs
│ │ └── SslStream.cs
│ ├── NullProtocolLogger.cs
│ ├── PreviewOptions.cs
│ ├── ProgressStream.cs
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── ProtocolException.cs
│ ├── ProtocolLogger.cs
│ ├── ReplaceRequest.cs
│ ├── Search/
│ │ ├── AnnotationSearchQuery.cs
│ │ ├── BinarySearchQuery.cs
│ │ ├── DateSearchQuery.cs
│ │ ├── FilterSearchQuery.cs
│ │ ├── HeaderSearchQuery.cs
│ │ ├── ISearchQueryOptimizer.cs
│ │ ├── NumericSearchQuery.cs
│ │ ├── OrderBy.cs
│ │ ├── OrderByAnnotation.cs
│ │ ├── OrderByType.cs
│ │ ├── SearchOptions.cs
│ │ ├── SearchQuery.cs
│ │ ├── SearchResults.cs
│ │ ├── SearchTerm.cs
│ │ ├── SortOrder.cs
│ │ ├── TextSearchQuery.cs
│ │ ├── UidSearchQuery.cs
│ │ └── UnarySearchQuery.cs
│ ├── Security/
│ │ ├── AuthenticationException.cs
│ │ ├── KeyedHashAlgorithm.cs
│ │ ├── Ntlm/
│ │ │ ├── BitConverterLE.cs
│ │ │ ├── DES.cs
│ │ │ ├── HMACMD5.cs
│ │ │ ├── MD4.cs
│ │ │ ├── NtlmAttribute.cs
│ │ │ ├── NtlmAttributeValuePair.cs
│ │ │ ├── NtlmAuthenticateMessage.cs
│ │ │ ├── NtlmChallengeMessage.cs
│ │ │ ├── NtlmFlags.cs
│ │ │ ├── NtlmMessageBase.cs
│ │ │ ├── NtlmNegotiateMessage.cs
│ │ │ ├── NtlmSingleHostData.cs
│ │ │ ├── NtlmTargetInfo.cs
│ │ │ ├── NtlmUtils.cs
│ │ │ └── RC4.cs
│ │ ├── RandomNumberGenerator.cs
│ │ ├── SaslException.cs
│ │ ├── SaslMechanism.cs
│ │ ├── SaslMechanismAnonymous.cs
│ │ ├── SaslMechanismCramMd5.cs
│ │ ├── SaslMechanismDigestMd5.cs
│ │ ├── SaslMechanismGssapi.cs
│ │ ├── SaslMechanismLogin.cs
│ │ ├── SaslMechanismNegotiateBase.cs
│ │ ├── SaslMechanismNtlm.cs
│ │ ├── SaslMechanismNtlmNative.cs
│ │ ├── SaslMechanismOAuth2.cs
│ │ ├── SaslMechanismOAuthBearer.cs
│ │ ├── SaslMechanismPlain.cs
│ │ ├── SaslMechanismScramBase.cs
│ │ ├── SaslMechanismScramSha1.cs
│ │ ├── SaslMechanismScramSha256.cs
│ │ ├── SaslMechanismScramSha512.cs
│ │ ├── SecureSocketOptions.cs
│ │ └── SslHandshakeException.cs
│ ├── ServiceNotAuthenticatedException.cs
│ ├── ServiceNotConnectedException.cs
│ ├── SpecialFolder.cs
│ ├── StatusItems.cs
│ ├── StoreAction.cs
│ ├── StoreFlagsRequest.cs
│ ├── StoreLabelsRequest.cs
│ ├── Telemetry.cs
│ ├── TextEncodings.cs
│ ├── ThreadingAlgorithm.cs
│ ├── UniqueId.cs
│ ├── UniqueIdMap.cs
│ ├── UniqueIdRange.cs
│ ├── UniqueIdSet.cs
│ ├── UriExtensions.cs
│ ├── WebAlertEventArgs.cs
│ └── mailkit.snk
├── MailKit.Coverity.sln
├── MailKit.Documentation.sln
├── MailKit.sln
├── MailKitLite.sln
├── README.md
├── RFCs.md
├── ReleaseNotes.md
├── SECURITY.md
├── TODO.md
├── Telemetry.md
├── UnitTests/
│ ├── AccessControlListTests.cs
│ ├── AnnotationAttributeTests.cs
│ ├── AnnotationEntryTests.cs
│ ├── AnnotationTests.cs
│ ├── AppendRequestTests.cs
│ ├── ArgumentExceptionTests.cs
│ ├── BodyPartTests.cs
│ ├── CompressedStreamTests.cs
│ ├── DuplexStreamTests.cs
│ ├── EnvelopeTests.cs
│ ├── EventArgsTests.cs
│ ├── ExceptionTests.cs
│ ├── ExceptionalProtocolLogger.cs
│ ├── FolderNamespaceTests.cs
│ ├── HeaderSetTests.cs
│ ├── MailServiceTests.cs
│ ├── MessageSortingTests.cs
│ ├── MessageSummaryTests.cs
│ ├── MessageThreadingTests.cs
│ ├── MetadataTests.cs
│ ├── Net/
│ │ ├── DummyNetworkStream.cs
│ │ ├── Imap/
│ │ │ ├── ImapAuthenticationSecretDetectorTests.cs
│ │ │ ├── ImapClientTests.cs
│ │ │ ├── ImapCommandExceptionTests.cs
│ │ │ ├── ImapCommandTests.cs
│ │ │ ├── ImapEncodingTests.cs
│ │ │ ├── ImapEngineTests.cs
│ │ │ ├── ImapEventGroupTests.cs
│ │ │ ├── ImapFolderAnnotationsTests.cs
│ │ │ ├── ImapFolderFetchTests.cs
│ │ │ ├── ImapFolderFlagsTests.cs
│ │ │ ├── ImapFolderSearchTests.cs
│ │ │ ├── ImapFolderTests.cs
│ │ │ ├── ImapImplementationTests.cs
│ │ │ ├── ImapReplayStream.cs
│ │ │ ├── ImapSearchQueryOptimizerTests.cs
│ │ │ ├── ImapStreamTests.cs
│ │ │ ├── ImapUtilsTests.cs
│ │ │ └── Resources/
│ │ │ ├── acl/
│ │ │ │ ├── authenticate.txt
│ │ │ │ ├── capability.txt
│ │ │ │ ├── getacl.txt
│ │ │ │ ├── listrights.txt
│ │ │ │ └── myrights.txt
│ │ │ ├── common/
│ │ │ │ ├── basic-greeting.txt
│ │ │ │ ├── capability-greeting.txt
│ │ │ │ ├── capability.txt
│ │ │ │ ├── fetch-annotations.txt
│ │ │ │ ├── getquota-no-root.txt
│ │ │ │ ├── getquota.txt
│ │ │ │ ├── id.txt
│ │ │ │ ├── list-inbox.txt
│ │ │ │ ├── list-literal-subfolders.txt
│ │ │ │ ├── list-namespace.txt
│ │ │ │ ├── list-nil-folder-delim.txt
│ │ │ │ ├── message.0.msg
│ │ │ │ ├── message.1.msg
│ │ │ │ ├── message.10.msg
│ │ │ │ ├── message.11.msg
│ │ │ │ ├── message.12.msg
│ │ │ │ ├── message.13.msg
│ │ │ │ ├── message.14.msg
│ │ │ │ ├── message.15.msg
│ │ │ │ ├── message.16.msg
│ │ │ │ ├── message.17.msg
│ │ │ │ ├── message.18.msg
│ │ │ │ ├── message.19.msg
│ │ │ │ ├── message.2.msg
│ │ │ │ ├── message.20.msg
│ │ │ │ ├── message.21.msg
│ │ │ │ ├── message.22.msg
│ │ │ │ ├── message.23.msg
│ │ │ │ ├── message.24.msg
│ │ │ │ ├── message.25.msg
│ │ │ │ ├── message.26.msg
│ │ │ │ ├── message.27.msg
│ │ │ │ ├── message.28.msg
│ │ │ │ ├── message.29.msg
│ │ │ │ ├── message.3.msg
│ │ │ │ ├── message.30.msg
│ │ │ │ ├── message.31.msg
│ │ │ │ ├── message.32.msg
│ │ │ │ ├── message.33.msg
│ │ │ │ ├── message.34.msg
│ │ │ │ ├── message.35.msg
│ │ │ │ ├── message.36.msg
│ │ │ │ ├── message.37.msg
│ │ │ │ ├── message.38.msg
│ │ │ │ ├── message.39.msg
│ │ │ │ ├── message.4.msg
│ │ │ │ ├── message.40.msg
│ │ │ │ ├── message.41.msg
│ │ │ │ ├── message.42.msg
│ │ │ │ ├── message.43.msg
│ │ │ │ ├── message.44.msg
│ │ │ │ ├── message.45.msg
│ │ │ │ ├── message.46.msg
│ │ │ │ ├── message.47.msg
│ │ │ │ ├── message.48.msg
│ │ │ │ ├── message.49.msg
│ │ │ │ ├── message.5.msg
│ │ │ │ ├── message.6.msg
│ │ │ │ ├── message.7.msg
│ │ │ │ ├── message.8.msg
│ │ │ │ ├── message.9.msg
│ │ │ │ ├── namespace.txt
│ │ │ │ ├── preauth-capability-greeting.txt
│ │ │ │ ├── preauth-greeting.txt
│ │ │ │ ├── select-inbox-annotate-no-modseq.txt
│ │ │ │ ├── select-inbox-annotate-none.txt
│ │ │ │ ├── select-inbox-annotate-readonly.txt
│ │ │ │ ├── select-inbox-annotate.txt
│ │ │ │ ├── select-inbox-no-modseq.txt
│ │ │ │ ├── select-inbox.txt
│ │ │ │ ├── setquota.txt
│ │ │ │ └── status-literal-folder.txt
│ │ │ ├── courier/
│ │ │ │ ├── capability.txt
│ │ │ │ └── greeting.txt
│ │ │ ├── cyrus/
│ │ │ │ ├── authenticate.txt
│ │ │ │ ├── capability.txt
│ │ │ │ └── greeting.txt
│ │ │ ├── domino/
│ │ │ │ ├── capability.txt
│ │ │ │ ├── fetch-extra-parens.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── list-inbox.txt
│ │ │ │ └── namespace.txt
│ │ │ ├── dovecot/
│ │ │ │ ├── append.1.txt
│ │ │ │ ├── append.2.txt
│ │ │ │ ├── append.3.txt
│ │ │ │ ├── append.4.txt
│ │ │ │ ├── append.5.txt
│ │ │ │ ├── append.6.txt
│ │ │ │ ├── append.7.txt
│ │ │ │ ├── append.8.txt
│ │ │ │ ├── authenticate+annotate+replace.txt
│ │ │ │ ├── authenticate+annotate.txt
│ │ │ │ ├── authenticate+filters.txt
│ │ │ │ ├── authenticate+fuzzy.txt
│ │ │ │ ├── authenticate+gmail-capabilities.txt
│ │ │ │ ├── authenticate+replace.txt
│ │ │ │ ├── authenticate+savedate.txt
│ │ │ │ ├── authenticate.txt
│ │ │ │ ├── copy.txt
│ │ │ │ ├── enable-qresync.txt
│ │ │ │ ├── examine-folder.txt
│ │ │ │ ├── expunge.txt
│ │ │ │ ├── fetch1.txt
│ │ │ │ ├── fetch2.txt
│ │ │ │ ├── fetch3.txt
│ │ │ │ ├── fetch4.txt
│ │ │ │ ├── getbodypart.txt
│ │ │ │ ├── getbodypart1.txt
│ │ │ │ ├── getbodypartheaders.txt
│ │ │ │ ├── getmessageheaders.txt
│ │ │ │ ├── getstream-section.txt
│ │ │ │ ├── getstream-section2.txt
│ │ │ │ ├── getstream.txt
│ │ │ │ ├── getstream2.txt
│ │ │ │ ├── getstreams1.txt
│ │ │ │ ├── getstreams2.txt
│ │ │ │ ├── greeting-preauth.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── list-folder.txt
│ │ │ │ ├── list-inbox.txt
│ │ │ │ ├── list-personal.txt
│ │ │ │ ├── list-special-use.txt
│ │ │ │ ├── list-unittests-destination.txt
│ │ │ │ ├── list-unittests-messages.txt
│ │ │ │ ├── list-unittests.txt
│ │ │ │ ├── move.txt
│ │ │ │ ├── multiappend.txt
│ │ │ │ ├── namespace.txt
│ │ │ │ ├── noop+alert.txt
│ │ │ │ ├── notify-idle-done.txt
│ │ │ │ ├── notify-idle.txt
│ │ │ │ ├── notify-list-personal.txt
│ │ │ │ ├── notify.txt
│ │ │ │ ├── optimized-search.txt
│ │ │ │ ├── search-all.txt
│ │ │ │ ├── search-changed-since.txt
│ │ │ │ ├── search-raw.txt
│ │ │ │ ├── search-uids-options.txt
│ │ │ │ ├── search-uids.txt
│ │ │ │ ├── select-unittests-destination.txt
│ │ │ │ ├── select-unittests-messages-qresync.txt
│ │ │ │ ├── select-unittests-messages.txt
│ │ │ │ ├── setflags-unchangedsince.txt
│ │ │ │ ├── sort-by-date.txt
│ │ │ │ ├── sort-by-strings.txt
│ │ │ │ ├── sort-raw.txt
│ │ │ │ ├── sort-reverse-arrival.txt
│ │ │ │ ├── sort-uids-options.txt
│ │ │ │ ├── status-unittests-destination.txt
│ │ │ │ ├── store-answered.txt
│ │ │ │ ├── store-deleted-custom.txt
│ │ │ │ ├── store-deleted.txt
│ │ │ │ ├── store-seen.txt
│ │ │ │ ├── thread-orderedsubject.txt
│ │ │ │ ├── thread-references.txt
│ │ │ │ └── uid-expunge.txt
│ │ │ ├── exchange/
│ │ │ │ ├── capability-postauth.txt
│ │ │ │ ├── capability-preauth.txt
│ │ │ │ ├── greeting-2003.txt
│ │ │ │ ├── greeting-2007.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ └── issue115.txt
│ │ │ ├── gmail/
│ │ │ │ ├── add-flags.txt
│ │ │ │ ├── add-labels.txt
│ │ │ │ ├── append.1.txt
│ │ │ │ ├── append.10.txt
│ │ │ │ ├── append.11.txt
│ │ │ │ ├── append.12.txt
│ │ │ │ ├── append.13.txt
│ │ │ │ ├── append.14.txt
│ │ │ │ ├── append.15.txt
│ │ │ │ ├── append.16.txt
│ │ │ │ ├── append.17.txt
│ │ │ │ ├── append.18.txt
│ │ │ │ ├── append.19.txt
│ │ │ │ ├── append.2.txt
│ │ │ │ ├── append.20.txt
│ │ │ │ ├── append.21.txt
│ │ │ │ ├── append.22.txt
│ │ │ │ ├── append.23.txt
│ │ │ │ ├── append.24.txt
│ │ │ │ ├── append.25.txt
│ │ │ │ ├── append.26.txt
│ │ │ │ ├── append.27.txt
│ │ │ │ ├── append.28.txt
│ │ │ │ ├── append.29.txt
│ │ │ │ ├── append.3.txt
│ │ │ │ ├── append.30.txt
│ │ │ │ ├── append.31.txt
│ │ │ │ ├── append.32.txt
│ │ │ │ ├── append.33.txt
│ │ │ │ ├── append.34.txt
│ │ │ │ ├── append.35.txt
│ │ │ │ ├── append.36.txt
│ │ │ │ ├── append.37.txt
│ │ │ │ ├── append.38.txt
│ │ │ │ ├── append.39.txt
│ │ │ │ ├── append.4.txt
│ │ │ │ ├── append.40.txt
│ │ │ │ ├── append.41.txt
│ │ │ │ ├── append.42.txt
│ │ │ │ ├── append.43.txt
│ │ │ │ ├── append.44.txt
│ │ │ │ ├── append.45.txt
│ │ │ │ ├── append.46.txt
│ │ │ │ ├── append.47.txt
│ │ │ │ ├── append.48.txt
│ │ │ │ ├── append.49.txt
│ │ │ │ ├── append.5.txt
│ │ │ │ ├── append.50.txt
│ │ │ │ ├── append.6.txt
│ │ │ │ ├── append.7.txt
│ │ │ │ ├── append.8.txt
│ │ │ │ ├── append.9.txt
│ │ │ │ ├── authenticate+annotate.txt
│ │ │ │ ├── authenticate+create-special-use.txt
│ │ │ │ ├── authenticate+preview.txt
│ │ │ │ ├── authenticate+savedate.txt
│ │ │ │ ├── authenticate+statussize+objectid.txt
│ │ │ │ ├── authenticate+webalert.txt
│ │ │ │ ├── authenticate-no-appendlimit-value.txt
│ │ │ │ ├── authenticate.txt
│ │ │ │ ├── capability+login.txt
│ │ │ │ ├── capability+logindisabled.txt
│ │ │ │ ├── capability.txt
│ │ │ │ ├── count-explicit.noop.txt
│ │ │ │ ├── count-implicit.noop.txt
│ │ │ │ ├── count.examine.txt
│ │ │ │ ├── create-mailboxid.txt
│ │ │ │ ├── examine-inbox.txt
│ │ │ │ ├── expunge-during-fetch.txt
│ │ │ │ ├── expunge.txt
│ │ │ │ ├── fetch-all-headers.txt
│ │ │ │ ├── fetch-invalid-headers.txt
│ │ │ │ ├── fetch-korean-previewtext-bodystructure.txt
│ │ │ │ ├── fetch-korean-previewtext-peek-text-only.txt
│ │ │ │ ├── fetch-nil-bodystructure.txt
│ │ │ │ ├── fetch-nil.txt
│ │ │ │ ├── fetch-objectid.txt
│ │ │ │ ├── fetch-preview.txt
│ │ │ │ ├── fetch-previewtext-bodystructure.txt
│ │ │ │ ├── fetch-previewtext-peek-html-only.txt
│ │ │ │ ├── fetch-previewtext-peek-text-alternative.txt
│ │ │ │ ├── fetch-previewtext-peek-text-only.txt
│ │ │ │ ├── fetch-quoted-string-bodystructure.txt
│ │ │ │ ├── fetch-quoted-string.txt
│ │ │ │ ├── fetch-savedate.txt
│ │ │ │ ├── fetch.1+unsolicited-info.txt
│ │ │ │ ├── fetch.1.txt
│ │ │ │ ├── fetch.11.txt
│ │ │ │ ├── fetch.12.txt
│ │ │ │ ├── fetch.13.txt
│ │ │ │ ├── fetch.14.txt
│ │ │ │ ├── fetch.2.txt
│ │ │ │ ├── fetch.26.txt
│ │ │ │ ├── fetch.27.txt
│ │ │ │ ├── fetch.28.txt
│ │ │ │ ├── fetch.29.txt
│ │ │ │ ├── fetch.3.txt
│ │ │ │ ├── fetch.31.txt
│ │ │ │ ├── fetch.34.txt
│ │ │ │ ├── fetch.41.txt
│ │ │ │ ├── fetch.42.txt
│ │ │ │ ├── fetch.43.txt
│ │ │ │ ├── fetch.5.txt
│ │ │ │ ├── fetch.50.txt
│ │ │ │ ├── fetch.7.txt
│ │ │ │ ├── fetch.8.txt
│ │ │ │ ├── fetch.9.txt
│ │ │ │ ├── get-indexes.txt
│ │ │ │ ├── go-ahead.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── headers.1+unsolicited-info.txt
│ │ │ │ ├── idle-done.txt
│ │ │ │ ├── idle.txt
│ │ │ │ ├── list-all-no-status.txt
│ │ │ │ ├── list-all.txt
│ │ │ │ ├── list-archived-messages.txt
│ │ │ │ ├── list-archives.txt
│ │ │ │ ├── list-flagged.txt
│ │ │ │ ├── list-gmail-subfolders-no-status.txt
│ │ │ │ ├── list-gmail-subfolders.txt
│ │ │ │ ├── list-gmail.txt
│ │ │ │ ├── list-inbox.txt
│ │ │ │ ├── list-level1.txt
│ │ │ │ ├── list-level2.txt
│ │ │ │ ├── list-level3.txt
│ │ │ │ ├── list-personal-status-appendlimit.txt
│ │ │ │ ├── list-personal.txt
│ │ │ │ ├── list-sublevel1.txt
│ │ │ │ ├── list-sublevel2.txt
│ │ │ │ ├── list-toplevel1.txt
│ │ │ │ ├── list-toplevel2.txt
│ │ │ │ ├── list-unittests-dummy.txt
│ │ │ │ ├── list-unittests.txt
│ │ │ │ ├── logout.txt
│ │ │ │ ├── lsub-all.txt
│ │ │ │ ├── lsub-personal.txt
│ │ │ │ ├── namespace.txt
│ │ │ │ ├── precise-pangolin-message.txt
│ │ │ │ ├── rename-unittests.txt
│ │ │ │ ├── search-deleted-not-1-3.txt
│ │ │ │ ├── search-summary.txt
│ │ │ │ ├── search.txt
│ │ │ │ ├── select-inbox.txt
│ │ │ │ ├── select-sublevel1.txt
│ │ │ │ ├── select-sublevel2.txt
│ │ │ │ ├── select-toplevel.txt
│ │ │ │ ├── select-unittests.txt
│ │ │ │ ├── set-flags.txt
│ │ │ │ ├── set-labels.txt
│ │ │ │ ├── status-+folder.txt
│ │ │ │ ├── status-all-mail.txt
│ │ │ │ ├── status-drafts.txt
│ │ │ │ ├── status-important.txt
│ │ │ │ ├── status-inbox-appendlimit-nil.txt
│ │ │ │ ├── status-inbox-appendlimit.txt
│ │ │ │ ├── status-inbox.txt
│ │ │ │ ├── status-sent-mail.txt
│ │ │ │ ├── status-spam.txt
│ │ │ │ ├── status-starred.txt
│ │ │ │ ├── status-trash.txt
│ │ │ │ ├── uid-copy.txt
│ │ │ │ ├── uid-expunge.txt
│ │ │ │ ├── uid-move.txt
│ │ │ │ ├── utf8accept.txt
│ │ │ │ └── xlist.txt
│ │ │ ├── icloud/
│ │ │ │ ├── authenticate-plain.txt
│ │ │ │ ├── capability.txt
│ │ │ │ ├── enable-qresync.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── list-inbox.txt
│ │ │ │ └── namespace.txt
│ │ │ ├── lowercase/
│ │ │ │ ├── authenticate.txt
│ │ │ │ ├── capability.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ └── list.txt
│ │ │ ├── metadata/
│ │ │ │ ├── authenticate.txt
│ │ │ │ ├── capability.txt
│ │ │ │ ├── getmetadata-multi.txt
│ │ │ │ ├── getmetadata-options.txt
│ │ │ │ ├── getmetadata.txt
│ │ │ │ ├── inbox-getmetadata-multi.txt
│ │ │ │ ├── inbox-getmetadata-options.txt
│ │ │ │ ├── inbox-getmetadata.txt
│ │ │ │ ├── inbox-setmetadata-maxsize.txt
│ │ │ │ ├── inbox-setmetadata-noprivate.txt
│ │ │ │ ├── inbox-setmetadata-toomany.txt
│ │ │ │ ├── setmetadata-maxsize.txt
│ │ │ │ ├── setmetadata-noprivate.txt
│ │ │ │ └── setmetadata-toomany.txt
│ │ │ ├── protonmail/
│ │ │ │ ├── capability.txt
│ │ │ │ └── greeting.txt
│ │ │ ├── qqmail/
│ │ │ │ └── greeting.txt
│ │ │ ├── smartermail/
│ │ │ │ └── greeting.txt
│ │ │ ├── strato.de/
│ │ │ │ ├── authenticate.txt
│ │ │ │ ├── capability.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── list-inbox.txt
│ │ │ │ ├── namespace.txt
│ │ │ │ └── xlist.txt
│ │ │ ├── uw/
│ │ │ │ ├── greeting.txt
│ │ │ │ └── preauth-greeting.txt
│ │ │ ├── yahoo/
│ │ │ │ ├── capabilities.txt
│ │ │ │ ├── examine-inbox.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── list-inbox.txt
│ │ │ │ ├── namespace.txt
│ │ │ │ └── search.txt
│ │ │ ├── yandex/
│ │ │ │ ├── authenticate.txt
│ │ │ │ ├── capability.txt
│ │ │ │ ├── getbodypart-missing-content.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── list-inbox.txt
│ │ │ │ ├── namespace.txt
│ │ │ │ ├── select-inbox.txt
│ │ │ │ └── xlist.txt
│ │ │ └── zoho/
│ │ │ ├── authenticate.txt
│ │ │ ├── capability.txt
│ │ │ ├── examine-gesendet.txt
│ │ │ ├── fetch-negative-modseq-values.txt
│ │ │ ├── greeting.txt
│ │ │ ├── list-inbox.txt
│ │ │ ├── namespace.txt
│ │ │ └── xlist.txt
│ │ ├── NetworkStreamTests.cs
│ │ ├── Pop3/
│ │ │ ├── Pop3AuthenticationSecretDetectorTests.cs
│ │ │ ├── Pop3ClientTests.cs
│ │ │ ├── Pop3CommandExceptionTests.cs
│ │ │ ├── Pop3ReplayStream.cs
│ │ │ ├── Pop3StreamTests.cs
│ │ │ └── Resources/
│ │ │ ├── comcast/
│ │ │ │ ├── capa1.txt
│ │ │ │ ├── capa2.txt
│ │ │ │ ├── err.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── list-error1.txt
│ │ │ │ ├── list-error2.txt
│ │ │ │ ├── list-error3.txt
│ │ │ │ ├── list.txt
│ │ │ │ ├── list1-error1.txt
│ │ │ │ ├── list1-error2.txt
│ │ │ │ ├── list1-error3.txt
│ │ │ │ ├── list1.txt
│ │ │ │ ├── ok.txt
│ │ │ │ ├── quit.txt
│ │ │ │ ├── retr1.txt
│ │ │ │ ├── stat-error1.txt
│ │ │ │ ├── stat-error2.txt
│ │ │ │ ├── stat-error3.txt
│ │ │ │ └── stat.txt
│ │ │ ├── common/
│ │ │ │ ├── err-greeting.txt
│ │ │ │ └── ok-greeting.txt
│ │ │ ├── exchange/
│ │ │ │ ├── auth.txt
│ │ │ │ ├── capa.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── plus.txt
│ │ │ │ ├── quit.txt
│ │ │ │ ├── retr1.txt
│ │ │ │ ├── stat.txt
│ │ │ │ └── uidl.txt
│ │ │ ├── gmail/
│ │ │ │ ├── auth.txt
│ │ │ │ ├── capa1.txt
│ │ │ │ ├── capa2.txt
│ │ │ │ ├── dele.txt
│ │ │ │ ├── dele123.txt
│ │ │ │ ├── greeting.txt
│ │ │ │ ├── list.txt
│ │ │ │ ├── list1.txt
│ │ │ │ ├── list2.txt
│ │ │ │ ├── list3.txt
│ │ │ │ ├── noop.txt
│ │ │ │ ├── plus.txt
│ │ │ │ ├── quit.txt
│ │ │ │ ├── retr1-parse-error.txt
│ │ │ │ ├── retr1.txt
│ │ │ │ ├── retr123.txt
│ │ │ │ ├── rset.txt
│ │ │ │ ├── stat.txt
│ │ │ │ ├── top.txt
│ │ │ │ ├── top123.txt
│ │ │ │ ├── uidl-error1.txt
│ │ │ │ ├── uidl-error2.txt
│ │ │ │ ├── uidl.txt
│ │ │ │ ├── uidl1-error1.txt
│ │ │ │ ├── uidl1-error2.txt
│ │ │ │ ├── uidl1.txt
│ │ │ │ ├── uidl2.txt
│ │ │ │ └── uidl3.txt
│ │ │ └── lang/
│ │ │ ├── auth.txt
│ │ │ ├── capa1.txt
│ │ │ ├── capa2.txt
│ │ │ ├── getlang.txt
│ │ │ ├── greeting.txt
│ │ │ ├── quit.txt
│ │ │ ├── setlang.txt
│ │ │ ├── stat.txt
│ │ │ └── utf8.txt
│ │ ├── Proxy/
│ │ │ ├── HttpProxyClientTests.cs
│ │ │ ├── HttpProxyListener.cs
│ │ │ ├── HttpsProxyClientTests.cs
│ │ │ ├── ProxyListener.cs
│ │ │ ├── ProxyProtocolExceptionTests.cs
│ │ │ ├── Socks4ClientTests.cs
│ │ │ ├── Socks4ProxyListener.cs
│ │ │ ├── Socks4aClientTests.cs
│ │ │ ├── Socks4aProxyListener.cs
│ │ │ ├── Socks5ClientTests.cs
│ │ │ ├── Socks5ProxyListener.cs
│ │ │ └── WebProxyClientTests.cs
│ │ ├── Smtp/
│ │ │ ├── Resources/
│ │ │ │ ├── auth-failed.txt
│ │ │ │ ├── auth-required.txt
│ │ │ │ ├── auth-successful.txt
│ │ │ │ ├── auth-too-weak.txt
│ │ │ │ ├── bad-command-sequence.txt
│ │ │ │ ├── comcast-auth-digest-md5-reset.txt
│ │ │ │ ├── comcast-auth-digest-md5-response.txt
│ │ │ │ ├── comcast-auth-digest-md5.txt
│ │ │ │ ├── comcast-auth-login-password.txt
│ │ │ │ ├── comcast-auth-login-username.txt
│ │ │ │ ├── comcast-auth-login.txt
│ │ │ │ ├── comcast-auth-plain.txt
│ │ │ │ ├── comcast-data-done.txt
│ │ │ │ ├── comcast-data.txt
│ │ │ │ ├── comcast-ehlo+binarymime.txt
│ │ │ │ ├── comcast-ehlo+digest-md5.txt
│ │ │ │ ├── comcast-ehlo+dsn.txt
│ │ │ │ ├── comcast-ehlo+pipelining.txt
│ │ │ │ ├── comcast-ehlo+requiretls.txt
│ │ │ │ ├── comcast-ehlo+smtputf8.txt
│ │ │ │ ├── comcast-ehlo+x-exps.txt
│ │ │ │ ├── comcast-ehlo.txt
│ │ │ │ ├── comcast-greeting.txt
│ │ │ │ ├── comcast-mail-from.txt
│ │ │ │ ├── comcast-noop.txt
│ │ │ │ ├── comcast-quit.txt
│ │ │ │ ├── comcast-rcpt-to.txt
│ │ │ │ ├── comcast-rset.txt
│ │ │ │ ├── ehlo-failed.txt
│ │ │ │ ├── greeting-not-ready.txt
│ │ │ │ ├── helo.txt
│ │ │ │ ├── mailbox-unavailable.txt
│ │ │ │ ├── pipelined-mail-from-rcpt-to.txt
│ │ │ │ ├── pipelined-mailbox-unavailable.txt
│ │ │ │ ├── rfc0821-expn.txt
│ │ │ │ └── rfc0821-vrfy.txt
│ │ │ ├── SmtpAuthenticationSecretDetectorTests.cs
│ │ │ ├── SmtpClientTests.cs
│ │ │ ├── SmtpCommandExceptionTests.cs
│ │ │ ├── SmtpDataFilterTests.cs
│ │ │ ├── SmtpProtocolExceptionTests.cs
│ │ │ ├── SmtpReplayStream.cs
│ │ │ └── SmtpStreamTests.cs
│ │ └── SocketUtilsTests.cs
│ ├── ProgressStreamTests.cs
│ ├── ProtocolLoggerTests.cs
│ ├── ReplaceRequestTests.cs
│ ├── Search/
│ │ └── SearchQueryTests.cs
│ ├── Security/
│ │ ├── AuthenticationExceptionTests.cs
│ │ ├── ChannelBindingContext.cs
│ │ ├── Ntlm/
│ │ │ ├── MD4Tests.cs
│ │ │ ├── NtlmAuthenticateMessageTests.cs
│ │ │ ├── NtlmChallengeMessageTests.cs
│ │ │ ├── NtlmNegotiateMessageTests.cs
│ │ │ ├── NtlmSingleHostDataTests.cs
│ │ │ ├── NtlmTargetInfoTests.cs
│ │ │ └── RC4Tests.cs
│ │ ├── SaslExceptionTests.cs
│ │ ├── SaslMechanismAnonymousTests.cs
│ │ ├── SaslMechanismCramMd5Tests.cs
│ │ ├── SaslMechanismDigestMd5Tests.cs
│ │ ├── SaslMechanismLoginTests.cs
│ │ ├── SaslMechanismNtlmTests.cs
│ │ ├── SaslMechanismOAuth2Tests.cs
│ │ ├── SaslMechanismOAuthBearerTests.cs
│ │ ├── SaslMechanismPlainTests.cs
│ │ ├── SaslMechanismScramSha1Tests.cs
│ │ ├── SaslMechanismScramSha256Tests.cs
│ │ ├── SaslMechanismScramSha512Tests.cs
│ │ ├── SaslMechanismTests.cs
│ │ └── SslHandshakeExceptionTests.cs
│ ├── StoreFlagsRequestTests.cs
│ ├── StoreLabelsRequestTests.cs
│ ├── TestHelper.cs
│ ├── UniqueIdMapTests.cs
│ ├── UniqueIdRangeTests.cs
│ ├── UniqueIdSetTests.cs
│ ├── UniqueIdTests.cs
│ ├── UnitTests.csproj
│ └── UriExtensionTests.cs
├── cov-build.bat
├── nuget/
│ ├── GettingStarted.md
│ ├── MailKit.nuspec
│ └── MailKitLite.nuspec
├── rfc/
│ ├── SOCKS4.protocol
│ ├── draft-murchison-sasl-login-00.txt
│ ├── rfc0821.txt
│ ├── rfc1652.txt
│ ├── rfc1730.txt
│ ├── rfc1731.txt
│ ├── rfc1734.txt
│ ├── rfc1854.txt
│ ├── rfc1870.txt
│ ├── rfc1891.txt
│ ├── rfc1928.txt
│ ├── rfc1929.txt
│ ├── rfc1939.txt
│ ├── rfc1961.txt
│ ├── rfc2034.txt
│ ├── rfc2060.txt
│ ├── rfc2086.txt
│ ├── rfc2087.txt
│ ├── rfc2088.txt
│ ├── rfc2177.txt
│ ├── rfc2193.txt
│ ├── rfc2195.txt
│ ├── rfc2197.txt
│ ├── rfc2221.txt
│ ├── rfc2222.txt
│ ├── rfc2245.txt
│ ├── rfc2342.txt
│ ├── rfc2359.txt
│ ├── rfc2449.txt
│ ├── rfc2487.txt
│ ├── rfc2554.txt
│ ├── rfc2595.txt
│ ├── rfc2683.txt
│ ├── rfc2821.txt
│ ├── rfc2831.txt
│ ├── rfc2920.txt
│ ├── rfc2971.txt
│ ├── rfc3030.txt
│ ├── rfc3207.txt
│ ├── rfc3348.txt
│ ├── rfc3461.txt
│ ├── rfc3501.txt
│ ├── rfc3502.txt
│ ├── rfc3516.txt
│ ├── rfc3691.txt
│ ├── rfc4013.txt
│ ├── rfc4314.txt
│ ├── rfc4315.txt
│ ├── rfc4466.txt
│ ├── rfc4469.txt
│ ├── rfc4505.txt
│ ├── rfc4551.txt
│ ├── rfc4616.txt
│ ├── rfc4731.txt
│ ├── rfc4959.txt
│ ├── rfc4978.txt
│ ├── rfc5032.txt
│ ├── rfc5161.txt
│ ├── rfc5162.txt
│ ├── rfc5182.txt
│ ├── rfc5255.txt
│ ├── rfc5256.txt
│ ├── rfc5257.txt
│ ├── rfc5258.txt
│ ├── rfc5259.txt
│ ├── rfc5267.txt
│ ├── rfc5321.txt
│ ├── rfc5464.txt
│ ├── rfc5465.txt
│ ├── rfc5466.txt
│ ├── rfc5530.txt
│ ├── rfc5788.txt
│ ├── rfc5801.txt
│ ├── rfc5802.txt
│ ├── rfc5819.txt
│ ├── rfc5957.txt
│ ├── rfc6154.txt
│ ├── rfc6203.txt
│ ├── rfc6237.txt
│ ├── rfc6531.txt
│ ├── rfc6851.txt
│ ├── rfc6855.txt
│ ├── rfc6856.txt
│ ├── rfc7162.txt
│ ├── rfc7377.txt
│ ├── rfc7628.txt
│ ├── rfc7677.txt
│ ├── rfc7888.txt
│ ├── rfc7889.txt
│ ├── rfc8437.txt
│ ├── rfc8438.txt
│ ├── rfc8440.txt
│ ├── rfc8457.txt
│ ├── rfc8474.txt
│ ├── rfc8508.txt
│ ├── rfc8514.txt
│ ├── rfc8689.txt
│ ├── rfc8970.txt
│ ├── rfc9051.txt
│ ├── rfc9208.txt
│ └── rfc9394.txt
├── samples/
│ ├── ImapClientDemo/
│ │ ├── .gitignore
│ │ ├── ImapClientDemo/
│ │ │ ├── App.config
│ │ │ ├── AuthenticationFailedEventArgs.cs
│ │ │ ├── ClientCommand.cs
│ │ │ ├── ClientCommandPipeline.cs
│ │ │ ├── ClientConnection.cs
│ │ │ ├── ClientConnections.cs
│ │ │ ├── CommandFailedEventArgs.cs
│ │ │ ├── ConnectionFailedEventArgs.cs
│ │ │ ├── CustomTaskScheduler.cs
│ │ │ ├── FolderNameComparer.cs
│ │ │ ├── FolderSelectedEventArgs.cs
│ │ │ ├── FolderTreeView.cs
│ │ │ ├── ImapClientDemo.csproj
│ │ │ ├── LoginWindow.Designer.cs
│ │ │ ├── LoginWindow.cs
│ │ │ ├── LoginWindow.resx
│ │ │ ├── MainWindow.Designer.cs
│ │ │ ├── MainWindow.cs
│ │ │ ├── MainWindow.resx
│ │ │ ├── MessageInfo.cs
│ │ │ ├── MessageList.cs
│ │ │ ├── MessageSelectedEventArgs.cs
│ │ │ ├── MultipartRelatedImageContext.cs
│ │ │ ├── Program.cs
│ │ │ └── Properties/
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ ├── Resources.resx
│ │ │ ├── Settings.Designer.cs
│ │ │ └── Settings.settings
│ │ └── ImapClientDemo.sln
│ ├── ImapClientDemo.Android/
│ │ ├── ImapClientDemo.Android/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── FoldersActivity.cs
│ │ │ ├── ImapClientDemo.Android.csproj
│ │ │ ├── LoginActivity.cs
│ │ │ ├── Mail.cs
│ │ │ ├── MainActivity.cs
│ │ │ ├── MessageListActivity.cs
│ │ │ ├── MessageViewActivity.cs
│ │ │ └── Resources/
│ │ │ ├── AboutResources.txt
│ │ │ ├── Resource.designer.cs
│ │ │ ├── layout/
│ │ │ │ ├── FoldersLayout.xml
│ │ │ │ ├── LoginLayout.xml
│ │ │ │ ├── Main.xml
│ │ │ │ ├── MessageListItemLayout.xml
│ │ │ │ ├── MessagesLayout.xml
│ │ │ │ └── ViewMessageLayout.xml
│ │ │ ├── mipmap-anydpi-v26/
│ │ │ │ ├── appicon.xml
│ │ │ │ └── appicon_round.xml
│ │ │ └── values/
│ │ │ ├── Strings.xml
│ │ │ └── themes.xml
│ │ └── ImapClientDemo.Android.sln
│ ├── ImapClientDemo.iOS/
│ │ ├── ImapClientDemo.iOS/
│ │ │ ├── AppDelegate.cs
│ │ │ ├── Assets.xcassets/
│ │ │ │ └── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ ├── Entitlements.plist
│ │ │ ├── FoldersViewController.cs
│ │ │ ├── ImapClientDemo.iOS.csproj
│ │ │ ├── Info.plist
│ │ │ ├── LaunchScreen.storyboard
│ │ │ ├── LoginViewController.cs
│ │ │ ├── Mail.cs
│ │ │ ├── Main.cs
│ │ │ ├── MessageListViewController.cs
│ │ │ ├── MessageViewController.cs
│ │ │ ├── MultipartRelatedUrlCache.cs
│ │ │ ├── Resources/
│ │ │ │ └── LaunchScreen.xib
│ │ │ └── SceneDelegate.cs
│ │ └── ImapClientDemo.iOS.sln
│ └── ImapIdle/
│ ├── .gitignore
│ ├── ImapIdle/
│ │ ├── IdleClient.cs
│ │ ├── ImapIdle.csproj
│ │ └── Program.cs
│ └── ImapIdle.sln
└── scripts/
├── coveralls.ps1
├── test-aot-compatibility.ps1
├── test.ps1
└── update-version.ps1
================================================
FILE CONTENTS
================================================
================================================
FILE: .config/dotnet-tools.json
================================================
{
"version": 1,
"isRoot": true,
"tools": {
"altcover.global": {
"version": "9.0.102",
"commands": [
"altcover"
],
"rollForward": false
},
"coveralls.net": {
"version": "4.0.1",
"commands": [
"csmacnz.Coveralls"
],
"rollForward": false
},
"nunit.consolerunner.netcore": {
"version": "3.22.0",
"commands": [
"nunit"
],
"rollForward": false
}
}
}
================================================
FILE: .editorconfig
================================================
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true
# C# files
[*.cs]
#### Core EditorConfig Options ####
# Indentation and spacing
indent_size = 4
indent_style = tab
tab_width = 4
# New line preferences
end_of_line = crlf
insert_final_newline = true
#### .NET Coding Conventions ####
# Organize usings
dotnet_separate_import_directive_groups = true
dotnet_sort_system_directives_first = true
file_header_template = unset
# this. and Me. preferences
dotnet_style_qualification_for_event = false:silent
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_property = false:silent
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
# Expression-level preferences
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_object_initializer = true:suggestion
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
# Field preferences
dotnet_style_readonly_field = true:suggestion
# Parameter preferences
dotnet_code_quality_unused_parameters = all:suggestion
#### C# Coding Conventions ####
# var preferences
csharp_style_var_elsewhere = false:silent
csharp_style_var_for_built_in_types = false:silent
csharp_style_var_when_type_is_apparent = false:silent
# Expression-bodied members
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_prefer_switch_expression = true:suggestion
# Null-checking preferences
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_prefer_static_local_function = true:suggestion
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent
# Code-block preferences
csharp_prefer_braces = true:silent
csharp_prefer_simple_using_statement = true:suggestion
# Expression-level preferences
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:silent
#### C# Formatting Rules ####
# New line preferences
csharp_new_line_before_catch = false
csharp_new_line_before_else = false
csharp_new_line_before_finally = false
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = methods,types
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = false
# Space preferences
csharp_space_after_cast = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = true
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
#### Naming styles ####
# Naming rules
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
================================================
FILE: .gitattributes
================================================
*.csproj text
*.nuspec text
*.sln eol=crlf
*.msg text
*.txt text
*.yml text
*.cs text
*.md text
================================================
FILE: .github/FUNDING.yml
================================================
github: jstedfast
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**Platform (please complete the following information):**
- OS: [e.g. Windows, Linux, MacOS, iOS, Android, Windows Phone, etc.]
- .NET Runtime: [e.g. CoreCLR, Mono]
- .NET Framework: [e.g. .Net Core, .NET 4.5, UWP, etc.]
- MailKit Version:
**Exception**
If you got an exception, please include the exception Message *and* StackTrace.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Code Snippets**
If applicable, add code snippets to help explain your problem.
```csharp
// Add your code snippet here.
```
**Protocol Logs**
Please include a protocol log (scrubbed of any authentication data), especially
if you got an exception such as `Syntax error in XYZ. Unexpected token: ...`.
To get a protocol log, follow one of the following code snippets:
```csharp
// log to a file called 'imap.log'
var client = new ImapClient (new ProtocolLogger ("imap.log"));
```
```csharp
// log to a file called 'pop3.log'
var client = new Pop3Client (new ProtocolLogger ("pop3.log"));
```
```csharp
// log to a file called 'smtp.log'
var client = new SmtpClient (new ProtocolLogger ("smtp.log"));
```
Note: if the protocol log contains sensitive information, feel free to email it to me at
jestedfa@microsoft.com instead of including it in the GitHub issue.
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/dependabot.yml
================================================
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "08:00"
timezone: "America/New_York"
================================================
FILE: .github/workflows/aot-compatibility.yml
================================================
name: AOT Compatibility
on:
push:
branches: [ 'master' ]
paths-ignore:
- '**.md'
pull_request:
branches: [ 'master' ]
paths-ignore:
- '**.md'
jobs:
aot-test:
strategy:
fail-fast: false # ensures the entire test matrix is run, even if one permutation fails
matrix:
os: [ windows-latest ]
mailkitlite: [ true ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # fetching all
submodules: true
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: publish AOT testApp, assert static analysis warning count, and run the app
shell: pwsh
run: .\scripts\test-aot-compatibility.ps1 ${{ matrix.mailkitlite }}
================================================
FILE: .github/workflows/codeql.yml
================================================
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: '38 12 * * 1'
jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'csharp' ]
steps:
- name: Setup/Install the .NET 8 SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
submodules: recursive
fetch-depth: 0
- name: Run .NET restore
shell: pwsh
run: |
dotnet restore MailKit.sln
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
- name: Build
continue-on-error: false
shell: pwsh
run: |
dotnet msbuild MailKit.sln -property:Platform="Any CPU" -property:Configuration=Release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
================================================
FILE: .github/workflows/main.yml
================================================
name: Build
on: [push, pull_request, workflow_dispatch]
jobs:
ci:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ windows-latest, ubuntu-latest ]
build-configuration: [ Debug, Release ]
outputs:
latest-version: ${{ steps.semantic_version.outputs.version_num }}
environment: ci
env:
SOLUTION_PATH: MailKit.sln
BUILD_PLATFORM: Any CPU
BUILD_CONFIGURATION: ${{ matrix.build-configuration }}
GENERATE_CODE_COVERAGE: ${{ matrix.os == 'windows-latest' && matrix.build-configuration == 'Debug' }}
MONO_RUNTIME: ${{ matrix.os != 'windows-latest' }}
PUBLISH: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.os == 'windows-latest' && matrix.build-configuration == 'Release' }}
steps:
- name: Setup/Install the .NET 8 SDK
id: install-netsdk8
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Setup/Install the .NET 10 SDK
id: install-netsdk
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- if: runner.os == 'Windows'
name: Setup MSBuild
id: setup_msbuild
uses: microsoft/setup-msbuild@v2
- name: Checkout repository
id: checkout_repo
uses: actions/checkout@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
submodules: recursive
fetch-depth: 0
- name: Get semantic version from csproj
id: semantic_version
shell: pwsh
run: |
$xml = [xml](gc MailKit/MailKit.csproj)
$SEMANTIC_VERSION_NUMBER = $xml.Project.PropertyGroup.VersionPrefix
$VERSION_NUM = $SEMANTIC_VERSION_NUMBER[0].Trim()
Write-Host "version_num=${VERSION_NUM}"
[IO.File]::AppendAllText($env:GITHUB_OUTPUT, "version_num=${VERSION_NUM}$([Environment]::NewLine)")
- if: ${{ env.PUBLISH == 'true' }}
name: Get latest tag
id: get_latest_tag
shell: pwsh
run: |
$LATEST_TAG = git -c 'versionsort.suffix=-' ls-remote --exit-code --refs --sort='version:refname' --tags "https://github.com/$env:GIT_URL.git" '*.*.*' | tail --lines=1 | cut --delimiter='/' --fields=3
Write-Host "tag=$LATEST_TAG"
[IO.File]::AppendAllText($env:GITHUB_OUTPUT, "tag=${LATEST_TAG}$([Environment]::NewLine)")
env:
GIT_URL: ${{ github.repository }}
- if: ${{ env.PUBLISH == 'true' && steps.semantic_version.outputs.version_num != steps.get_latest_tag.outputs.tag }}
name: Add new tag to repo
id: add_new_tag_to_repo
continue-on-error: true
shell: pwsh
run: |
git config --global user.name $env:GIT_USER_NAME
git config --global user.email $env:GIT_USER_EMAIL
git tag -a -m "Tagged for $env:NEW_VERSION_NUM" $env:NEW_VERSION_NUM
git push --follow-tags
env:
GIT_USER_NAME: ${{ github.event.head_commit.author.username }}
GIT_USER_EMAIL: ${{ github.event.head_commit.author.email }}
NEW_VERSION_NUM: ${{ steps.semantic_version.outputs.version_num }}
- name: Run .NET restore
shell: pwsh
run: |
dotnet restore $env:SOLUTION_PATH
- name: Run .NET tool restore
shell: pwsh
run: |
dotnet tool restore
- name: Build solution
id: build_solution
continue-on-error: true
shell: pwsh
run: |
dotnet msbuild $env:SOLUTION_PATH -property:Platform=$env:BUILD_PLATFORM -property:Configuration=$env:BUILD_CONFIGURATION -property:MonoRuntime=$env:MONO_RUNTIME
- name: Run unit tests
id: run_unit_tests
continue-on-error: true
shell: pwsh
run: |
& ./scripts/test.ps1 -Configuration:$env:BUILD_CONFIGURATION -GenerateCodeCoverage:$env:GENERATE_CODE_COVERAGE
- name: Upload unit test results
id: upload_test_results
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: MailKit.${{ steps.semantic_version.outputs.version_num }}.${{ github.run_number }}-${{ matrix.os }}-${{ matrix.build-configuration }}-TestResults.xml
path: TestResult.xml
- if: ${{ env.GENERATE_CODE_COVERAGE == 'true' }}
name: Upload code coverage data to coveralls.io
id: upload_to_coveralls
shell: pwsh
run: |
& ./scripts/coveralls.ps1
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
GIT_COMMIT_SHA: ${{ github.sha }}
GIT_REF: ${{ github.ref }}
GIT_ACTOR: ${{ github.event.head_commit.author.username }}
GIT_ACTOR_EMAIL: ${{ github.event.head_commit.author.email }}
GIT_COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
COVERALLS_JOB_ID: ${{ steps.semantic_version.outputs.version_num }}.${{ github.run_number }}
- if: ${{ env.PUBLISH == 'true' }}
name: Create NuGet package
id: create_nuget_package
shell: pwsh
run: |
nuget pack nuget/MailKit.nuspec -Version "$env:LATEST_VERSION.$env:GITHUB_RUN_NUMBER"
env:
LATEST_VERSION: ${{ steps.semantic_version.outputs.version_num }}
- if: ${{ env.PUBLISH == 'true' }}
name: Push NuGet package to MyGet
id: push_nuget_package
shell: pwsh
run: |
nuget push $env:NUGET_PKG_PATH -ApiKey $env:MYGET_API_KEY -Source https://www.myget.org/F/mimekit/api/v3/index.json
env:
NUGET_PKG_PATH: MailKit.${{ steps.semantic_version.outputs.version_num }}.${{ github.run_number }}.nupkg
MYGET_API_KEY: ${{ secrets.MYGET_API_KEY }}
- if: ${{ env.PUBLISH == 'true' }}
name: Upload NuGet package as artifact
id: upload_nuget_package
uses: actions/upload-artifact@v4
with:
name: MailKit.${{ steps.semantic_version.outputs.version_num }}.${{ github.run_number }}.nupkg
path: MailKit.${{ steps.semantic_version.outputs.version_num }}.${{ github.run_number }}.nupkg
# Built with ❤ by [Pipeline Foundation](https://pipeline.foundation)
================================================
FILE: .gitignore
================================================
MailKit/Resources/Resource.designer.cs
*.csproj.nuget.dgspec.json
*.csproj.nuget.cache
*project.lock.json
*.userprefs
*.user
*.suo
*~
test-results
packages
obj
bin
.vs
*.patch
*.tree
*.zip
.idea
.DS_Store
================================================
FILE: .gitmodules
================================================
[submodule "submodules/MimeKit"]
path = submodules/MimeKit
url = https://github.com/jstedfast/MimeKit.git
================================================
FILE: AotCompatibility/AotCompatibility.csproj
================================================
Hey Alice, What are you up to this weekend? Monica is throwing one of her parties on
Saturday and I was hoping you could make it. Will you be my +1? -- Joey
System.Text.Encoding.RegisterProvider (System.Text.CodePagesEncodingProvider.Instance);
System.Text.Encoding.RegisterProvider (System.Text.CodePagesEncodingProvider.Instance);
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
using (var client = new SmtpClient ()) {
client.ServerCertificateValidationCallback = (s,c,h,e) => true;
client.Connect (hostName, port, SecureSocketOptions.Auto);
// ...
}
bool MyServerCertificateValidationCallback (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
// Note: The following code casts to an X509Certificate2 because it's easier to get the
// values for comparison, but it's possible to get them from an X509Certificate as well.
if (certificate is X509Certificate2 certificate2) {
var cn = certificate2.GetNameInfo (X509NameType.SimpleName, false);
var fingerprint = certificate2.Thumbprint;
var serial = certificate2.SerialNumber;
var issuer = certificate2.Issuer;
return cn == "imap.gmail.com" && issuer == "CN=GTS CA 1O1, O=Google Trust Services, C=US" &&
serial == "00BABE95B167C9ECAF08000000006065B6" &&
fingerprint == "E79A011EF55EEC72D2B7E391D193761372796836";
}
return false;
}
using (var client = new SmtpClient ()) {
client.CheckCertificateRevocation = false;
client.Connect (hostName, port, SecureSocketOptions.Auto);
// ...
}
using (var client = new SmtpClient ()) {
// Allow SSLv3.0 and all versions of TLS
client.SslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;
client.Connect ("smtp.gmail.com", 465, true);
// ...
}
// log to a file called 'imap.log'
var client = new ImapClient (new ProtocolLogger ("imap.log"));
// log to standard output (i.e. the console)
var client = new ImapClient (new ProtocolLogger (Console.OpenStandardOutput ()));
using (var client = new ImapClient ()) {
client.Connect ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
client.Authenticate ("user@gmail.com", "app-specific-password");
// do stuff...
client.Disconnect (true);
}
const string GMailAccount = "username@gmail.com";
var clientSecrets = new ClientSecrets {
ClientId = "XXX.apps.googleusercontent.com",
ClientSecret = "XXX"
};
var codeFlow = new GoogleAuthorizationCodeFlow (new GoogleAuthorizationCodeFlow.Initializer {
// Cache tokens in ~/.local/share/google-filedatastore/CredentialCacheFolder on Linux/Mac
DataStore = new FileDataStore ("CredentialCacheFolder", false),
Scopes = new [] { "https://mail.google.com/" },
ClientSecrets = clientSecrets
});
var codeReceiver = new LocalServerCodeReceiver ();
var authCode = new AuthorizationCodeInstalledApp (codeFlow, codeReceiver);
var credential = await authCode.AuthorizeAsync (GMailAccount, CancellationToken.None);
if (authCode.ShouldRequestAuthorizationCode (credential.Token))
await credential.RefreshTokenAsync (CancellationToken.None);
var oauth2 = new SaslMechanismOAuth2 (credential.UserId, credential.Token.AccessToken);
using (var client = new ImapClient ()) {
await client.ConnectAsync ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
await client.AuthenticateAsync (oauth2);
await client.DisconnectAsync (true);
}
multipart/alternative
text/plain
text/html
multipart/alternative
text/plain
multipart/related
text/html
image/jpeg
image/png
multipart/mixed
text/plain
application/octet-stream
application/zip
multipart/mixed
multipart/alternative
text/plain
text/html
application/octet-stream
application/zip
multipart/mixed
multipart/alternative
text/plain
multipart/related
text/html
image/jpeg
image/png
application/octet-stream
application/zip
var attachments = message.BodyParts.OfType<MimePart> ().Where (part => !string.IsNullOrEmpty (part.FileName));
message.WriteTo ("message.eml");
// clone the default formatting options
var format = FormatOptions.Default.Clone ();
// override the line-endings to be DOS no matter what platform we are on
format.NewLineFormat = NewLineFormat.Dos;
message.WriteTo (format, "message.eml");
foreach (var mailbox in message.To.Mailboxes)
Console.WriteLine ("{0}'s email address is {1}", mailbox.Name, mailbox.Address);
Parameter param;
if (attachment.ContentDisposition.Parameters.TryGetValue ("filename", out param))
param.EncodingMethod = ParameterEncodingMethod.Rfc2047;
var options = FormatOptions.Default.Clone ();
options.ParameterEncodingMethod = ParameterEncodingMethod.Rfc2047;
message.WriteTo (options, stream);
foreach (var uid in folder.Search (SearchQuery.NotSeen)) {
var message = folder.GetMessage (uid);
}
multipart/alternative
text/plain
text/html
multipart/alternative
text/plain
multipart/related
text/html
image/jpeg
video/mp4
image/png
urls that refer to images embedded within the message with
// "file://" urls that the browser control will actually be able to load.
void HtmlTagCallback (HtmlTagContext ctx, HtmlWriter htmlWriter)
{
if (ctx.TagId == HtmlTagId.Meta && !ctx.IsEndTag) {
bool isContentType = false;
ctx.WriteTag (htmlWriter, false);
// replace charsets with "utf-8" since our output will be in utf-8 (and not whatever the original charset was)
foreach (var attribute in ctx.Attributes) {
if (attribute.Id == HtmlAttributeId.Charset) {
htmlWriter.WriteAttributeName (attribute.Name);
htmlWriter.WriteAttributeValue ("utf-8");
} else if (isContentType && attribute.Id == HtmlAttributeId.Content) {
htmlWriter.WriteAttributeName (attribute.Name);
htmlWriter.WriteAttributeValue ("text/html; charset=utf-8");
} else {
if (attribute.Id == HtmlAttributeId.HttpEquiv && attribute.Value != null
&& attribute.Value.Equals ("Content-Type", StringComparison.OrdinalIgnoreCase))
isContentType = true;
htmlWriter.WriteAttribute (attribute);
}
}
} else if (ctx.TagId == HtmlTagId.Image && !ctx.IsEndTag && stack.Count > 0) {
ctx.WriteTag (htmlWriter, false);
// replace the src attribute with a "data:" URL
foreach (var attribute in ctx.Attributes) {
if (attribute.Id == HtmlAttributeId.Src) {
if (!TryGetImage (attribute.Value, out var image)) {
htmlWriter.WriteAttribute (attribute);
continue;
}
var dataUri = GetDataUri (image);
htmlWriter.WriteAttributeName (attribute.Name);
htmlWriter.WriteAttributeValue (dataUri);
} else {
htmlWriter.WriteAttribute (attribute);
}
}
} else if (ctx.TagId == HtmlTagId.Body && !ctx.IsEndTag) {
ctx.WriteTag (htmlWriter, false);
// add and/or replace oncontextmenu="return false;"
foreach (var attribute in ctx.Attributes) {
if (attribute.Name.Equals ("oncontextmenu", StringComparison.OrdinalIgnoreCase))
continue;
htmlWriter.WriteAttribute (attribute);
}
htmlWriter.WriteAttribute ("oncontextmenu", "return false;");
} else {
// pass the tag through to the output
ctx.WriteTag (htmlWriter, true);
}
}
protected override void VisitTextPart (TextPart entity)
{
TextConverter converter;
if (body != null) {
// since we've already found the body, treat this as an attachment
attachments.Add (entity);
return;
}
if (entity.IsHtml) {
converter = new HtmlToHtml {
HtmlTagCallback = HtmlTagCallback
};
} else if (entity.IsFlowed) {
var flowed = new FlowedToHtml ();
string delsp;
if (entity.ContentType.Parameters.TryGetValue ("delsp", out delsp))
flowed.DeleteSpace = delsp.Equals ("yes", StringComparison.OrdinalIgnoreCase);
converter = flowed;
} else {
converter = new TextToHtml ();
}
body = converter.Convert (entity.Text);
}
protected override void VisitTnefPart (TnefPart entity)
{
// extract any attachments in the MS-TNEF part
attachments.AddRange (entity.ExtractAttachments ());
}
protected override void VisitMessagePart (MessagePart entity)
{
// treat message/rfc822 parts as attachments
attachments.Add (entity);
}
protected override void VisitMimePart (MimePart entity)
{
// realistically, if we've gotten this far, then we can treat this as an attachment
// even if the IsAttachment property is false.
attachments.Add (entity);
}
}
#endregion
#region ReplyVisitor
public class ReplyVisitor : MimeVisitor
{
readonly Stack
htmlWriter.WriteEndTag (HtmlTagId.BlockQuote);
// pass the
htmlWriter.WriteStartTag (HtmlTagId.BlockQuote); htmlWriter.WriteAttribute (HtmlAttributeId.Style, "border-left: 1px #ccc solid; margin: 0 0 0 .8ex; padding-left: 1ex;"); ctx.InvokeCallbackForEndTag = true; } } else { // pass the tag through to the output ctx.WriteTag (htmlWriter, true); } } string QuoteText (string text) { using (var quoted = new StringWriter ()) { quoted.WriteLine (GetOnDateSenderWrote (message)); using (var reader = new StringReader (text)) { string line; while ((line = reader.ReadLine ()) != null) { quoted.Write ("> "); quoted.WriteLine (line); } } return quoted.ToString (); } } protected override void VisitTextPart (TextPart entity) { string text; if (entity.IsHtml) { var converter = new HtmlToHtml { HtmlTagCallback = HtmlTagCallback }; text = converter.Convert (entity.Text); } else if (entity.IsFlowed) { var converter = new FlowedToText (); text = converter.Convert (entity.Text); text = QuoteText (text); } else { // quote the original message text text = QuoteText (entity.Text); } var part = new TextPart (entity.ContentType.MediaSubtype.ToLowerInvariant ()) { Text = text }; Push (part); } protected override void VisitMessagePart (MessagePart entity) { // don't descend into message/rfc822 parts } } #endregion public class Program { #region RenderMessage void Render (MimeMessage message) { var tmpDir = Path.Combine (Path.GetTempPath (), message.MessageId); var visitor = new HtmlPreviewVisitor (tmpDir); Directory.CreateDirectory (tmpDir); message.Accept (visitor); DisplayHtml (visitor.HtmlBody); DisplayAttachments (visitor.Attachments); } #endregion #region ReplySimple public static MimeMessage Reply (MimeMessage message, MailboxAddress from, bool replyToAll) { var reply = new MimeMessage (); reply.From.Add (from); // reply to the sender of the message if (message.ReplyTo.Count > 0) { reply.To.AddRange (message.ReplyTo); } else if (message.From.Count > 0) { reply.To.AddRange (message.From); } else if (message.Sender != null) { reply.To.Add (message.Sender); } if (replyToAll) { // include all of the other original recipients (removing ourselves from the list) reply.To.AddRange (message.To.Mailboxes.Where (x => x.Address != from.Address)); reply.Cc.AddRange (message.Cc.Mailboxes.Where (x => x.Address != from.Address)); } // set the reply subject if (!message.Subject.StartsWith ("Re:", StringComparison.OrdinalIgnoreCase)) reply.Subject = "Re: " + message.Subject; else reply.Subject = message.Subject; // construct the In-Reply-To and References headers if (!string.IsNullOrEmpty (message.MessageId)) { reply.InReplyTo = message.MessageId; foreach (var id in message.References) reply.References.Add (id); reply.References.Add (message.MessageId); } // quote the original message text using (var quoted = new StringWriter ()) { var sender = message.Sender ?? message.From.Mailboxes.FirstOrDefault (); var name = sender != null ? (!string.IsNullOrEmpty (sender.Name) ? sender.Name : sender.Address) : "someone"; quoted.WriteLine ("On {0}, {1} wrote:", message.Date.ToString ("f"), name); using (var reader = new StringReader (message.TextBody)) { string line; while ((line = reader.ReadLine ()) != null) { quoted.Write ("> "); quoted.WriteLine (line); } } reply.Body = new TextPart ("plain") { Text = quoted.ToString () }; } return reply; } #endregion #region Reply public static MimeMessage Reply (MimeMessage message, MailboxAddress from, bool replyToAll) { var visitor = new ReplyVisitor (); var reply = new MimeMessage (); reply.From.Add (from); // reply to the sender of the message if (message.ReplyTo.Count > 0) { reply.To.AddRange (message.ReplyTo); } else if (message.From.Count > 0) { reply.To.AddRange (message.From); } else if (message.Sender != null) { reply.To.Add (message.Sender); } if (replyToAll) { // include all of the other original recipients (removing ourselves from the list) reply.To.AddRange (message.To.Mailboxes.Where (x => x.Address != from.Address)); reply.Cc.AddRange (message.Cc.Mailboxes.Where (x => x.Address != from.Address)); } // set the reply subject if (!message.Subject.StartsWith ("Re:", StringComparison.OrdinalIgnoreCase)) reply.Subject = "Re: " + message.Subject; else reply.Subject = message.Subject; // construct the In-Reply-To and References headers if (!string.IsNullOrEmpty (message.MessageId)) { reply.InReplyTo = message.MessageId; foreach (var id in message.References) reply.References.Add (id); reply.References.Add (message.MessageId); } visitor.Visit (message); reply.Body = visitor.Body ?? new TextPart ("plain") { Text = ReplyVisitor.GetOnDateSenderWrote (message) + Environment.NewLine }; return reply; } #endregion } } ================================================ FILE: Documentation/Examples/MultipartFormDataExamples.cs ================================================ using System; using System.Net; using MimeKit; namespace Examples { class MultipartFormDataExample { #region ParseMultipartFormDataSimple MimeEntity ParseMultipartFormData (HttpWebResponse response) { var contentType = ContentType.Parse (response.ContentType); return MimeEntity.Load (contentType, response.GetResponseStream ()); } #endregion #region ParseMultipartFormDataComplex MimeEntity ParseMultipartFormData (HttpWebResponse response) { // create a temporary file to store our large HTTP data stream var tmp = Path.GetTempFileName (); using (var stream = File.Open (tmp, FileMode.Open, FileAccess.ReadWrite)) { // create a header for the multipart/form-data MIME entity based on the Content-Type value of the HTTP // response var header = Encoding.UTF8.GetBytes (string.Format ("Content-Type: {0}\r\n\r\n", response.ContentType)); // write the header to the stream stream.Write (header, 0, header.Length); // copy the content of the HTTP response to our temporary stream response.GetResponseStream ().CopyTo (stream); // reset the stream back to the beginning stream.Position = 0; // parse the MIME entity with persistent = true, telling the parser not to load the content into memory return MimeEntity.Load (stream, persistent: true); } } #endregion } } ================================================ FILE: Documentation/Examples/OAuth2ExchangeExample.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; using MailKit; using MailKit.Net.Imap; using MailKit.Security; using Microsoft.Identity.Client; namespace OAuth2ExchangeExample { class Program { const string ExchangeAccount = "username@office365.com"; public static void Main (string[] args) { using (var client = new ImapClient ()) { client.Connect ("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect); if (client.AuthenticationMechanisms.Contains ("OAUTHBEARER") || client.AuthenticationMechanisms.Contains ("XOAUTH2")) AuthenticateAsync (client).GetAwaiter ().GetResult (); client.Disconnect (true); } } static async Task AuthenticateAsync (ImapClient client) { var options = new PublicClientApplicationOptions { ClientId = "Application (client) ID", TenantId = "Directory (tenant) ID", RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient" }; var publicClientApplication = PublicClientApplicationBuilder .CreateWithApplicationOptions (options) .Build (); var scopes = new string[] { "email", "offline_access", "https://outlook.office.com/IMAP.AccessAsUser.All", // Only needed for IMAP //"https://outlook.office.com/POP.AccessAsUser.All", // Only needed for POP //"https://outlook.office.com/SMTP.AccessAsUser.All", // Only needed for SMTP }; AuthenticationResult? result; try { // First, check the cache for an auth token. result = await publicClientApplication.AcquireTokenSilent (scopes, username).ExecuteAsync (); } catch (MsalUiRequiredException) { // If that fails, then try getting an auth token interactively. result = await publicClientApplication.AcquireTokenInteractive (scopes).WithLoginHint (username).ExecuteAsync (); } // Note: We use result.Account.Username here instead of ExchangeAccount because the user *may* have chosen a // different Microsoft Exchange account when presented with the browser window during the authentication process. SaslMechanism oauth2; if (client.AuthenticationMechanisms.Contains ("OAUTHBEARER")) oauth2 = new SaslMechanismOAuthBearer (result.Account.Username, result.AccessToken); else oauth2 = new SaslMechanismOAuth2 (result.Account.Username, result.AccessToken); await client.AuthenticateAsync (oauth2); } } } ================================================ FILE: Documentation/Examples/OAuth2GMailExample.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; using Google.Apis.Util; using Google.Apis.Util.Store; using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2.Flows; using MailKit; using MailKit.Net.Imap; using MailKit.Security; namespace OAuth2GMailExample { class Program { const string GMailAccount = "username@gmail.com"; public static void Main (string[] args) { using (var client = new ImapClient ()) { client.Connect ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect); if (client.AuthenticationMechanisms.Contains ("OAUTHBEARER") || client.AuthenticationMechanisms.Contains ("XOAUTH2")) AuthenticateAsync (client).GetAwaiter ().GetResult (); client.Disconnect (true); } } static async Task AuthenticateAsync (ImapClient client) { var clientSecrets = new ClientSecrets { ClientId = "XXX.apps.googleusercontent.com", ClientSecret = "XXX" }; var codeFlow = new GoogleAuthorizationCodeFlow (new GoogleAuthorizationCodeFlow.Initializer { DataStore = new FileDataStore ("CredentialCacheFolder", false), Scopes = new [] { "https://mail.google.com/" }, ClientSecrets = clientSecrets }); // Note: For a web app, you'll want to use AuthorizationCodeWebApp instead. var codeReceiver = new LocalServerCodeReceiver (); var authCode = new AuthorizationCodeInstalledApp (codeFlow, codeReceiver); var credential = await authCode.AuthorizeAsync (GMailAccount, CancellationToken.None); if (credential.Token.IsStale) await credential.RefreshTokenAsync (CancellationToken.None); // Note: We use credential.UserId here instead of GMailAccount because the user *may* have chosen a // different GMail account when presented with the browser window during the authentication process. SaslMechanism oauth2; if (client.AuthenticationMechanisms.Contains ("OAUTHBEARER")) oauth2 = new SaslMechanismOAuthBearer (credential.UserId, credential.Token.AccessToken); else oauth2 = new SaslMechanismOAuth2 (credential.UserId, credential.Token.AccessToken); await client.AuthenticateAsync (oauth2); } } } ================================================ FILE: Documentation/Examples/OpenPGPExamples.cs ================================================ using System; using System.IO; using System.Linq; using System.Text; using MimeKit; using MimeKit.Cryptography; namespace Examples { #region MyGnuPGContext public class MyGnuPGContext : GnuPGContext { public MyGnuPGContext () { } protected override string GetPasswordForKey (PgpSecretKey key) { // prompt the user (or a secure password cache) for the password for the specified secret key. return "password"; } } #endregion public class OpenPGPExamples { public void RegisterMyGnuPGeContext () { #region RegisterCustomContext // Note: by registering our custom context it becomes the default OpenPGP context // instantiated by MimeKit when methods such as Encrypt(), Decrypt(), Sign(), and // Verify() are used without an explicit context. CryptographyContext.Register (typeof (MyGnuPGContext)); #endregion } #region Encrypt public void Encrypt (MimeMessage message) { // encrypt our message body using our custom GnuPG cryptography context using (var ctx = new MyGnuPGContext ()) { // Note: this assumes that each of the recipients has a PGP key associated // with their email address in the user's public keyring. // // If this is not the case, you can use SecureMailboxAddresses instead of // normal MailboxAddresses which would allow you to specify the fingerprint // of their PGP keys. You could also choose to use one of the Encrypt() // overloads that take a list of PgpPublicKeys. message.Body = MultipartEncrypted.Encrypt (ctx, message.To.Mailboxes, message.Body); } } #endregion #region Decrypt public MimeEntity Decrypt (MimeMessage message) { if (message.Body is MultipartEncrypted) { // the top-level MIME part of the message is encrypted using PGP/MIME var encrypted = (MultipartEncrypted) entity; return encrypted.Decrypt (); } else { // the top-level MIME part is not encrypted return message.Body; } } #endregion #region Sign public void Sign (MimeMessage message) { // digitally sign our message body using our custom GnuPG cryptography context using (var ctx = new MyGnuPGContext ()) { // Note: this assumes that the Sender address has an S/MIME signing certificate // and private key with an X.509 Subject Email identifier that matches the // sender's email address. // // If this is not the case, you can use a SecureMailboxAddress instead of a // normal MailboxAddress which would allow you to specify the fingerprint // of the sender's private PGP key. You could also choose to use one of the // Create() overloads that take a PgpSecretKey, instead. var sender = message.From.Mailboxes.FirstOrDefault (); message.Body = MultipartSigned.Create (ctx, sender, DigestAlgorithm.Sha1, message.Body); } } #endregion #region SignWithKey public void Sign (MimeMessage message, PgpSecretKey key) { // digitally sign our message body using our custom GnuPG cryptography context using (var ctx = new MyGnuPGContext ()) { message.Body = MultipartSigned.Create (ctx, key, DigestAlgorithm.Sha1, message.Body); } } #endregion #region Verify public void Verify (MimeMessage message) { if (message.Body is MultipartSigned) { var signed = (MultipartSigned) message.Body; foreach (var signature in signed.Verify ()) { try { bool valid = signature.Verify (); // If valid is true, then it signifies that the signed content // has not been modified since this particular signer signed the // content. // // However, if it is false, then it indicates that the signed // content has been modified. } catch (DigitalSignatureVerifyException) { // There was an error verifying the signature. } } } } #endregion #region DecryptInlinePGP static Stream Decrypt (MimeMessage message) { var text = message.TextBody; using (var encrypted = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { using (var ctx = new MyGnuPGContext ()) { var decrypted = new MemoryStream (); ctx.DecryptTo (encrypted, decrypted); decrypted.Position = 0; return decrypted; } } } #endregion } } ================================================ FILE: Documentation/Examples/OpeningContent.cs ================================================ using (var stream = part.Content.Open ()) { // At this point, you can now read from the stream as if it were the original, // raw content. Assuming you have an image UI control that could load from a // stream, you could do something like this: imageControl.Load (stream); } ================================================ FILE: Documentation/Examples/ParameterExamples.cs ================================================ using System; using MimeKit; namespace MimeKit.Examples { public static class ParameterExamples { public void OverrideAllParameterEncodings (MimePart part) { #region OverrideAllParameterEncodings // Some versions of Outlook expect the rfc2047 style of encoding of parameter values. foreach (var parameter in part.ContentDisposition.Parameters) parameter.EncodingMethod = ParameterEncodingMethod.Rfc2047; #endregion OverrideAllParameterEncodings } public void OverrideFileNameParameterEncodings (MimePart part) { #region OverrideFileNameParameterEncoding // Some versions of Outlook expect the rfc2047 style of encoding for the filename parameter value. if (part.ContentDisposition.Parameters.TryGetValue ("filename", out var parameter)) parameter.EncodingMethod = ParameterEncodingMethod.Rfc2047; #endregion OverrideFileNameParameterEncoding } } } ================================================ FILE: Documentation/Examples/Pop3Examples.cs ================================================ // // Pop3Examples.cs // // Author: Jeffrey Stedfasttag through to the output ctx.WriteTag (htmlWriter, true); // prepend the HTML reply with "On {DATE}, {SENDER} wrote:" htmlWriter.WriteStartTag (HtmlTagId.P); htmlWriter.WriteText (GetOnDateSenderWrote (original)); htmlWriter.WriteEndTag (HtmlTagId.P); // Wrap the original content in a// // Copyright (c) 2013-2023 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.IO; using System.Collections.Generic; using MimeKit; using MailKit; using MailKit.Security; using MailKit.Net.Pop3; namespace MailKit.Examples { public static class Pop3Examples { #region ProtocolLogger public static void DownloadMessages () { using (var client = new Pop3Client (new ProtocolLogger ("pop3.log"))) { client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); for (int i = 0; i < client.Count; i++) { var message = client.GetMessage (i); // write the message to a file message.WriteTo (string.Format ("{0}.msg", i)); // mark the message for deletion client.DeleteMessage (i); } client.Disconnect (true); } } #endregion #region Capabilities public static void PrintCapabilities () { using (var client = new Pop3Client ()) { client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect); if (client.Capabilities.HasFlag (Pop3Capabilities.SASL)) { var mechanisms = string.Join (", ", client.AuthenticationMechanisms); Console.WriteLine ("The POP3 server supports the following SASL mechanisms: {0}", mechanisms); } client.Authenticate ("username", "password"); if (client.Capabilities.HasFlag (Pop3Capabilities.Apop)) Console.WriteLine ("The server supports APOP authentication."); if (client.Capabilities.HasFlag (Pop3Capabilities.Expire)) { if (client.ExpirePolicy > 0) Console.WriteLine ("The POP3 server automatically expires messages after {0} days", client.ExpirePolicy); else Console.WriteLine ("The POP3 server will never expire messages."); } if (client.Capabilities.HasFlag (Pop3Capabilities.LoginDelay)) Console.WriteLine ("The minimum number of seconds between login attempts is {0}.", client.LoginDelay); if (client.Capabilities.HasFlag (Pop3Capabilities.Pipelining)) Console.WriteLine ("The POP3 server can pipeline commands, so using client.GetMessages() will be faster."); if (client.Capabilities.HasFlag (Pop3Capabilities.Top)) Console.WriteLine ("The POP3 server supports the TOP command, so it's possible to download message headers."); if (client.Capabilities.HasFlag (Pop3Capabilities.UIDL)) Console.WriteLine ("The POP3 server supports the UIDL command which means we can track messages by UID."); client.Disconnect (true); } } #endregion #region DownloadMessages public static void DownloadMessages () { using (var client = new Pop3Client ()) { client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); for (int i = 0; i < client.Count; i++) { var message = client.GetMessage (i); // write the message to a file message.WriteTo (string.Format ("{0}.msg", i)); // mark the message for deletion client.DeleteMessage (i); } client.Disconnect (true); } } #endregion #region BatchDownloadMessages public static void DownloadMessages () { using (var client = new Pop3Client ()) { client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); var messages = client.DownloadMessages (0, count); foreach (var message in messages) { // write the message to a file message.WriteTo (string.Format ("{0}.msg", i)); } client.DeleteMessages (0, count); client.Disconnect (true); } } #endregion #region DownloadNewMessages public static void DownloadNewMessages (HashSet previouslyDownloadedUids) { using (var client = new Pop3Client ()) { client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); if (!client.Capabilities.HasFlag (Pop3Capabilities.UIDL)) throw new Exception ("The POP3 server does not support UIDs!"); var uids = client.GetMessageUids (); for (int i = 0; i < client.Count; i++) { // check that we haven't already downloaded this message // in a previous session if (previouslyDownloadedUids.Contains (uids[i])) continue; var message = client.GetMessage (i); // write the message to a file message.WriteTo (string.Format ("{0}.msg", uids[i])); // add the message uid to our list of downloaded uids previouslyDownloadedUids.Add (uids[i]); } client.Disconnect (true); } } #endregion #region ExceptionHandling public static void DownloadNewMessages (HashSet previouslyDownloadedUids) { using (var client = new Pop3Client ()) { IList uids = null; try { client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect); } catch (Pop3CommandException ex) { Console.WriteLine ("Error trying to connect: {0}", ex.Message); Console.WriteLine ("\tStatusText: {0}", ex.StatusText); return; } catch (Pop3ProtocolException ex) { Console.WriteLine ("Protocol error while trying to connect: {0}", ex.Message); return; } try { client.Authenticate ("username", "password"); } catch (AuthenticationException ex) { Console.WriteLine ("Invalid user name or password."); return; } catch (Pop3CommandException ex) { Console.WriteLine ("Error trying to authenticate: {0}", ex.Message); Console.WriteLine ("\tStatusText: {0}", ex.StatusText); return; } catch (Pop3ProtocolException ex) { Console.WriteLine ("Protocol error while trying to authenticate: {0}", ex.Message); return; } // for the sake of this example, let's assume GMail supports the UIDL extension if (client.Capabilities.HasFlag (Pop3Capabilities.UIDL)) { try { uids = client.GetMessageUids (); } catch (Pop3CommandException ex) { Console.WriteLine ("Error trying to get the list of uids: {0}", ex.Message); Console.WriteLine ("\tStatusText: {0}", ex.StatusText); // we'll continue on leaving uids set to null... } catch (Pop3ProtocolException ex) { Console.WriteLine ("Protocol error while trying to authenticate: {0}", ex.Message); // Pop3ProtocolExceptions often cause the connection to drop if (!client.IsConnected) return; } } for (int i = 0; i < client.Count; i++) { if (uids != null && previouslyDownloadedUids.Contains (uids[i])) { // we must have downloaded this message in a previous session continue; } try { // download the message at the specified index var message = client.GetMessage (i); // write the message to a file if (uids != null) { message.WriteTo (string.Format ("{0}.msg", uids[i])); // keep track of our downloaded message uids so we can skip downloading them next time previouslyDownloadedUids.Add (uids[i]); } else { message.WriteTo (string.Format ("{0}.msg", i)); } } catch (Pop3CommandException ex) { Console.WriteLine ("Error downloading message {0}: {1}", i, ex.Message); Console.WriteLine ("\tStatusText: {0}", ex.StatusText); continue; } catch (Pop3ProtocolException ex) { Console.WriteLine ("Protocol error while sending message {0}: {1}", i, ex.Message); // most likely the connection has been dropped if (!client.IsConnected) break; } } if (client.IsConnected) { // if we do not disconnect cleanly, then the messages won't actually get deleted client.Disconnect (true); } } } #endregion #region SslConnectionInformation public static void PrintSslConnectionInfo (string host, int port) { using (var client = new SmtpClient ()) { client.Connect (host, port, SecureSocketOptions.Auto); Console.WriteLine ($"Negotiated the following SSL options with {host}:"); Console.WriteLine ($" Protocol Version: {client.SslProtocol}"); Console.WriteLine ($" Cipher Algorithm: {client.SslCipherAlgorithm}"); Console.WriteLine ($" Cipher Strength: {client.SslCipherStrength}"); Console.WriteLine ($" Hash Algorithm: {client.SslHashAlgorithm}"); Console.WriteLine ($" Hash Strength: {client.SslHashStrength}"); Console.WriteLine ($" Key-Exchange Algorithm: {client.SslKeyExchangeAlgorithm}"); Console.WriteLine ($" Key-Exchange Strength: {client.SslKeyExchangeStrength}"); // Example Log: // // Negotiated the following SSL options with pop.gmail.com: // Protocol Version: Tls12 // Cipher Algorithm: Aes128 // Cipher Strength: 128 // Hash Algorithm: Sha256 // Hash Strength: 0 // Key-Exchange Algorithm: 44550 // Key-Exchange Strength: 255 client.Disconnect (true); } } #endregion } } ================================================ FILE: Documentation/Examples/ProxyExamples.cs ================================================ // // ProxyExamples.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2023 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections.Generic; using MimeKit; using MailKit; using MailKit.Security; using MailKit.Net.Smtp; using MailKit.Net.Pop3; using MailKit.Net.Imap; using MailKit.Net.Proxy; namespace MailKit.Examples { public static class ProxyExamples { #region ProxyClient public static void SendMessageViaProxy (MimeMessage message) { using (var client = new SmtpClient ()) { client.ProxyClient = new Socks5Proxy ("socks5.proxy.com", 1080, new NetworkCredentials ("proxyUserName", "proxyPassword")); client.Connect ("smtp.gmail.com", 465, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); client.Send (message); client.Disconnect (true); } } #endregion } } ================================================ FILE: Documentation/Examples/RecursivelyTraverse.cs ================================================ static void HandleMimeEntity (MimeEntity entity) { var multipart = entity as Multipart; if (multipart != null) { for (int i = 0; i < multipart.Count; i++) HandleMimeEntity (multipart[i]); return; } var rfc822 = entity as MessagePart; if (rfc822 != null) { var message = rfc822.Message; HandleMimeEntity (message.Body); return; } var part = (MimePart) entity; // do something with the MimePart, such as save content to disk } ================================================ FILE: Documentation/Examples/SMimeExamples.cs ================================================ using System; using MimeKit; using MimeKit.Cryptography; namespace Examples { #region MySecureMimeContext public class MySecureMimeContext : DefaultSecureMimeContext { public MySecureMimeContext () : base (OpenDatabase ("C:\\wherever\\certdb.sqlite")) { } static IX509CertificateDatabase OpenDatabase (string fileName) { var builder = new SQLiteConnectionStringBuilder (); builder.DateTimeFormat = SQLiteDateFormats.Ticks; builder.DataSource = fileName; if (!File.Exists (fileName)) SQLiteConnection.CreateFile (fileName); var sqlite = new SQLiteConnection (builder.ConnectionString); sqlite.Open (); return new SqliteCertificateDatabase (sqlite, "password"); } } #endregion public class SMimeExamples { public void RegisterMySecureMimeContext () { #region RegisterCustomContext // Note: by registering our custom context it becomes the default S/MIME context // instantiated by MimeKit when methods such as Encrypt(), Decrypt(), Sign(), and // Verify() are used without an explicit context. CryptographyContext.Register (typeof (MySecureMimeContext)); #endregion } #region Encrypt public void Encrypt (MimeMessage message) { // encrypt our message body using our custom S/MIME cryptography context using (var ctx = new MySecureMimeContext ()) { // Note: this assumes that each of the recipients has an S/MIME certificate // with an X.509 Subject Email identifier that matches their email address. // // If this is not the case, you can use SecureMailboxAddresses instead of // normal MailboxAddresses which would allow you to specify the fingerprint // of their certificates. You could also choose to use one of the Encrypt() // overloads that take a list of CmsRecipients, instead. message.Body = ApplicationPkcs7Mime.Encrypt (ctx, message.To.Mailboxes, message.Body); } } #endregion #region Decrypt public MimeEntity Decrypt (MimeMessage message) { var pkcs7 = message.Body as ApplicationPkcs7Mime; if (pkcs7 != null && pkcs7.SecureMimeType == SecureMimeType.EnvelopedData) { // the top-level MIME part of the message is encrypted using S/MIME return pkcs7.Decrypt (); } else { // the top-level MIME part is not encrypted return message.Body; } } #endregion #region MultipartSign public void MultipartSign (MimeMessage message) { // digitally sign our message body using our custom S/MIME cryptography context using (var ctx = new MySecureMimeContext ()) { // Note: this assumes that the Sender address has an S/MIME signing certificate // and private key with an X.509 Subject Email identifier that matches the // sender's email address. var sender = message.From.Mailboxes.FirstOrDefault (); message.Body = MultipartSigned.Create (ctx, sender, DigestAlgorithm.Sha1, message.Body); } } #endregion #region MultipartSignWithKey public void MultipartSign (MimeMessage message, X509Certificate2 certificate) { // digitally sign our message body using our custom S/MIME cryptography context using (var ctx = new MySecureMimeContext ()) { var signer = new CmsSigner (certificate) { DigestAlgorithm = DigestAlgorithm.Sha1 }; message.Body = MultipartSigned.Create (ctx, signer, message.Body); } } #endregion #region Pkcs7Sign public void Pkcs7Sign (MimeMessage message) { // digitally sign our message body using our custom S/MIME cryptography context using (var ctx = new MySecureMimeContext ()) { // Note: this assumes that the Sender address has an S/MIME signing certificate // and private key with an X.509 Subject Email identifier that matches the // sender's email address. var sender = message.From.Mailboxes.FirstOrDefault (); message.Body = ApplicationPkcs7Mime.Sign (ctx, sender, DigestAlgorithm.Sha1, message.Body); } } #endregion #region VerifyMultipartSigned public void VerifyMultipartSigned (MimeMessage message) { if (message.Body is MultipartSigned) { var signed = (MultipartSigned) message.Body; foreach (var signature in signed.Verify ()) { try { bool valid = signature.Verify (); // If valid is true, then it signifies that the signed content // has not been modified since this particular signer signed the // content. // // However, if it is false, then it indicates that the signed // content has been modified. } catch (DigitalSignatureVerifyException) { // There was an error verifying the signature. } } } } #endregion #region VerifyPkcs7 public void VerifyPkcs7 (MimeMessage message) { var pkcs7 = message.Body as ApplicationPkcs7Mime; if (pkcs7 != null && pkcs7.SecureMimeType == SecureMimeType.SignedData) { // extract the original content and get a list of signatures MimeEntity original; // Note: if you are rendering the message, you'll want to render the // original mime part rather than the application/pkcs7-mime part. foreach (var signature in pkcs7.Verify (out original)) { try { bool valid = signature.Verify (); // If valid is true, then it signifies that the signed content // has not been modified since this particular signer signed the // content. // // However, if it is false, then it indicates that the signed // content has been modified. } catch (DigitalSignatureVerifyException) { // There was an error verifying the signature. } } } } #endregion } } ================================================ FILE: Documentation/Examples/SmtpExamples.cs ================================================ // // SmtpExamples.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2023 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections.Generic; using MimeKit; using MailKit; using MailKit.Security; using MailKit.Net.Smtp; namespace MailKit.Examples { public static class SmtpExamples { #region SaveToPickupDirectory public static void SaveToPickupDirectory (MimeMessage message, string pickupDirectory) { do { // Generate a random file name to save the message to. var path = Path.Combine (pickupDirectory, Guid.NewGuid ().ToString () + ".eml"); Stream stream; try { // Attempt to create the new file. stream = File.Open (path, FileMode.CreateNew); } catch (IOException) { // If the file already exists, try again with a new Guid. if (File.Exists (path)) continue; // Otherwise, fail immediately since it probably means that there is // no graceful way to recover from this error. throw; } try { using (stream) { // IIS pickup directories expect the message to be "byte-stuffed" // which means that lines beginning with "." need to be escaped // by adding an extra "." to the beginning of the line. // // Use an SmtpDataFilter to "byte-stuff" the message as it is written // to the file stream. This is the same process that an SmtpClient // would use when sending the message in a `DATA` command. using (var filtered = new FilteredStream (stream)) { filtered.Add (new SmtpDataFilter ()); // Make sure to write the message in DOS ( ) format. var options = FormatOptions.Default.Clone (); options.NewLineFormat = NewLineFormat.Dos; message.WriteTo (options, filtered); filtered.Flush (); return; } } } catch { // An exception here probably means that the disk is full. // // Delete the file that was created above so that incomplete files are not // left behind for IIS to send accidentally. File.Delete (path); throw; } } while (true); } #endregion #region LoadFromPickupDirectory public static MimeMessage LoadFromPickupDirectory (string fileName) { using (var stream = File.OpenRead (fileName)) { // IIS pickup directories store messages that have been "byte-stuffed" // which means that lines beginning with "." have been escaped by // adding an extra "." to the beginning of the line. // // Use an SmtpDataFilter to decode the message as it is loaded from // the file stream. This is the reverse process that an SmtpClient // would use when sending the message in a `DATA` command. using (var filtered = new FilteredStream (stream)) { filtered.Add (new SmtpDataFilter (decode: true)); return MimeMessage.Load (filtered); } } } #endregion #region ProtocolLogger public static void SendMessage (MimeMessage message) { using (var client = new SmtpClient (new ProtocolLogger ("smtp.log"))) { client.Connect ("smtp.gmail.com", 465, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); client.Send (message); client.Disconnect (true); } // Example log: // // Connected to smtps://smtp.gmail.com:465/ // S: 220 smtp.gmail.com ESMTP w81sm22057166qkg.43 - gsmtp // C: EHLO [192.168.1.220] // S: 250-smtp.gmail.com at your service, [192.168.1.220] // S: 250-SIZE 35882577 // S: 250-8BITMIME // S: 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH // S: 250-ENHANCEDSTATUSCODES // S: 250-PIPELINING // S: 250-CHUNKING // S: 250 SMTPUTF8 // C: AUTH PLAIN AHVzZXJuYW1lAHBhc3N3b3Jk // S: 235 2.7.0 Accepted // C: MAIL FROM: // C: RCPT TO: // S: 250 2.1.0 OK w81sm22057166qkg.43 - gsmtp // S: 250 2.1.5 OK w81sm22057166qkg.43 - gsmtp // C: DATA // S: 354 Go ahead w81sm22057166qkg.43 - gsmtp // C: From: "LastName, FirstName" // C: Date: Thu, 27 Dec 2018 10:55:18 -0500 // C: Subject: This is a test message // C: Message-Id: // C: To: "LastName, FirstName" // C: MIME-Version: 1.0 // C: Content-Type: multipart/alternative; boundary="=-CToJI+AD2gS6z+fFlzDvhg==" // C: // C: --=-CToJI+AD2gS6z+fFlzDvhg== // C: Content-Type: text/plain; charset=utf-8 // C: Content-Transfer-Encoding: quoted-printable // C: // C: This is the text/plain message body. // C: --=-CToJI+AD2gS6z+fFlzDvhg== // C: Content-Type: text/html; charset=utf-8 // C: Content-Transfer-Encoding: quoted-printable // C: // C: This is the text/html message body. // C: --=-CToJI+AD2gS6z+fFlzDvhg==-- // C: // C: . // S: 250 2.0.0 OK 1545926120 w81sm22057166qkg.43 - gsmtp // C: QUIT // S: 221 2.0.0 closing connection w81sm22057166qkg.43 - gsmtp } #endregion #region Capabilities public static void PrintCapabilities () { using (var client = new SmtpClient ()) { client.Connect ("smtp.gmail.com", 465, SecureSocketOptions.SslOnConnect); if (client.Capabilities.HasFlag (SmtpCapabilities.Authentication)) { var mechanisms = string.Join (", ", client.AuthenticationMechanisms); Console.WriteLine ("The SMTP server supports the following SASL mechanisms: {0}", mechanisms); client.Authenticate ("username", "password"); } if (client.Capabilities.HasFlag (SmtpCapabilities.Size)) Console.WriteLine ("The SMTP server has a size restriction on messages: {0}.", client.MaxSize); if (client.Capabilities.HasFlag (SmtpCapabilities.Dsn)) Console.WriteLine ("The SMTP server supports delivery-status notifications."); if (client.Capabilities.HasFlag (SmtpCapabilities.EightBitMime)) Console.WriteLine ("The SMTP server supports Content-Transfer-Encoding: 8bit"); if (client.Capabilities.HasFlag (SmtpCapabilities.BinaryMime)) Console.WriteLine ("The SMTP server supports Content-Transfer-Encoding: binary"); if (client.Capabilities.HasFlag (SmtpCapabilities.UTF8)) Console.WriteLine ("The SMTP server supports UTF-8 in message headers."); client.Disconnect (true); } } #endregion #region ExceptionHandling public static void SendMessage (MimeMessage message) { using (var client = new SmtpClient ()) { try { client.Connect ("smtp.gmail.com", 465, SecureSocketOptions.SslOnConnect); } catch (SmtpCommandException ex) { Console.WriteLine ("Error trying to connect: {0}", ex.Message); Console.WriteLine ("\tStatusCode: {0}", ex.StatusCode); return; } catch (SmtpProtocolException ex) { Console.WriteLine ("Protocol error while trying to connect: {0}", ex.Message); return; } // Note: Not all SMTP servers support authentication, but GMail does. if (client.Capabilities.HasFlag (SmtpCapabilities.Authentication)) { try { client.Authenticate ("username", "password"); } catch (AuthenticationException ex) { Console.WriteLine ("Invalid user name or password."); return; } catch (SmtpCommandException ex) { Console.WriteLine ("Error trying to authenticate: {0}", ex.Message); Console.WriteLine ("\tStatusCode: {0}", ex.StatusCode); return; } catch (SmtpProtocolException ex) { Console.WriteLine ("Protocol error while trying to authenticate: {0}", ex.Message); return; } } try { client.Send (message); } catch (SmtpCommandException ex) { Console.WriteLine ("Error sending message: {0}", ex.Message); Console.WriteLine ("\tStatusCode: {0}", ex.StatusCode); switch (ex.ErrorCode) { case SmtpErrorCode.RecipientNotAccepted: Console.WriteLine ("\tRecipient not accepted: {0}", ex.Mailbox); break; case SmtpErrorCode.SenderNotAccepted: Console.WriteLine ("\tSender not accepted: {0}", ex.Mailbox); break; case SmtpErrorCode.MessageNotAccepted: Console.WriteLine ("\tMessage not accepted."); break; } } catch (SmtpProtocolException ex) { Console.WriteLine ("Protocol error while sending message: {0}", ex.Message); } client.Disconnect (true); } } #endregion #region SendMessage public static void SendMessage (MimeMessage message) { using (var client = new SmtpClient ()) { client.Connect ("smtp.gmail.com", 465, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); client.Send (message); client.Disconnect (true); } } #endregion #region SendMessageUri public static void SendMessage (MimeMessage message) { using (var client = new SmtpClient ()) { // Note: since GMail requires SSL at connection time, use the "smtps" // protocol instead of "smtp". var uri = new Uri ("smtps://smtp.gmail.com:465"); client.Connect (uri); client.Authenticate ("username", "password"); client.Send (message); client.Disconnect (true); } } #endregion #region SendMessageWithOptions public static void SendMessageWithOptions (MimeMessage message) { using (var client = new SmtpClient ()) { client.Connect ("smtp.gmail.com", 465, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); var options = FormatOptions.Default.Clone (); if (client.Capabilities.HasFlag (SmtpCapabilities.UTF8)) options.International = true; client.Send (options, message); client.Disconnect (true); } } #endregion #region SendMessages public static void SendMessages (IListmessages) { using (var client = new SmtpClient ()) { client.Connect ("smtp.gmail.com", 465, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); foreach (var message in messages) { client.Send (message); } client.Disconnect (true); } } #endregion #region VerifyAddress public static void VerifyAddress () { using (var client = new SmtpClient ()) { client.Connect ("smtp.mail-server.com", 465, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); try { var verified = client.Verify ("smith"); Console.WriteLine ($"'smith' was resolved the the following mailbox: {verified}"); } catch (SmtpCommandException ex) { Console.WriteLine ($"'smith' is not a valid address: {ex.Message}"); } client.Disconnect (true); } } #endregion #region ExpandAlias public static void ExpandAlias (string alias) { using (var client = new SmtpClient ()) { client.Connect ("smtp.mail-server.com", 465, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); var expanded = client.Expand (alias); Console.WriteLine ($"Expanding the alias '{alias}' results in the following list of addresses:"); foreach (var mailbox in expanded.Mailboxes) Console.WriteLine ($"* {mailbox}"); client.Disconnect (true); } } #endregion #region DeliveryStatusNotification public class DSNSmtpClient : SmtpClient { public DSNSmtpClient () { } /// /// Get the envelope identifier to be used with delivery status notifications. /// ////// ///The envelope identifier, if non-empty, is useful in determining which message /// a delivery status notification was issued for. ///The envelope identifier should be unique and may be up to 100 characters in /// length, but must consist only of printable ASCII characters and no white space. ///For more information, see rfc3461, section 4.4. ///The envelope identifier. /// The message. protected override string GetEnvelopeId (MimeMessage message) { // Since you will want to be able to map whatever identifier you return here to the // message, the obvious identifier to use is probably the Message-Id value. return message.MessageId; } ////// Get the types of delivery status notification desired for the specified recipient mailbox. /// ////// Gets the types of delivery status notification desired for the specified recipient mailbox. /// ///The desired delivery status notification type. /// The message being sent. /// The mailbox. protected override DeliveryStatusNotification? GetDeliveryStatusNotifications (MimeMessage message, MailboxAddress mailbox) { // In this example, we only want to be notified of failures to deliver to a mailbox. // If you also want to be notified of delays or successful deliveries, simply bitwise-or // whatever combination of flags you want to be notified about. return DeliveryStatusNotification.Failure; } } #endregion #region SslConnectionInformation public static void PrintSslConnectionInfo (string host, int port) { using (var client = new SmtpClient ()) { client.Connect (host, port, SecureSocketOptions.Auto); Console.WriteLine ($"Negotiated the following SSL options with {host}:"); Console.WriteLine ($" Protocol Version: {client.SslProtocol}"); Console.WriteLine ($" Cipher Algorithm: {client.SslCipherAlgorithm}"); Console.WriteLine ($" Cipher Strength: {client.SslCipherStrength}"); Console.WriteLine ($" Hash Algorithm: {client.SslHashAlgorithm}"); Console.WriteLine ($" Hash Strength: {client.SslHashStrength}"); Console.WriteLine ($" Key-Exchange Algorithm: {client.SslKeyExchangeAlgorithm}"); Console.WriteLine ($" Key-Exchange Strength: {client.SslKeyExchangeStrength}"); // Example Log: // // Negotiated the following SSL options with smtp.gmail.com: // Protocol Version: Tls12 // Cipher Algorithm: Aes128 // Cipher Strength: 128 // Hash Algorithm: Sha256 // Hash Strength: 0 // Key-Exchange Algorithm: 44550 // Key-Exchange Strength: 255 client.Disconnect (true); } } #endregion } } ================================================ FILE: Documentation/Examples/SslCertificateValidation.cs ================================================ using System; using System.Net.Security; using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; using MimeKit; using MailKit; using MailKit.Security; using MailKit.Net.Smtp; namespace MailKit.Examples { public static class SslCertificateValidationExample { public static void SendMessage (MimeMessage message) { using (var client = new SmtpClient ()) { // Set our custom SSL certificate validation callback. client.ServerCertificateValidationCallback = MySslCertificateValidationCallback; // Connect to smtp.gmail.com on the SSL-wrapped port. client.Connect ("smtp.gmail.com", 465, SecureSocketOptions.SslOnConnect); // Authenticate with our username and password. client.Authenticate ("username@gmail.com", "password"); // Send our message. client.Send (message); // Disconnect cleanly from the server. client.Disconnect (true); } } static bool MySslCertificateValidationCallback (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { // If there are no errors, then everything went smoothly. if (sslPolicyErrors == SslPolicyErrors.None) return true; // Note: MailKit will always pass the host name string as the `sender` argument. var host = (string) sender; if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != 0) { // This means that the remote certificate is unavailable. Notify the user and return false. Console.WriteLine ("The SSL certificate was not available for {0}", host); return false; } if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) != 0) { // This means that the server's SSL certificate did not match the host name that we are trying to connect to. var certificate2 = certificate as X509Certificate2; var cn = certificate2 != null ? certificate2.GetNameInfo (X509NameType.SimpleName, false) : certificate.Subject; Console.WriteLine ("The Common Name for the SSL certificate did not match {0}. Instead, it was {1}.", host, cn); return false; } // The only other errors left are chain errors. Console.WriteLine ("The SSL certificate for the server could not be validated for the following reasons:"); // The first element's certificate will be the server's SSL certificate (and will match the `certificate` argument) // while the last element in the chain will typically either be the Root Certificate Authority's certificate -or- it // will be a non-authoritative self-signed certificate that the server admin created. foreach (var element in chain.ChainElements) { // Each element in the chain will have its own status list. If the status list is empty, it means that the // certificate itself did not contain any errors. if (element.ChainElementStatus.Length == 0) continue; Console.WriteLine ("\u2022 {0}", element.Certificate.Subject); foreach (var error in element.ChainElementStatus) { // `error.StatusInformation` contains a human-readable error string while `error.Status` is the corresponding enum value. Console.WriteLine ("\t\u2022 {0}", error.StatusInformation); } } return false; } } } ================================================ FILE: Documentation/Examples/VerifySignature.cs ================================================ if (entity is MultipartSigned) { var signed = (MultipartSigned) entity; foreach (var signature in signed.Verify ()) { try { bool valid = signature.Verify (); // If valid is true, then it signifies that the signed content has not been // modified since this particular signer signed the content. // // However, if it is false, then it indicates that the signed content has // been modified. } catch (DigitalSignatureVerifyException) { // There was an error verifying the signature. } } } ================================================ FILE: ExchangeOAuth2.md ================================================ # Using OAuth2 With Exchange (IMAP, POP3 or SMTP) ## Quick Index * [Registering Your Application with Microsoft](#registering-your-application-with-microsoft) * [Configuring the Correct API Permissions for Your Application](#configuring-the-correct-api-permissions-for-your-application) * Desktop and Mobile Applications * [Authenticating a Desktop or Mobile Application with OAuth2](#authenticating-a-desktop-or-mobile-application-with-oauth2) * Web Applications * [Authenticating a Web Application with OAuth2](#authenticating-a-web-application-with-oauth2) * Web Services * [Registering Service Principals for Your Web Service](#registering-service-principals-for-your-web-service) * [Granting Permissions for Your Web Service](#granting-permissions-for-your-web-service) * [Authenticating a Web Service with OAuth2](#authenticating-a-web-service-with-oauth2) * [Additional Resources](#additional-resources) ## Registering Your Application with Microsoft Whether you are writing a Desktop, Mobile or Web Service application, the first thing you'll need to do is register your application with Microsoft's Identity Platform. To do this, go to Microsoft's [Quickstart guide](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) and follow the instructions. ## Configuring the Correct API Permissions for Your Application There are several different API permissions that you may want to configure depending on which protocols your application intends to use. Follow the instructions for [adding the POP, IMAP, and/or SMTP permissions to your Entra AD application](https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-smtp-imap-and-pop-connections). ## Desktop and Mobile Applications ### Authenticating a Desktop or Mobile Application with OAuth2 Now that you have the **Client ID** and **Tenant ID** strings, you'll need to plug those values into your application. The following sample code uses the [Microsoft.Identity.Client](https://www.nuget.org/packages/Microsoft.Identity.Client/) nuget package for obtaining the access token which will be needed by MailKit to pass on to the Exchange server. ```csharp static async TaskGetPublicClientOAuth2CredentialsAsync (string protocol, string emailAddress, CancellationToken cancellationToken = default) { var options = new PublicClientApplicationOptions { ClientId = "Application (client) ID", TenantId = "Directory (tenant) ID", // Use "https://login.microsoftonline.com/common/oauth2/nativeclient" for apps using // embedded browsers or "http://localhost" for apps that use system browsers. RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient" }; var publicClientApplication = PublicClientApplicationBuilder .CreateWithApplicationOptions (options) .Build (); string[] scopes; if (protocol.Equals ("IMAP", StringComparison.OrdinalIgnoreCase)) { scopes = new string[] { "email", "offline_access", "https://outlook.office.com/IMAP.AccessAsUser.All" }; } else if (protocol.Equals ("POP", StringComparison.OrdinalIgnoreCase)) { scopes = new string[] { "email", "offline_access", "https://outlook.office.com/POP.AccessAsUser.All" }; } else { scopes = new string[] { "email", "offline_access", "https://outlook.office.com/SMTP.Send" }; } try { // First, check the cache for an auth token. return await publicClientApplication.AcquireTokenSilent (scopes, emailAddress).ExecuteAsync (cancellationToken); } catch (MsalUiRequiredException) { // If that fails, then try getting an auth token interactively. return await publicClientApplication.AcquireTokenInteractive (scopes).WithLoginHint (emailAddress).ExecuteAsync (cancellationToken); } } ``` #### IMAP (using PublicClientApplication) ```csharp var result = await GetPublicClientOAuth2CredentialsAsync ("IMAP", "username@outlook.com"); // Note: We always use result.Account.Username instead of `Username` because the user may have selected an alternative account. var oauth2 = new SaslMechanismOAuth2 (result.Account.Username, result.AccessToken); using (var client = new ImapClient ()) { await client.ConnectAsync ("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect); await client.AuthenticateAsync (oauth2); await client.DisconnectAsync (true); } ``` #### SMTP (using PublicClientApplication) ```csharp var result = await GetPublicClientOAuth2CredentialsAsync ("SMTP", "username@outlook.com"); // Note: We always use result.Account.Username instead of `Username` because the user may have selected an alternative account. var oauth2 = new SaslMechanismOAuth2 (result.Account.Username, result.AccessToken); using (var client = new SmtpClient ()) { await client.ConnectAsync ("smtp.office365.com", 587, SecureSocketOptions.StartTls); await client.AuthenticateAsync (oauth2); await client.DisconnectAsync (true); } ``` Note: Once you've acquired an auth token using the interactive method above, you can avoid prompting the user if you cache the `result.Account` information and then silently reacquire auth tokens in the future using the following code: ```csharp var result = await publicClientApplication.AcquireTokenSilent(scopes, account).ExecuteAsync(cancellationToken); ``` Note: for information on caching tokens, see Microsoft's documentation about how to implement a [cross-platform token cache](https://github.com/AzureAD/microsoft-authentication-extensions-for-dotnet/wiki/Cross-platform-Token-Cache). ## Web Applications ### Authenticating a Web Application with OAuth2 Use this if you want to send/receive mail on behalf of a user. ```csharp // Common Code using Microsoft.Graph; using Microsoft.Identity.Client; using Microsoft.Kiota.Abstractions.Authentication; public static class OAuthMicrosoft { public static readonly string[] RegistrationScopes = new string[] { "offline_access", "User.Read", "Mail.Send", "https://outlook.office.com/SMTP.Send", "https://outlook.office.com/IMAP.AccessAsUser.All", }; public static readonly string[] SmtpScopes = new string[] { "email", "offline_access", "https://outlook.office.com/SMTP.Send" }; public static readonly string[] ImapScopes = new string[] { "email", "offline_access", "https://outlook.office.com/IMAP.AccessAsUser.All", }; public static IConfidentialClientApplication CreateConfidentialClient () { var clientId = "Application (client) ID"; var tenantId = "common"; // common = anybody with microsoft account personal or organization; other options see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints var clientSecret = "client secret"; var redirectURL = "https://example.com/oauth/microsoft/callback"; var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create (clientId) .WithAuthority ($"https://login.microsoftonline.com/{tenantId}/v2.0") .WithClientSecret (clientSecret) .WithRedirectUri (redirectURL) .Build (); // You also need to configure an MSAL token cache. so that token are remembered. return confidentialClientApplication; } } ``` ```csharp // Registration page - redirect user to Microsoft to get authorization public async Task OnPostAsync () { var client = OAuthMicrosoft.CreateConfidentialClient (); // Note: When getting authorization, specify all of the scopes that your application will ever need (eg. SMTP /and/ IMAP). // Later, when requesting an access token, you will only ask for the specific scopes that you need (e.g. SMTP). var authurlbuilder = client.GetAuthorizationRequestUrl (OAuthMicrosoft.RegistrationScopes); var authurl = await authurlbuilder.ExecuteAsync (); return this.Redirect (authurl.ToString ()); } // Callback page = https://example.com/oauth/microsoft/callback in this example public async Task OnGet ([FromQuery] string code) { var confidentialClientApplication = OAuthMicrosoft.CreateConfidentialClient (); var scopes = OAuthMicrosoft.SmtpScopes; var auth = await confidentialClientApplication.AcquireTokenByAuthorizationCode (scopes, code).ExecuteAsync (); //this saves the token in msal cache var ident = auth.Account.HomeAccountId.Identifier; // Note: you will need to persist the ident to refer to later. } // Use the credentials public async Task SendEmailAsync (string ident) { var confidentialClientApplication = OAuthMicrosoft.CreateConfidentialClient (); var account = await confidentialClientApplication.GetAccountAsync (ident); var scopes = OAuthMicrosoft.SmtpScopes; try { var auth = await confidentialClientApplication.AcquireTokenSilent (scopes, account).ExecuteAsync (); using (var client = new SmtpClient ()) { await client.ConnectAsync ("smtp-mail.outlook.com", 587, SecureSocketOptions.StartTls); var oauth2 = new SaslMechanismOAuth2 (auth.Account.Username, auth.AccessToken); await client.AuthenticateAsync (oauth2); var serverfeedback = await client.SendAsync (message); await client.DisconnectAsync (true); } } catch (MsalUiRequiredException) { throw new Exception ("Need to get authorization again"); } } public async Task TestImapAsync (string ident) { var confidentialClientApplication = OAuthMicrosoft.CreateConfidentialClient (); var account = await confidentialClientApplication.GetAccountAsync (ident); var scopes = OAuthMicrosoft.ImapScopes; var auth = await confidentialClientApplication.AcquireTokenSilent (scopes, account).ExecuteAsync (); var oauth2 = new SaslMechanismOAuth2 (auth.Account.Username, auth.AccessToken); using (var client = new ImapClient ()) { await client.ConnectAsync ("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect); await client.AuthenticateAsync (oauth2); await client.DisconnectAsync (true); } } ``` ## Web Services ### Registering Service Principals for Your Web Service Once your web service has been registered, the tenant admin will need to register your service principal. To use the New-ServicePrincipal cmdlet, open an [Azure Powershell](https://learn.microsoft.com/en-us/powershell/azure/new-azureps-module-az?view=azps-10.2.0) terminal and install ExchangeOnlineManagement and connect to your tenant as shown below: ```powershell Install-Module -Name ExchangeOnlineManagement -allowprerelease Import-module ExchangeOnlineManagement Connect-ExchangeOnline -Organization ``` Next, register the Service Principal for your web service: ```powershell New-ServicePrincipal -AppId -ObjectId [-Organization ] ``` Note: In the Azure portal, make sure you retrieve the Object ID from the Service Principal, under Enterprise Applications, and not the App Registration. ### Granting Permissions for Your Web Service In order to grant permissions for your web service to access an Office365 and/or Exchange account, you'll need to first get the Service Principal ID registered in the previous step using the following command: ```powershell Get-ServicePrincipal | fl ``` Once you have the Service Principal ID for your web service, use the following command to add full mailbox permissions for the email account that your web service will be accessing: ```powershelllo;.k,; Add-MailboxPermission -Identity "john.smith@example.com" -User -AccessRights FullAccess ``` ### Authenticating a Web Service with OAuth2 Now that you have the **Client ID** and **Tenant ID** strings, you'll need to plug those values into your application. The following sample code uses the [Microsoft.Identity.Client](https://www.nuget.org/packages/Microsoft.Identity.Client/) nuget package for obtaining the access token which will be needed by MailKit to pass on to the Exchange server. ```csharp static async Task GetConfidentialClientOAuth2CredentialsAsync (string protocol, CancellationToken cancellationToken = default) { var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create (clientId) .WithAuthority ($"https://login.microsoftonline.com/{tenantId}/v2.0") .WithCertificate (certificate) // or .WithClientSecret (clientSecret) .Build (); string[] scopes; if (protocol.Equals ("SMTP", StringComparison.OrdinalIgnoreCase)) { scopes = new string[] { // For SMTP, use the following scope "https://outlook.office365.com/.default" }; } else { scopes = new string[] { // For IMAP and POP3, use the following scope "https://ps.outlook.com/.default" }; } return await confidentialClientApplication.AcquireTokenForClient (scopes).ExecuteAsync (cancellationToken); } ``` #### IMAP (using ConfidentialClientApplication) ```csharp var result = await GetConfidentialClientOAuth2CredentialsAsync ("IMAP"); var oauth2 = new SaslMechanismOAuth2 ("username@outlook.com", result.AccessToken); using (var client = new ImapClient ()) { await client.ConnectAsync ("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect); await client.AuthenticateAsync (oauth2); await client.DisconnectAsync (true); } ``` #### SMTP (using ConfidentialClientApplication) ```csharp var result = await GetConfidentialClientOAuth2CredentialsAsync ("SMTP"); var oauth2 = new SaslMechanismOAuth2 ("username@outlook.com", result.AccessToken); using (var client = new SmtpClient ()) { await client.ConnectAsync ("smtp.office365.com", 587, SecureSocketOptions.StartTls); await client.AuthenticateAsync (oauth2); await client.DisconnectAsync (true); } ``` ## Additional Resources For more information, check out the [Microsoft.Identity.Client](https://docs.microsoft.com/en-us/dotnet/api/microsoft.identity.client?view=azure-dotnet) documentation. ================================================ FILE: FAQ.md ================================================ # Frequently Asked Questions ## Question Index ### General * [Are MimeKit and MailKit completely free? Can I use them in my proprietary product(s)?](#completely-free) * [Why do I get `NotSupportedException: No data is available for encoding ######. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.`?](#register-provider) * [Why does text show up garbled in my ASP.NET Core / .NET Core / .NET 5+ app?](#garbled-text) * [Why do I get a `TypeLoadException` when I try to create a new MimeMessage?](#type-load-exception) * [Why do I get `"MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection."` when I try to Connect?](#ssl-handshake-exception) * [How can I get a protocol log for IMAP, POP3, or SMTP to see what is going wrong?](#protocol-log) * [Why doesn't MailKit find some of my GMail POP3 or IMAP messages?](#gmail-hidden-messages) * [How can I access GMail using MailKit?](#gmail-access) * [How can I log in to a GMail account using OAuth 2.0?](#gmail-oauth2) ### Messages * [How can I create a message with attachments?](#create-attachments) * [How can I get the main body of a message?](#message-body) * [How can I tell if a message has attachments?](#has-attachments) * [Why doesn't the `MimeMessage` class implement `ISerializable` so that I can serialize a message to disk and read it back later?](#serialize-message) * [How can I parse messages?](#load-messages) * [How can I save messages?](#save-messages) * [How can I save attachments?](#save-attachments) * [How can I get the email addresses in the From, To, and Cc headers?](#address-headers) * [Why do attachments with Unicode filenames appear as "ATT0####.dat" in Outlook?](#untitled-attachments) * [How can I decrypt PGP messages that are embedded in the main message text?](#decrypt-inline-pgp) * [How can I reply to a message?](#reply-message) * [How can I forward a message?](#forward-message) ### ImapClient * [How can I get the number of unread messages in a folder?](#imap-unread-count) * [How can I search for messages delivered between two dates?](#imap-search-date-range) * [What does "The ImapClient is currently busy processing a command." mean?](#imap-client-busy) * [Why do I get InvalidOperationException: "The folder is not currently open."?](#imap-folder-not-open-exception) * [Why doesn't ImapFolder.MoveTo() move the message out of the source folder?](#imap-move-does-not-move) * [How can I mark messages as read using IMAP?](#imap-mark-as-read) * [How can I re-synchronize the cache for an IMAP folder?](#imap-folder-resync) * [How can I login using a shared mailbox in Office365?](#office365-shared-mailboxes) ### SmtpClient * [Why doesn't the message show up in the "Sent Mail" folder after sending it?](#smtp-sent-folder) * [How can I send email to the SpecifiedPickupDirectory?](#smtp-specified-pickup-directory) * [How can I request a notification when the message is read by the user?](#smtp-request-read-receipt) * [How can I process a read receipt notification?](#smtp-process-read-receipt) ## General ### Q: Are MimeKit and MailKit completely free? Can I use them in my proprietary product(s)? Yes. MimeKit and MailKit are both completely free and open source. They are both covered under the [MIT](https://opensource.org/licenses/MIT) license. ### Q: Why do I get `NotSupportedException: No data is available for encoding ######. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.`? In .NET Core, Microsoft decided to split out the non-Unicode text encodings into a separate NuGet package called [System.Text.Encoding.CodePages](https://www.nuget.org/packages/System.Text.Encoding.CodePages). MimeKit already pulls in a reference to this NuGet package, so you shouldn't need to add a reference to it in your project. That said, you will still need to register the encoding provider. It is recommended that you add the following line of code to your program initialization (e.g. the beginning of your program's Main() method): ```csharp System.Text.Encoding.RegisterProvider (System.Text.CodePagesEncodingProvider.Instance); ``` ### Q: Why does text show up garbled in my ASP.NET Core / .NET Core / .NET 5+ app? .NET Core (and ASP.NET Core by extension) and .NET 5 (and later) only provide the Unicode encodings, ASCII and ISO-8859-1 by default. Other text encodings are not available to your application unless your application [registers](https://docs.microsoft.com/en-us/dotnet/api/system.text.encoding.registerprovider?view=net-5.0) the encoding provider that provides all of the additional encodings. First, add a package reference for the [System.Text.Encoding.CodePages](https://www.nuget.org/packages/System.Text.Encoding.CodePages) nuget package to your project and then register the additional text encodings using the following code snippet: ```csharp System.Text.Encoding.RegisterProvider (System.Text.CodePagesEncodingProvider.Instance); ``` Note: The above code snippet should be safe to call in .NET Framework versions >= 4.6 as well. ### Q: Why do I get a `TypeLoadException` when I try to create a new MimeMessage? This only seems to happen in cases where the application is built for .NET Framework (v4.x) and seems to be most common for ASP.NET web applications that were built using Visual Studio 2019 (it is unclear whether this happens with Visual Studio 2022 as well). The issue is that some (older?) versions of MSBuild do not correctly generate `\*.dll.config`, `app.config` and/or `web.config` files with proper assembly version binding redirects. If this problem is happening to you, make sure to use MimeKit and MailKit >= v4.0 which include `MimeKit.dll.config` and `MailKit.dll.config`. The next step is to manually edit your application's `app.config` (or `web.config`) to add a binding redirect for `System.Runtime.CompilerServices.Unsafe`: ```xml ``` ### Q: Why do I get `"MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection."` when I try to Connect? When you get an exception with that error message, it usually means that you are encountering one of the following scenarios: #### 1. The mail server does not support SSL on the specified port. There are 2 different ways to use SSL/TLS encryption with mail servers. The first way is to enable SSL/TLS encryption immediately upon connecting to the SMTP, POP3 or IMAP server. This method requires an "SSL port" because the standard port defined for the protocol is meant for plain-text communication. The second way is via a `STARTTLS` command (aka `STLS` for POP3) that is *optionally* supported by the server. Below is a table of the protocols supported by MailKit and the standard plain-text ports (which either do not support any SSL/TLS encryption at all or only via the `STARTTLS` command extension) and the SSL ports which require SSL/TLS encryption immediately upon a successful connection to the remote host. |Protocol|Standard Port|SSL Port| |:------:|:-----------:|:------:| | SMTP | 25 or 587 | 465 | | POP3 | 110 | 995 | | IMAP | 143 | 993 | It is important to use the correct `SecureSocketOptions` for the port that you are connecting to. If you are connecting to one of the standard ports above, you will need to use `SecureSocketOptions.None`, `SecureSocketOptions.StartTls` or `SecureSocketOptions.StartTlsWhenAvailable`. If you are connecting to one of the SSL ports, you will need to use `SecureSocketOptions.SslOnConnect`. You could also try using `SecureSocketOptions.Auto` which works by choosing the appropriate option to use by comparing the specified port to the ports in the above table. #### 2. The mail server that you are connecting to is using an expired (or otherwise untrusted) SSL certificate. Often times, mail servers will use self-signed certificates instead of using a certificate that has been signed by a trusted Certificate Authority. Another potential pitfall is when locally installed anti-virus software replaces the certificate in order to scan web traffic for viruses. When your system is unable to validate the mail server's certificate because it is not signed by a known and trusted Certificate Authority, the above error will occur. If you are on a Linux system or are running a web service in a Linux container, it might be possible to use the following command to install the standard set of Certificate Authority root certificates using the following command: ```text apt update && apt install -y ca-certificates ``` Another option is to work around this problem by supplying a custom [RemoteCertificateValidationCallback](https://msdn.microsoft.com/en-us/library/ms145054) and setting it on the client's [ServerCertificateValidationCallback](https://mimekit.net/docs/html/P_MailKit_MailService_ServerCertificateValidationCallback.htm) property. In the simplest example, you could do something like this (although I would strongly recommend against it in production use): ```csharp using (var client = new SmtpClient ()) { client.ServerCertificateValidationCallback = (s,c,h,e) => true; client.Connect (hostName, port, SecureSocketOptions.Auto); // ... } ``` A better solution might be to compare the certificate's common name, issuer, serial number, and fingerprint to known values to make sure that the certificate can be trusted. Take the following code snippet as an example of how to do this: ```csharp bool MyServerCertificateValidationCallback (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (sslPolicyErrors == SslPolicyErrors.None) return true; // Note: The following code casts to an X509Certificate2 because it's easier to get the // values for comparison, but it's possible to get them from an X509Certificate as well. if (certificate is X509Certificate2 certificate2) { var cn = certificate2.GetNameInfo (X509NameType.SimpleName, false); var fingerprint = certificate2.Thumbprint; var serial = certificate2.SerialNumber; var issuer = certificate2.Issuer; return cn == "imap.gmail.com" && issuer == "CN=GTS CA 1O1, O=Google Trust Services, C=US" && serial == "00A15434C2695FB1880300000000CBF786" && fingerprint == "F351BCB631771F19AF41DFF22EB0A0839092DA51"; } return false; } ``` The downside of the above example is that it requires hard-coding known values for "trusted" mail server certificates which can quickly become unwieldy to deal with if your program is meant to be used with a wide range of mail servers. The best approach would be to prompt the user with a dialog explaining that the certificate is not trusted for the reasons enumerated by the [SslPolicyErrors](https://docs.microsoft.com/en-us/dotnet/api/system.net.security.sslpolicyerrors?view=netframework-4.8) argument as well as potentially the errors provided in the [X509Chain](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509chain?view=netframework-4.8). If the user wishes to accept the risks of trusting the certificate, your program could then `return true`. For more details on writing a custom SSL certificate validation callback, it may be worth checking out the [SslCertificateValidation.cs](https://github.com/jstedfast/MailKit/blob/master/Documentation/Examples/SslCertificateValidation.cs) example. #### 3. A Certificate Authority CRL server for one or more of the certificates in the chain is temporarily unavailable. Most Certificate Authorities are probably pretty good at keeping their CRL and/or OCSP servers up 24/7, but occasionally they *do* go down or are otherwise unreachable due to other network problems between you and the server. When this happens, it becomes impossible to check the revocation status of one or more of the certificates in the chain. To ignore revocation checks, you can set the [CheckCertificateRevocation](https://www.mimekit.net/docs/html/P_MailKit_IMailService_CheckCertificateRevocation.htm) property of the IMAP, POP3 or SMTP client to `false` before you connect: ```csharp using (var client = new SmtpClient ()) { client.CheckCertificateRevocation = false; client.Connect (hostName, port, SecureSocketOptions.Auto); // ... } ``` #### 4. The server does not support the same set of SSL/TLS protocols that the client is configured to use. MailKit attempts to keep up with the latest security recommendations and so is continuously removing older SSL and TLS protocols that are no longer considered secure from the default configuration. This often means that MailKit's SMTP, POP3 and IMAP clients will fail to connect to servers that are still using older SSL and TLS protocols. Currently, the SSL and TLS protocols that are not supported by default are: SSL v2.0, SSL v3.0, TLS v1.0 and TLS v1.1. You can override MailKit's default set of supported [SSL and TLS protocols](https://docs.microsoft.com/en-us/dotnet/api/system.security.authentication.sslprotocols?view=netframework-4.8) by setting the value of the [SslProtocols](https://www.mimekit.net/docs/html/P_MailKit_MailService_SslProtocols.htm) property on your SMTP, POP3 or IMAP client. For example: ```csharp using (var client = new SmtpClient ()) { // Allow SSLv3.0 and all versions of TLS client.SslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13; client.Connect ("smtp.gmail.com", 465, true); // ... } ``` ### Q: How can I get a protocol log for IMAP, POP3, or SMTP to see what is going wrong? All of MailKit's client implementations have a constructor that takes a nifty [IProtocolLogger](https://www.mimekit.net/docs/html/T_MailKit_IProtocolLogger.htm) interface for logging client/server communications. Out of the box, you can use the handy [ProtocolLogger](https://www.mimekit.net/docs/html/T_MailKit_ProtocolLogger.htm) class. Here are some examples of how to use it: ```csharp // log to a file called 'imap.log' var client = new ImapClient (new ProtocolLogger ("imap.log")); ``` ```csharp // log to standard output (i.e. the console) var client = new ImapClient (new ProtocolLogger (Console.OpenStandardOutput ())); ``` **Note:** When submitting a protocol log as part of a bug report, make sure to scrub any sensitive information including your authentication credentials. This information will generally be the base64 encoded blob immediately following an `AUTHENTICATE` or `AUTH` command (depending on the type of server). The only exception to this case is if you are authenticating with `NTLM` in which case I *may* need this information, but *only if* the bug/error is in the authentication step. ### Q: Why doesn't MailKit find some of my GMail POP3 or IMAP messages? By default, GMail's POP3 and IMAP server does not behave like standard POP3 or IMAP servers and hides messages from clients using those protocols (as well as having other non-standard behavior). If you want to configure your GMail POP3 or IMAP settings to behave the way POP3 and IMAP are intended to behave according to their protocol specifications, you'll need to log in to your GMail account via your web browser and navigate to the `Forwarding and POP/IMAP` tab of your GMail Settings page and set your options to look like this:  #### POP download: **1. Status:** POP is enabled for all mail that has arrived since 12/31/69 - [X] Enable POP for **all mail** (even mail that's already been downloaded) - [ ] Enable POP for **mail that arrives from now on** - [ ] **Disable** POP **2. When messages are accessed with POP** \[keep GMail's copy in the Inbox] #### IMAP access: **When I mark a message in IMAP as deleted:** - [ ] Auto-Expunge on - Immediately update the server. (default) - [X] Auto-Expunge off - Wait for the client to update the server. **When a message is marked as deleted and expunged from the last visible IMAP folder:** - [ ] Archive the message (default) - [ ] Move the message to the Trash - [X] Immediately delete the message forever **Folder size limits** - [X] Do not limit the number of messages in an IMAP folder (default) - [ ] Limit IMAP folders to contain no more than this many messages \[1000] ### Q: How can I access GMail using MailKit? As of September 30th, 2024, authentication using only a username and password is [no longer supported by Google](https://support.google.com/accounts/answer/6010255?hl=en). There are now only 2 options to choose from: 1. Use [OAuth 2.0 authentication](#gmail-oauth2) 2. Use an "App password" To use an App password, you will first need to [turn on 2-Step Verification](https://support.google.com/accounts/answer/185839). Once 2-Step Verification is turned on, you can [generate an App password](https://myaccount.google.com/apppasswords). Then, assuming that your GMail account is `user@gmail.com`, you would use the following code snippet to connect to GMail via IMAP: ```csharp using (var client = new ImapClient ()) { client.Connect ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect); client.Authenticate ("user@gmail.com", "app-specific-password"); // do stuff... client.Disconnect (true); } ``` Connecting via POP3 or SMTP is identical except for the host names and ports (and, of course, you'd use a `Pop3Client` or `SmtpClient` as appropriate). ### Q: How can I log in to a GMail account using OAuth 2.0? The first thing you need to do is follow [Google's instructions](https://developers.google.com/accounts/docs/OAuth2) for obtaining OAuth 2.0 credentials for your application. (Or, as an alternative set of step-by-step instructions, you can follow the directions that I have written in [GMailOAuth2.md](https://github.com/jstedfast/MailKit/blob/master/GMailOAuth2.md).) Once you've done that, the easiest way to obtain an access token is to use Google's [Google.Apis.Auth](https://www.nuget.org/packages/Google.Apis.Auth/) library: ```csharp const string GMailAccount = "username@gmail.com"; var clientSecrets = new ClientSecrets { ClientId = "XXX.apps.googleusercontent.com", ClientSecret = "XXX" }; var codeFlow = new GoogleAuthorizationCodeFlow (new GoogleAuthorizationCodeFlow.Initializer { // Cache tokens in ~/.local/share/google-filedatastore/CredentialCacheFolder on Linux/Mac DataStore = new FileDataStore ("CredentialCacheFolder", false), Scopes = new [] { "https://mail.google.com/" }, ClientSecrets = clientSecrets, LoginHint = GMailAccount }); // Note: For a web app, you'll want to use AuthorizationCodeWebApp instead. var codeReceiver = new LocalServerCodeReceiver (); var authCode = new AuthorizationCodeInstalledApp (codeFlow, codeReceiver); var credential = await authCode.AuthorizeAsync (GMailAccount, CancellationToken.None); if (credential.Token.IsStale) await credential.RefreshTokenAsync (CancellationToken.None); var oauth2 = new SaslMechanismOAuthBearer (credential.UserId, credential.Token.AccessToken); using (var client = new ImapClient ()) { await client.ConnectAsync ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect); await client.AuthenticateAsync (oauth2); await client.DisconnectAsync (true); } ``` ## Messages ### Q: How can I create a message with attachments? To construct a message with attachments, the first thing you'll need to do is create a `multipart/mixed` container which you'll then want to add the message body to first. Once you've added the body, you can then add MIME parts to it that contain the content of the files you'd like to attach, being sure to set the `Content-Disposition` header value to attachment. You'll probably also want to set the `filename` parameter on the `Content-Disposition` header as well as the `name` parameter on the `Content-Type` header. The most convenient way to do this is to use the [MimePart.FileName](https://www.mimekit.net/docs/html/P_MimeKit_MimePart_FileName.htm) property which will set both parameters for you as well as setting the `Content-Disposition` header value to `attachment` if it has not already been set to something else. ```csharp var message = new MimeMessage (); message.From.Add (new MailboxAddress ("Joey", "joey@friends.com")); message.To.Add (new MailboxAddress ("Alice", "alice@wonderland.com")); message.Subject = "How you doin?"; // create our message text, just like before (except don't set it as the message.Body) var body = new TextPart ("plain") { Text = @"Hey Alice, What are you up to this weekend? Monica is throwing one of her parties on Saturday and I was hoping you could make it. Will you be my +1? -- Joey " }; // create an image attachment for the file located at path var attachment = new MimePart ("image", "gif") { Content = new MimeContent (File.OpenRead (path), ContentEncoding.Default), ContentDisposition = new ContentDisposition (ContentDisposition.Attachment), ContentTransferEncoding = ContentEncoding.Base64, FileName = Path.GetFileName (path) }; // now create the multipart/mixed container to hold the message text and the // image attachment var multipart = new Multipart ("mixed"); multipart.Add (body); multipart.Add (attachment); // now set the multipart/mixed as the message body message.Body = multipart; ``` A simpler way to construct messages with attachments is to take advantage of the [BodyBuilder](https://www.mimekit.net/docs/html/T_MimeKit_BodyBuilder.htm) class. ```csharp var message = new MimeMessage (); message.From.Add (new MailboxAddress ("Joey", "joey@friends.com")); message.To.Add (new MailboxAddress ("Alice", "alice@wonderland.com")); message.Subject = "How you doin?"; var builder = new BodyBuilder (); // Set the plain-text version of the message text builder.TextBody = @"Hey Alice, What are you up to this weekend? Monica is throwing one of her parties on Saturday and I was hoping you could make it. Will you be my +1? -- Joey "; // We may also want to attach a calendar event for Monica's party... builder.Attachments.Add (@"C:\Users\Joey\Documents\party.ics"); // Now we just need to set the message body and we're done message.Body = builder.ToMessageBody (); ``` For more information, see [Creating Messages](https://www.mimekit.net/docs/html/Creating-Messages.htm). ### Q: How can I get the main body of a message? (Note: for the TL;DR version, skip to [the end](#message-body-tldr)) MIME is a tree structure of parts. There are multiparts which contain other parts (even other multiparts). There are message parts which contain messages. And finally, there are leaf-node parts which contain content. There are a few common message structures: 1. The message contains only a `text/plain` or `text/html` part (easy, just use that). 2. The message contains a `multipart/alternative` which will typically look a bit like this: ``` multipart/alternative text/plain text/html ``` 3. Same as above, but the html part is inside a `multipart/related` so that it can embed images: ``` multipart/alternative text/plain multipart/related text/html image/jpeg image/png ``` 4. The message contains a textual body part as well as some attachments: ``` multipart/mixed text/plain or text/html application/octet-stream application/zip ``` 5. the same as above, but with the first part replaced with either #2 or #3. To illustrate: ``` multipart/mixed multipart/alternative text/plain text/html application/octet-stream application/zip ``` or... ``` multipart/mixed multipart/alternative text/plain multipart/related text/html image/jpeg image/png application/octet-stream application/zip ``` Now, if you don't care about any of that and just want to get the text of the first `text/plain` or `text/html` part you can find, that's easy. [MimeMessage](https://www.mimekit.net/docs/html/T_MimeKit_MimeMessage.htm) has two convenience properties for this: [TextBody](https://www.mimekit.net/docs/html/P_MimeKit_MimeMessage_TextBody.htm) and [HtmlBody](https://www.mimekit.net/docs/html/P_MimeKit_MimeMessage_HtmlBody.htm). `MimeMessage.HtmlBody`, as the name implies, will traverse the MIME structure for you and find the most appropriate body part with a `Content-Type` of `text/html` that can be interpreted as the message body. Likewise, the `TextBody` property can be used to get the `text/plain` version of the message body. For more information, see [Working with Messages](https://www.mimekit.net/docs/html/Working-With-Messages.htm). ### Q: How can I tell if a message has attachments? In most cases, a message with a body that has a MIME-type of `multipart/mixed` containing more than a single part probably has attachments. As illustrated above, the first part of a `multipart/mixed` is typically the textual body of the message, but it is not always quite that simple. In general, MIME attachments will have a `Content-Disposition` header with a value of `attachment`. To get the list of body parts matching this criteria, you can use the [MimeMessage.Attachments](https://www.mimekit.net/docs/html/P_MimeKit_MimeMessage_Attachments.htm) property. Unfortunately, not all mail clients follow this convention and so you may need to write your own custom logic. For example, you may wish to treat all body parts having a `name` or `filename` parameter set on them: ```csharp var attachments = message.BodyParts.OfType ().Where (part => !string.IsNullOrEmpty (part.FileName)); ``` A more sophisticated approach is to treat body parts not referenced by the main textual body part of the message as attachments. In other words, treat any body part not used for rendering the message as an attachment. For an example on how to do this, consider the following code snippets: ```csharp /// /// Visits a MimeMessage and generates HTML suitable to be rendered by a browser control. /// class HtmlPreviewVisitor : MimeVisitor { Liststack = new List (); List attachments = new List (); readonly string tempDir; string body; /// /// Creates a new HtmlPreviewVisitor. /// /// A temporary directory used for storing image files. public HtmlPreviewVisitor (string tempDirectory) { tempDir = tempDirectory; } ////// The list of attachments that were in the MimeMessage. /// public IListAttachments { get { return attachments; } } /// /// The HTML string that can be set on the BrowserControl. /// public string HtmlBody { get { return body ?? string.Empty; } } protected override void VisitMultipartAlternative (MultipartAlternative alternative) { // walk the multipart/alternative children backwards from greatest level of faithfulness to the least faithful for (int i = alternative.Count - 1; i >= 0 && body == null; i--) alternative[i].Accept (this); } protected override void VisitMultipartRelated (MultipartRelated related) { var root = related.Root; // push this multipart/related onto our stack stack.Add (related); // visit the root document root.Accept (this); // pop this multipart/related off our stack stack.RemoveAt (stack.Count - 1); } // look up the image based on the img src url within our multipart/related stack bool TryGetImage (string url, out MimePart image) { UriKind kind; int index; Uri uri; if (Uri.IsWellFormedUriString (url, UriKind.Absolute)) kind = UriKind.Absolute; else if (Uri.IsWellFormedUriString (url, UriKind.Relative)) kind = UriKind.Relative; else kind = UriKind.RelativeOrAbsolute; try { uri = new Uri (url, kind); } catch { image = null; return false; } for (int i = stack.Count - 1; i >= 0; i--) { if ((index = stack[i].IndexOf (uri)) == -1) continue; image = stack[i][index] as MimePart; return image != null; } image = null; return false; } ////// Get a file:// URI for the image attachment. /// ////// Saves the image attachment to a temp file and returns a file:// URI for the /// temp file. /// ///The file:// URI. /// The image attachment. /// The original HTML image URL. string GetFileUri (MimePart image, string url) { string fileName = url.Replace (':', '_').Replace ('\\', '_').Replace ('/', '_'); string path = Path.Combine (tempDir, fileName); if (!File.Exists (path)) { using (var output = File.Create (path)) image.Content.DecodeTo (output); } return "file://" + path.Replace ('\\', '/'); } ////// Get a data: URI for the image attachment. /// ////// Encodes the image attachment into a string suitable for setting as a src= attribute value in /// an img tag. /// ///The data: URI. /// The image attachment. string GetDataUri (MimePart image) { using (var memory = new MemoryStream ()) { image.Content.DecodeTo (memory); var buffer = memory.GetBuffer (); var length = (int) memory.Length; var base64 = Convert.ToBase64String (buffer, 0, length); return string.Format ("data:{0};base64,{1}", image.ContentType.MimeType, base64); } } // Replacesurls that refer to images embedded within the message with // "file://" urls that the browser control will actually be able to load. void HtmlTagCallback (HtmlTagContext ctx, HtmlWriter htmlWriter) { if (ctx.TagId == HtmlTagId.Meta && !ctx.IsEndTag) { bool isContentType = false; ctx.WriteTag (htmlWriter, false); // replace charsets with "utf-8" since our output will be in utf-8 (and not whatever the original charset was) foreach (var attribute in ctx.Attributes) { if (attribute.Id == HtmlAttributeId.Charset) { htmlWriter.WriteAttributeName (attribute.Name); htmlWriter.WriteAttributeValue ("utf-8"); } else if (isContentType && attribute.Id == HtmlAttributeId.Content) { htmlWriter.WriteAttributeName (attribute.Name); htmlWriter.WriteAttributeValue ("text/html; charset=utf-8"); } else { if (attribute.Id == HtmlAttributeId.HttpEquiv && attribute.Value != null && attribute.Value.Equals ("Content-Type", StringComparison.OrdinalIgnoreCase)) isContentType = true; htmlWriter.WriteAttribute (attribute); } } } else if (ctx.TagId == HtmlTagId.Image && !ctx.IsEndTag && stack.Count > 0) { ctx.WriteTag (htmlWriter, false); // replace the src attribute with a file:// URL foreach (var attribute in ctx.Attributes) { if (attribute.Id == HtmlAttributeId.Src) { if (!TryGetImage (attribute.Value, out var image)) { htmlWriter.WriteAttribute (attribute); continue; } // Note: you can either use a "file://" URI or you can use a // "data:" URI, the choice is yours. var uri = GetFileUri (image, attribute.Value); //var uri = GetDataUri (image); htmlWriter.WriteAttributeName (attribute.Name); htmlWriter.WriteAttributeValue (uri); } else { htmlWriter.WriteAttribute (attribute); } } } else if (ctx.TagId == HtmlTagId.Body && !ctx.IsEndTag) { ctx.WriteTag (htmlWriter, false); // add and/or replace oncontextmenu="return false;" foreach (var attribute in ctx.Attributes) { if (attribute.Name.Equals ("oncontextmenu", StringComparison.OrdinalIgnoreCase)) continue; htmlWriter.WriteAttribute (attribute); } htmlWriter.WriteAttribute ("oncontextmenu", "return false;"); } else { // pass the tag through to the output ctx.WriteTag (htmlWriter, true); } } protected override void VisitTextPart (TextPart entity) { TextConverter converter; if (body != null) { // since we've already found the body, treat this as an attachment attachments.Add (entity); return; } if (entity.IsHtml) { converter = new HtmlToHtml { HtmlTagCallback = HtmlTagCallback }; } else if (entity.IsFlowed) { var flowed = new FlowedToHtml (); string delsp; if (entity.ContentType.Parameters.TryGetValue ("delsp", out delsp)) flowed.DeleteSpace = delsp.Equals ("yes", StringComparison.OrdinalIgnoreCase); converter = flowed; } else { converter = new TextToHtml (); } body = converter.Convert (entity.Text); } protected override void VisitTnefPart (TnefPart entity) { // extract any attachments in the MS-TNEF part attachments.AddRange (entity.ExtractAttachments ()); } protected override void VisitMessagePart (MessagePart entity) { // treat message/rfc822 parts as attachments attachments.Add (entity); } protected override void VisitMimePart (MimePart entity) { // realistically, if we've gotten this far, then we can treat this as an attachment // even if the IsAttachment property is false. attachments.Add (entity); } } ``` And the way you'd use this visitor might look something like this: ```csharp void Render (MimeMessage message) { var tmpDir = Path.Combine (Path.GetTempPath (), message.MessageId); var visitor = new HtmlPreviewVisitor (tmpDir); Directory.CreateDirectory (tmpDir); message.Accept (visitor); DisplayHtml (visitor.HtmlBody); DisplayAttachments (visitor.Attachments); } ``` Once you've rendered the message using the above technique, you'll have a list of attachments that were not used, even if they did not match the simplistic criteria used by the `MimeMessage.Attachments` property. ### Q: Why doesn't the `MimeMessage` class implement `ISerializable` so that I can serialize a message to disk and read it back later? The MimeKit API was designed to use the existing MIME format for serialization. In light of this, the ability to use the .NET serialization API and format did not make much sense to support. You can easily serialize a [MimeMessage](https://www.mimekit.net/docs/html/T_MimeKit_MimeMessage.htm) to a stream using the [WriteTo](https://www.mimekit.net/docs/html/Overload_MimeKit_MimeMessage_WriteTo.htm) methods. For more information on this topic, see the following other two topics: * [How can I parse messages?](#load-messages) * [How can I save messages?](#save-messages) ### Q: How can I parse messages? One of the more common operations that MimeKit is meant for is parsing email messages from arbitrary streams. There are two ways of accomplishing this task. The first way is to use one of the [Load](https://www.mimekit.net/docs/html/Overload_MimeKit_MimeMessage_Load.htm) methods on `MimeMessage`: ```csharp // Load a MimeMessage from a stream var message = MimeMessage.Load (stream); ``` Or you can load a message from a file path: ```csharp // Load a MimeMessage from a file path var message = MimeMessage.Load ("message.eml"); ``` The second way is to use the [MimeParser](https://www.mimekit.net/docs/html/T_MimeKit_MimeParser.htm) class. For the most part, using the `MimeParser` directly is not necessary unless you wish to parse a Unix mbox file stream. However, this is how you would do it: ```csharp // Load a MimeMessage from a stream var parser = new MimeParser (stream, MimeFormat.Entity); var message = parser.ParseMessage (); ``` For Unix mbox file streams, you would use the parser like this: ```csharp // Load every message from a Unix mbox var parser = new MimeParser (stream, MimeFormat.Mbox); while (!parser.IsEndOfStream) { var message = parser.ParseMessage (); // do something with the message } ``` ### Q: How can I save messages? One you've got a [MimeMessage](https://www.mimekit.net/docs/html/T_MimeKit_MimeMessage.htm), you can save it to a file using the [WriteTo](https://mimekit.net/docs/html/Overload_MimeKit_MimeMessage_WriteTo.htm) method: ```csharp message.WriteTo ("message.eml"); ``` The `WriteTo` method also has overloads that allow you to write the message to a `Stream` instead. By default, the `WriteTo` method will save the message using DOS line-endings on Windows and Unix line-endings on Unix-based systems such as macOS and Linux. You can override this behavior by passing a [FormatOptions](https://mimekit.net/docs/html/T_MimeKit_FormatOptions.htm) argument to the method: ```csharp // clone the default formatting options var format = FormatOptions.Default.Clone (); // override the line-endings to be DOS no matter what platform we are on format.NewLineFormat = NewLineFormat.Dos; message.WriteTo (format, "message.eml"); ``` Note: While it may seem like you can safely use the `ToString` method to serialize a message, ***DON'T DO IT!*** This is ***not*** safe! MIME messages cannot be accurately represented as strings due to the fact that each MIME part of the message *may* be encoded in a different character set, thus making it impossible to convert the message into a unicode string using a single charset to do the conversion (which is *exactly* what `ToString` does). ### Q: How can I save attachments? If you've already got a [MimePart](https://www.mimekit.net/docs/html/T_MimeKit_MimePart.htm) that represents the attachment that you'd like to save, here's how you might save it: ```csharp using (var stream = File.Create (fileName)) attachment.Content.DecodeTo (stream); ``` Pretty simple, right? But what if your attachment is actually a [MessagePart](https://www.mimekit.net/docs/html/T_MimeKit_MessagePart.htm)? To save the content of a `message/rfc822` part, you'd use the following code snippet: ```csharp using (var stream = File.Create (fileName)) attachment.Message.WriteTo (stream); ``` If you are iterating over all of the attachments in a message, you might do something like this: ```csharp foreach (var attachment in message.Attachments) { var fileName = attachment.ContentDisposition?.FileName ?? attachment.ContentType.Name; using (var stream = File.Create (fileName)) { if (attachment is MessagePart) { var rfc822 = (MessagePart) attachment; rfc822.Message.WriteTo (stream); } else { var part = (MimePart) attachment; part.Content.DecodeTo (stream); } } } ``` ### Q: How can I get the email addresses in the From, To, and Cc headers? The [From](https://www.mimekit.net/docs/html/P_MimeKit_MimeMessage_From.htm), [To](https://www.mimekit.net/docs/html/P_MimeKit_MimeMessage_To.htm), and [Cc](https://www.mimekit.net/docs/html/P_MimeKit_MimeMessage_Cc.htm) properties of a [MimeMessage](https://www.mimekit.net/docs/html/T_MimeKit_MimeMessage.htm) are all of type [InternetAddressList](https://www.mimekit.net/docs/html/T_MimeKit_InternetAddressList.htm). An `InternetAddressList` is a list of [InternetAddress](https://www.mimekit.net/docs/html/T_MimeKit_InternetAddress.htm) items. This is where most people start to get lost because an `InternetAddress` is an abstract class that only really has a [Name](https://www.mimekit.net/docs/html/P_MimeKit_InternetAddress_Name.htm) property. As you've probably already discovered, the `Name` property contains the name of the person (if available), but what you want is his or her email address, not their name. To get the email address, you'll need to figure out what subclass of address each `InternetAddress` really is. There are 2 subclasses of `InternetAddress`: [GroupAddress](https://www.mimekit.net/docs/html/T_MimeKit_GroupAddress.htm) and [MailboxAddress](https://www.mimekit.net/docs/html/T_MimeKit_MailboxAddress.htm). A `GroupAddress` is a named group of more `InternetAddress` items that are contained within the [Members](https://www.mimekit.net/docs/html/P_MimeKit_GroupAddress_Members.htm) property. To get an idea of what a group address represents, consider the following examples: ``` To: My Friends: Joey
, Monica , "Mrs. Chanandler Bong" , Ross , Rachel ; ``` In the above example, the `To` header's `InternetAddressList` will contain only 1 item which will be a `GroupAddress` with a `Name` value of `My Friends`. The `Members` property of the `GroupAddress` will contain 5 more `InternetAddress` items (which will all be instances of `MailboxAddress`). The above example, however, is not very likely to ever be seen in messages you deal with. A far more common example would be the one below: ``` To: undisclosed-recipients:; ``` Most of the time, the `From`, `To`, and `Cc` headers will only contain mailbox addresses. As you will notice, a `MailboxAddress` has an [Address](https://www.mimekit.net/docs/html/P_MimeKit_MailboxAddress_Address.htm) property which will contain the email address of the mailbox. In the following example, the `Address` property will contain the value `john@smith.com`: ``` To: John Smith ``` If you only care about getting a flattened list of the mailbox addresses in a `From`, `To`, or `Cc` header, you can do something like this: ```csharp foreach (var mailbox in message.To.Mailboxes) Console.WriteLine ("{0}'s email address is {1}", mailbox.Name, mailbox.Address); ``` ### Q: Why do attachments with Unicode filenames appear as "ATT0####.dat" in Outlook? An attachment filename is stored as a MIME parameter on the `Content-Disposition` header. Unfortunately, the original MIME specifications did not specify a method for encoding non-ASCII filenames. In 1997, [rfc2184](https://tools.ietf.org/html/rfc2184) (later updated by [rfc2231](https://tools.ietf.org/html/rfc2231)) was published which specified an encoding mechanism to use for encoding them. Since there was a window in time where the MIME specifications did not define a way to encode them, some mail client developers decided to use the mechanism described by [rfc2047](https://tools.ietf.org/html/rfc2047) which was meant for encoding non-ASCII text in headers. While this may at first seem logical, the problem with this approach was that rfc2047 `encoded-word` tokens are not allowed to be in quotes (as well as some other issues) and so another, more appropriate, encoding mechanism was needed. Outlook is one of those mail clients which decided to encode filenames using the mechanism described in rfc2047 and until Outlook 2007, did not support filenames encoded using the mechanism defined in rfc2231. As of MimeKit v1.2.18, it is possible to configure MimeKit to use the rfc2047 encoding mechanism for filenames (and other `Content-Disposition` and `Content-Type` parameter values) by setting the encoding method on each individual [Parameter](https://www.mimekit.net/docs/html/T_MimeKit_Parameter.htm): ```csharp Parameter param; if (attachment.ContentDisposition.Parameters.TryGetValue ("filename", out param)) param.EncodingMethod = ParameterEncodingMethod.Rfc2047; ``` Or: ```csharp foreach (var param in attachment.ContentDisposition.Parameters) { param.EncodingMethod = ParameterEncodingMethod.Rfc2047; } ``` ### Q: How can I decrypt PGP messages that are embedded in the main message text? Some PGP-enabled mail clients, such as Thunderbird, embed encrypted PGP blurbs within the `text/plain` body of the message rather than using the PGP/MIME format that MimeKit prefers. These messages often look something like this: ```text Return-Path: Received: from [127.0.0.1] (hostname.example.com. [201.95.8.17]) by mx.google.com with ESMTPSA id l67sm26628445yha.8.2014.04.27.13.49.44 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 27 Apr 2014 13:49:44 -0700 (PDT) Message-ID: <535D6D67.8020803@example.com> Date: Sun, 27 Apr 2014 17:49:43 -0300 From: Die-Hard PGP Fan User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0 MIME-Version: 1.0 To: undisclosed-recipients:; Subject: Test of inline encrypted PGP blocks X-Enigmail-Version: 1.6 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-Antivirus: avast! (VPS 140427-1, 27/04/2014), Outbound message X-Antivirus-Status: Clean -----BEGIN PGP MESSAGE----- Charset: ISO-8859-1 Version: GnuPG v2.0.22 (MingW32) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ SGFoISBJIGZvb2xlZCB5b3UsIHRoaXMgdGV4dCBpc24ndCBhY3R1YWxseSBlbmNy eXB0ZWQgd2l0aCBQR1AsCml0J3MgYWN0dWFsbHkgb25seSBiYXNlNjQgZW5jb2Rl ZCEKCkknbSBqdXN0IHVzaW5nIHRoaXMgYXMgYW4gZXhhbXBsZSwgdGhvdWdoLCBz byBpdCBkb2Vzbid0IHJlYWxseSBtYXR0ZXIuCgpGb3IgdGhlIHNha2Ugb2YgYXJn dW1lbnQsIHdlJ2xsIHByZXRlbmQgdGhhdCB0aGlzIGlzIGFjdHVhbGx5IGFuIGVu Y3J5cHRlZApibHVyYi4gTW1ta2F5PyBUaGFua3MuCg== -----END PGP MESSAGE----- ``` To deal with these kinds of messages, I've added a method to OpenPgpContext called `GetDecryptedStream` which can be used to get the raw decrypted stream. There are actually 2 variants of this method: ```csharp public Stream GetDecryptedStream (Stream encryptedData, out DigitalSignatureCollection signatures) ``` and ```csharp public Stream GetDecryptedStream (Stream encryptedData) ``` The first variant is useful in cases where the encrypted PGP blurb is also digitally signed, allowing you to get your hands on the list of digital signatures in order for you to verify each of them. To decrypt the content of the message, you'll want to locate the `TextPart` (in this case, it'll just be `message.Body`) and then do this: ```csharp static Stream DecryptEmbeddedPgp (TextPart text) { using (var memory = new MemoryStream ()) { text.Content.DecodeTo (memory); memory.Position = 0; using (var ctx = new MyGnuPGContext ()) { return ctx.GetDecryptedStream (memory); } } } ``` What you do with that decrypted stream is up to you. It's up to you to figure out what the decrypted content is (is it text? a jpeg image? a video?) and how to display it to the user. ### Q: How can I reply to a message? Replying to a message is fairly simple. For the most part, you'd just create the reply message the same way you'd create any other message. There are only a few slight differences: 1. In the reply message, you'll want to prefix the `Subject` header with `"Re: "` if the prefix doesn't already exist in the message you are replying to (in other words, if you are replying to a message with a `Subject` of `"Re: party tomorrow night!"`, you would not prefix it with another `"Re: "`). 2. You will want to set the reply message's `In-Reply-To` header to the value of the `Message-Id` header in the original message. 3. You will want to copy the original message's `References` header into the reply message's `References` header and then append the original message's `Message-Id` header. 4. You will probably want to "quote" the original message's text in the reply. 5. If you are generating an automatic reply, you should also follow [RFC3834](https://www.rfc-editor.org/rfc/rfc3834) and set the `Auto-Submitted` value to `auto-replied`. If this logic were to be expressed in code, it might look something like this: ```csharp public static MimeMessage Reply (MimeMessage message, MailboxAddress from, bool replyToAll) { var reply = new MimeMessage (); reply.From.Add (from); // reply to the sender of the message if (message.ReplyTo.Count > 0) { reply.To.AddRange (message.ReplyTo); } else if (message.From.Count > 0) { reply.To.AddRange (message.From); } else if (message.Sender != null) { reply.To.Add (message.Sender); } if (replyToAll) { // include all of the other original recipients - TODO: remove ourselves from these lists reply.To.AddRange (message.To); reply.Cc.AddRange (message.Cc); } // set the reply subject if (!message.Subject?.StartsWith ("Re:", StringComparison.OrdinalIgnoreCase)) reply.Subject = "Re: " + (message.Subject ?? string.Empty); else reply.Subject = message.Subject; // construct the In-Reply-To and References headers if (!string.IsNullOrEmpty (message.MessageId)) { reply.InReplyTo = message.MessageId; foreach (var id in message.References) reply.References.Add (id); reply.References.Add (message.MessageId); } // if this is an automatic reply, be sure to specify this using the Auto-Submitted header in order to avoid (infinite) mail loops reply.Headers.Add (HeaderId.AutoSubmitted, "auto-replied"); // quote the original message text using (var quoted = new StringWriter ()) { var sender = message.Sender ?? message.From.Mailboxes.FirstOrDefault (); quoted.WriteLine ("On {0}, {1} wrote:", message.Date.ToString ("f"), !string.IsNullOrEmpty (sender.Name) ? sender.Name : sender.Address); using (var reader = new StringReader (message.TextBody)) { string line; while ((line = reader.ReadLine ()) != null) { quoted.Write ("> "); quoted.WriteLine (line); } } reply.Body = new TextPart ("plain") { Text = quoted.ToString () }; } return reply; } ``` But what if you wanted to reply to a message and quote the HTML formatting of the original message body (assuming it has an HTML body) while still including the embedded images? This gets a bit more complicated, but it's still doable... The first thing we'd need to do is implement our own [MimeVisitor](https://www.mimekit.net/docs/html/T_MimeKit_MimeVisitor.htm) to handle this: ```csharp public class ReplyVisitor : MimeVisitor { readonly Stack stack = new Stack (); MimeMessage original, reply; MailboxAddress from; bool replyToAll; int isRelated; /// /// Creates a new ReplyVisitor. /// public ReplyVisitor (MailboxAddress from, bool replyToAll) { this.replyToAll = replyToAll; this.from = from; } ////// Gets the reply. /// ///The reply. public MimeMessage Reply { get { return reply; } } void Push (MimeEntity entity) { var multipart = entity as Multipart; if (reply.Body == null) { reply.Body = entity; } else { var parent = stack.Peek (); parent.Add (entity); } if (multipart != null) stack.Push (multipart); } void Pop () { stack.Pop (); } static string GetOnDateSenderWrote (MimeMessage message) { var sender = message.Sender != null ? message.Sender : message.From.Mailboxes.FirstOrDefault (); var name = sender != null ? (!string.IsNullOrEmpty (sender.Name) ? sender.Name : sender.Address) : "an unknown sender"; return string.Format ("On {0}, {1} wrote:", message.Date.ToString ("f"), name); } ////// Visit the specified message. /// /// The message. public override void Visit (MimeMessage message) { reply = new MimeMessage (); original = message; stack.Clear (); reply.From.Add (from.Clone ()); // reply to the sender of the message if (message.ReplyTo.Count > 0) { reply.To.AddRange (message.ReplyTo); } else if (message.From.Count > 0) { reply.To.AddRange (message.From); } else if (message.Sender != null) { reply.To.Add (message.Sender); } if (replyToAll) { // include all of the other original recipients - TODO: remove ourselves from these lists reply.To.AddRange (message.To); reply.Cc.AddRange (message.Cc); } // set the reply subject if (!message.Subject?.StartsWith ("Re:", StringComparison.OrdinalIgnoreCase)) reply.Subject = "Re: " + (message.Subject ?? string.Empty); else reply.Subject = message.Subject; // construct the In-Reply-To and References headers if (!string.IsNullOrEmpty (message.MessageId)) { reply.InReplyTo = message.MessageId; foreach (var id in message.References) reply.References.Add (id); reply.References.Add (message.MessageId); } base.Visit (message); } ////// Visit the specified entity. /// /// The MIME entity. ////// Only Visit(MimeMessage) is supported. /// public override void Visit (MimeEntity entity) { throw new NotSupportedException (); } protected override void VisitMultipartAlternative (MultipartAlternative alternative) { var multipart = new MultipartAlternative (); Push (multipart); for (int i = 0; i < alternative.Count; i++) alternative[i].Accept (this); Pop (); } protected override void VisitMultipartRelated (MultipartRelated related) { var multipart = new MultipartRelated (); var root = related.Root; Push (multipart); root.Accept (this); isRelated++; for (int i = 0; i < related.Count; i++) { if (related[i] != root) related[i].Accept (this); } isRelated--; Pop (); } protected override void VisitMultipart (Multipart multipart) { foreach (var part in multipart) { if (part is MultipartAlternative) part.Accept (this); else if (part is MultipartRelated) part.Accept (this); else if (part is TextPart) part.Accept (this); } } void HtmlTagCallback (HtmlTagContext ctx, HtmlWriter htmlWriter) { if (ctx.TagId == HtmlTagId.Body && !ctx.IsEmptyElementTag) { if (ctx.IsEndTag) { // end our openinghtmlWriter.WriteEndTag (HtmlTagId.BlockQuote); // pass the
htmlWriter.WriteStartTag (HtmlTagId.BlockQuote); htmlWriter.WriteAttribute (HtmlAttributeId.Style, "border-left: 1px #ccc solid; margin: 0 0 0 .8ex; padding-left: 1ex;"); ctx.InvokeCallbackForEndTag = true; } } else { // pass the tag through to the output ctx.WriteTag (htmlWriter, true); } } string QuoteText (string text) { using (var quoted = new StringWriter ()) { quoted.WriteLine (GetOnDateSenderWrote (original)); using (var reader = new StringReader (text)) { string line; while ((line = reader.ReadLine ()) != null) { quoted.Write ("> "); quoted.WriteLine (line); } } return quoted.ToString (); } } protected override void VisitTextPart (TextPart entity) { string text; if (entity.IsHtml) { var converter = new HtmlToHtml { HtmlTagCallback = HtmlTagCallback }; text = converter.Convert (entity.Text); } else if (entity.IsFlowed) { var converter = new FlowedToText (); text = converter.Convert (entity.Text); text = QuoteText (text); } else { // quote the original message text text = QuoteText (entity.Text); } var part = new TextPart (entity.ContentType.MediaSubtype.ToLowerInvariant ()) { Text = text }; Push (part); } protected override void VisitMessagePart (MessagePart entity) { // don't descend into message/rfc822 parts } protected override void VisitMimePart (MimePart entity) { if (isRelated > 0 || !entity.IsAttachment) { var parent = stack.Peek (); parent.Add (entity); } } } ``` ```csharp public static MimeMessage Reply (MimeMessage message, MailboxAddress from, bool replyToAll) { var visitor = new ReplyVisitor (from, replyToAll); visitor.Visit (message); return visitor.Reply; } ``` ### Q: How can I forward a message? There are 2 common ways of forwarding a message: attaching the original message as an attachment and inlining the message body much like replying typically does. Which method you choose is up to you. To forward a message by attaching it as an attachment, you would do something like this: ```csharp public static MimeMessage Forward (MimeMessage original, MailboxAddress from, IEnumerableto) { var message = new MimeMessage (); message.From.Add (from); message.To.AddRange (to); // set the forwarded subject if (!original.Subject?.StartsWith ("FW:", StringComparison.OrdinalIgnoreCase)) message.Subject = "FW: " + (original.Subject ?? string.Empty); else message.Subject = original.Subject; // create the main textual body of the message var text = new TextPart ("plain") { Text = "Here's the forwarded message:" }; // create the message/rfc822 attachment for the original message var rfc822 = new MessagePart { Message = original }; // create a multipart/mixed container for the text body and the forwarded message var multipart = new Multipart ("mixed"); multipart.Add (text); multipart.Add (rfc822); // set the multipart as the body of the message message.Body = multipart; return message; } ``` To forward a message by inlining the original message's text content, you can do something like this: ```csharp public static MimeMessage Forward (MimeMessage original, MailboxAddress from, IEnumerable to) { var message = new MimeMessage (); message.From.Add (from); message.To.AddRange (to); // set the forwarded subject if (!original.Subject?.StartsWith ("FW:", StringComparison.OrdinalIgnoreCase)) message.Subject = "FW: " + (original.Subject ?? string.Empty); else message.Subject = original.Subject; // quote the original message text using (var text = new StringWriter ()) { text.WriteLine (); text.WriteLine ("-------- Original Message --------"); text.WriteLine ("Subject: {0}", original.Subject ?? string.Empty); text.WriteLine ("Date: {0}", DateUtils.FormatDate (original.Date)); text.WriteLine ("From: {0}", original.From); text.WriteLine ("To: {0}", original.To); text.WriteLine (); text.Write (original.TextBody); message.Body = new TextPart ("plain") { Text = text.ToString () }; } return message; } ``` Keep in mind that not all messages will have a `TextBody` available, so you'll have to find a way to handle those cases. ## ImapClient ### Q: How can I get the number of unread messages in a folder? If the folder is open (via [Open](https://www.mimekit.net/docs/html/Overload_MailKit_Net_Imap_ImapFolder_Open.htm)), then the [ImapFolder.Unread](https://www.mimekit.net/docs/html/P_MailKit_MailFolder_Unread.htm) property will be kept up to date (at least as-of the latest command issued to the server). If the folder *isn't* open, then you will need to query the unread state of the folder using the [Status](https://www.mimekit.net/docs/html/M_MailKit_Net_Imap_ImapFolder_Status.htm) method with the appropriate [StatusItems](https://www.mimekit.net/docs/html/T_MailKit_StatusItems.htm) flag(s). For example, to get the total *and* unread counts, you can do this: ```csharp folder.Status (StatusItems.Count | StatusItems.Unread); int total = folder.Count; int unread = folder.Unread; ``` ### Q: How can I search for messages delivered between two dates? The obvious solution is: ```csharp var query = SearchQuery.DeliveredAfter (dateRange.BeginDate) .And (SearchQuery.DeliveredBefore (dateRange.EndDate)); var results = folder.Search (query); ``` However, it has been reported to me that this doesn't work reliably depending on the IMAP server implementation. If you find that this query doesn't get the expected results for your IMAP server, here's another solution that should always work: ```csharp var query = SearchQuery.Not (SearchQuery.DeliveredBefore (dateRange.BeginDate) .Or (SearchQuery.DeliveredAfter (dateRange.EndDate))); var results = folder.Search (query); ``` ### Q: What does "The ImapClient is currently busy processing a command." mean? If you get an InvalidOperationException with the message, "The ImapClient is currently busy processing a command.", it means that you are trying to use the [ImapClient](https://www.mimekit.net/docs/html/T_MailKit_Net_Imap_ImapClient.htm) and/or one of its [ImapFolder](https://www.mimekit.net/docs/html/T_MailKit_Net_Imap_ImapFolder.htm)s from multiple threads. To avoid this situation, you'll need to lock the `SyncRoot` property of the `ImapClient` and `ImapFolder` objects when performing operations on them. For example: ```csharp lock (client.SyncRoot) { client.NoOp (); } ``` Note: Locking the `SyncRoot` is only necessary when using the synchronous API's. All `Async()` method variants already do this locking for you. ### Q: Why do I get InvalidOperationException: "The folder is not currently open."? If you get this exception, it's probably because you thought you had to open the destination folder that you passed as an argument to one of the [CopyTo](https://www.mimekit.net/docs/html/Overload_MailKit_MailFolder_CopyTo.htm) or [MoveTo](https://www.mimekit.net/docs/html/Overload_MailKit_MailFolder_MoveTo.htm) methods. When you opened that destination folder, you also inadvertently closed the source folder which is why you are getting this exception. The IMAP server can only have a single folder open at a time. Whenever you open a folder, you automatically close the previously opened folder. When copying or moving messages from one folder to another, you only need to have the source folder open. ### Q: Why doesn't ImapFolder.MoveTo() move the message out of the source folder? If you look at the source code for the `ImapFolder.MoveTo()` method, what you'll notice is that there are several code paths depending on the features that the IMAP server supports. If the IMAP server supports the `MOVE` extension, then MailKit's `MoveTo()` method will use the `MOVE` command. I suspect that your server does not support the `MOVE` command or you probably wouldn't be seeing what you are seeing. When the IMAP server does not support the `MOVE` command, MailKit has to use the `COPY` command to copy the message(s) to the destination folder. Once the `COPY` command has completed, it will then mark the messages that you asked it to move for deletion by setting the `\Deleted` flag on those messages. If the server supports the `UIDPLUS` extension, then MailKit will attempt to `EXPUNGE` the subset of messages that it just marked for deletion, however, if the `UIDPLUS` extension is not supported by the IMAP server, then it cannot safely expunge just that subset of messages and so it stops there. My guess is that your server supports neither `MOVE` nor `UIDPLUS` and that is why clients like Outlook continue to see the messages in your folder. I believe, however, that Outlook has a setting to show deleted messages with a strikeout (which you probably have disabled). So to answer your question more succinctly: After calling `folder.MoveTo (...);`, if you are confident that the messages marked for deletion should be expunged, call `folder.Expunge ();` ### Q: How can I mark messages as read for IMAP? The way to mark messages as read using the IMAP protocol is to set the `\Seen` flag on the message(s). To do this using MailKit, you will first need to know either the index(es) or the UID(s) of the messages that you would like to set the `\Seen` flag on. Once you have that information, you will want to call one of the [AddFlags](https://www.mimekit.net/docs/html/Overload_MailKit_MailFolder_AddFlags.htm) methods on the `ImapFolder`. For example: ```csharp folder.AddFlags (uids, MessageFlags.Seen, true); ``` To mark messages as unread, you would *remove* the `\Seen` flag, like so: ```csharp folder.RemoveFlags (uids, MessageFlags.Seen, true); ``` ### Q: How can I re-synchronize the cache for an IMAP folder? Assuming your IMAP server does not support the `QRESYNC` extension (which simplifies this procedure a ton), here is some simple code to illustrate how to go about re-synchronizing your cache with the remote IMAP server. ```csharp /// /// Just a simple class to represent the cached information about a message. /// class CachedMessageInfo { public UniqueId UniqueId; public MessageFlags Flags; public HashSetKeywords; public Envelope Envelope; public BodyPart Body; } /// /// Resynchronize the cache with the remote IMAP folder. /// /// The IMAP folder. /// The local cache of message metadata. /// The cached UIDVALIDITY value of the IMAP folder from a previous session. static void ResyncFolder (ImapFolder folder, Listcache, ref uint cachedUidValidity) { IList summaries; // Step 1: Open the folder. // Note: we only need read-only access to update our cache, but depending on // what you plan to do with the folder after resynchronizing, you may want // top open the folder in read-write mode instead. folder.Open (FolderAccess.ReadOnly); if (cache.Count > 0) { if (folder.UidValidity == cachedUidValidity) { // Step 2: Remove messages from our cache that no longer exist on the server. // get the full list of UIDs on the server... var all = folder.Search (SearchQuery.All); // remove any messages from our cache that no longer exist... for (int i = 0; i < cache.Count; i++) { if (!all.Contains (cache[i].UniqueId)) { cache.RemoveAt (i); i--; } } // Step 3: Sync any flag changes for our cached messages. // get a list of known uids... astute observers will note that an easy // optimization to make here would be to merge this loop with the above // loop. var known = new UniqueIdSet (SortOrder.Ascending); for (int i = 0; i < cache.Count; i++) known.Add (cache[i].UniqueId); // fetch the flags for our known messages... summaries = folder.Fetch (known, MessageSummaryItems.Flags); for (int i = 0; i < summaries.Count; i++) { // Note: the indexes should match up with our cache, but it wouldn't // hurt to add error checking to make sure. I'm not bothering to here // for simplicity reasons. cache[i].Flags = summaries[i].Flags.Value; cache[i].Keywords = summaries[i].Keywords; } } else { // The UIDVALIDITY of the folder has changed. This means that our entire // cache is obsolete. We need to clear our cache and start from scratch. cachedUidValidity = folder.UidValidity; cache.Clear (); } } else { // We have nothing cached, so just start from scratch. cachedUidValidity = folder.UidValidity; } // Step 4: Fetch the messages we don't already know about and add them to our cache. summaries = folder.Fetch (cache.Count, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.Flags | MessageSummaryItems.Envelope | MessageSummaryItems.BodyStructure); for (int i = 0; i < summaries.Count; i++) { cache.Add (new CachedMessageInfo { UniqueId = summaries[i].UniqueId, Flags = summaries[i].Flags.Value, Keywords = summaries[i].Keywords, Envelope = summaries[i].Envelope, Body = summaries[i].Body }); } // Tada! Now we are resynchronized with the server! } ``` ### Q: How can I login using a shared mailbox in Office365? ```csharp var result = await GetPublicClientOAuth2CredentialsAsync ("IMAP", "sharedMailboxName@custom-domain.com"); // Note: We always use result.Account.Username instead of `Username` because the user may have selected an alternative account. var oauth2 = new SaslMechanismOAuth2 (result.Account.Username, result.AccessToken); using (var client = new ImapClient ()) { await client.ConnectAsync ("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect); await client.AuthenticateAsync (oauth2); // ... await client.DisconnectAsync (true); } ``` Notes: 1. The `GetPublicClientOAuth2CredentialsAsync()` method used in this example code snippet can be found in the [ExchangeOAuth2.md](ExchangeOAuth2.md#desktop-and-mobile-applications) documentation. 2. Some users have reported that they need to use `"username@custom-domain.com\\sharedMailboxName"` as their username instead of `"sharedMailboxName@custom-domain.com"`. ## SmtpClient ### Q: Why doesn't the message show up in the "Sent Mail" folder after sending it? It seems to be a common misunderstanding that messages sent via SMTP will magically show up in the account's "Sent Mail" folder. In order for the message to show up in the "Sent Mail" folder, you will need to append the message to the "Sent Mail" folder yourself because the SMTP protocol does not support doing this automatically. If the "Sent Mail" folder is a local mbox folder, you'll need to append it like this: ```csharp using (var mbox = File.Open ("C:\\path\\to\\Sent Mail.mbox", FileMode.Append, FileAccess.Write)) { var marker = string.Format ("From MAILER-DAEMON {0}{1}", DateTime.Now.ToString (CultureInfo.InvariantCulture, "ddd MMM d HH:mm:ss yyyy"), Environment.NewLine); var bytes = Encoding.ASCII.GetBytes (marker); // Write the mbox marker bytes. mbox.Write (bytes, 0, bytes.Length); // Write the message, making sure to escape any line that looks like an mbox From-marker. using (var filtered = new FilteredStream (stream)) { filtered.Add (new MboxFromMarker ()); message.WriteTo (filtered); filtered.Flush (); } mbox.Flush (); } ``` If the "Sent Mail" folder exists on an IMAP server, you would need to do something more like this: ```csharp using (var client = new ImapClient ()) { client.Connect ("imap.server.com", 993, SecureSocketOptions.SslOnConnect); client.Authenticate ("username", "password"); IMailFolder sentMail; if (client.Capabilities.HasFlag (ImapCapabilities.SpecialUse)) { sentMail = client.GetFolder (SpecialFolder.Sent); } else { var personal = client.GetFolder (client.PersonalNamespaces[0]); // Note: This assumes that the "Sent Mail" folder lives at the root of the folder hierarchy // and is named "Sent Mail" as opposed to "Sent" or "Sent Items" or any other variation. sentMail = personal.GetSubfolder ("Sent Mail"); } sentMail.Append (message, MessageFlags.Seen); client.Disconnect (true); } ``` ### Q: How can I send email to a SpecifiedPickupDirectory? Based on Microsoft's [referencesource](https://github.com/Microsoft/referencesource/blob/master/System/net/System/Net/mail/SmtpClient.cs#L401), when `SmtpDeliveryMethod.SpecifiedPickupDirectory` is used, the `SmtpClient` saves the message to the specified pickup directory location using a randomly generated filename based on `Guid.NewGuid ().ToString () + ".eml"`, so to achieve the same results with MailKit, you could do something like this: ```csharp public static void SaveToPickupDirectory (MimeMessage message, string pickupDirectory) { do { // Generate a random file name to save the message to. var path = Path.Combine (pickupDirectory, Guid.NewGuid ().ToString () + ".eml"); Stream stream; try { // Attempt to create the new file. stream = File.Open (path, FileMode.CreateNew); } catch (IOException) { // If the file already exists, try again with a new Guid. if (File.Exists (path)) continue; // Otherwise, fail immediately since it probably means that there is // no graceful way to recover from this error. throw; } try { using (stream) { // IIS pickup directories expect the message to be "byte-stuffed" // which means that lines beginning with "." need to be escaped // by adding an extra "." to the beginning of the line. // // Use an SmtpDataFilter "byte-stuff" the message as it is written // to the file stream. This is the same process that an SmtpClient // would use when sending the message in a `DATA` command. using (var filtered = new FilteredStream (stream)) { filtered.Add (new SmtpDataFilter ()); // Make sure to write the message in DOS ( ) format. var options = FormatOptions.Default.Clone (); options.NewLineFormat = NewLineFormat.Dos; message.WriteTo (options, filtered); filtered.Flush (); return; } } } catch { // An exception here probably means that the disk is full. // // Delete the file that was created above so that incomplete files are not // left behind for IIS to send accidentally. File.Delete (path); throw; } } while (true); } ``` ### Q: How can I request a notification when the message is read by the user? The first thing I need to make clear is that requesting a notification does not guarantee that you'll actually get one. In order for you to receive a notification that the message was read by its recipient, the recipient's mail client needs to know how to send such a notification *and* that the user has enabled it to do so. That said, here's how you can request a notification when the recipient reads the message that has been sent: ```csharp // Add the following header to tell the recipient's client that you want to receive a // notification when the message has been read by the user. message.Headers[HeaderId.DispositionNotificationTo] = new MailboxAddress ("My Name", "me@example.com").ToString (true); ``` For more information on this topic, read [rfc3798](https://tools.ietf.org/html/rfc3798). ### Q: How can I process a read receipt notification? A read receipt notification comes in the form of a MIME message with a top-level MIME part with a MIME-type of `multipart/report` that has a `report-type` parameter with a value of `disposition-notification`. You could check for this in code like this: ```csharp var report = message.Body as MultipartReport; if (report != null && report.ReportType.Equals ("disposition-notification", StringComparison.OrdinalIgnoreCase)) { // This is a read receipt notification. } ``` The first part of the `multipart/report` will be a human-readable explanation of the notification. The second part will have a MIME-type of `message/disposition-notification` and be represented by a [MessageDispositionNotification](https://www.mimekit.net/docs/html/T_MimeKit_MessageDispositionNotification.htm). This notification part will contain a list of header-like fields containing information about the message that this notification is for such as the `Original-Message-Id`, `Original-Recipient`, etc. ```csharp var notification = report[1] as MessageDispositionNotification; if (notification != null) { // Get the Message-Id of the message this notification is for... var messageId = notification.Fields["Original-Message-Id"]; } ``` For more information on this topic, read [rfc3798](https://tools.ietf.org/html/rfc3798). ================================================ FILE: GMailOAuth2.md ================================================ # Using OAuth2 With GMail (IMAP, POP3 or SMTP) ## Quick Index * [Setting up OAuth2 for use with Google Mail](#setting-up-oauth2-for-use-with-google-mail) * [Register Your Application with Google](#register-your-application-with-google) * [Obtaining an OAuth2 Client ID and Secret](#obtaining-an-oauth2-client-id-and-secret) * [Authenticating a Desktop App with the OAuth2 Client ID and Secret](#authenticating-a-desktop-app-with-the-oauth2-client-id-and-secret) * [Authenticating an ASP.NET Web App with the OAuth2 Client ID and Secret](#authenticating-an-aspnet-web-app-with-the-oauth2-client-id-and-secret) ## Setting up OAuth2 for use with Google Mail ### Register Your Application with Google Go to [Google's Developer Console](https://cloud.google.com/console). Click the **Select A Project** button in the **Navigation Bar** at the top of the screen.  Click the **New Project** button.  Fill in the name **Project Name**, and if appropriate, select the **Organization** that your program should be associated with. Then click *Create*.  ### Obtaining an OAuth2 Client ID and Secret Click the **☰** symbol, move down to **APIs & Services** and then select **OAuth consent screen**.  Select the **External** radio item and then click **Create**.  Fill in the **Application name** and any other fields that are appropriate for your application and then click **Create**.  Click **+ Create Credentials** and then select **OAuth client ID**.  Select the **Other** radio item in the **Application type** section and then type in a name to use for the OAuth client ID. Once completed, click **Create**.  At this point, you will be presented with a web dialog that will allow you to copy the **Client ID** and **Client Secret** strings into your clipboard to paste them into your program.  ## Authenticating a Desktop App with the OAuth2 Client ID and Secret Now that you have the **Client ID** and **Client Secret** strings, you'll need to plug those values into your application. The following sample code uses the [Google.Apis.Auth](https://www.nuget.org/packages/Google.Apis.Auth/) nuget package for obtaining the access token which will be needed by MailKit to pass on to the GMail server. ```csharp const string GMailAccount = "username@gmail.com"; var clientSecrets = new ClientSecrets { ClientId = "XXX.apps.googleusercontent.com", ClientSecret = "XXX" }; var codeFlow = new GoogleAuthorizationCodeFlow (new GoogleAuthorizationCodeFlow.Initializer { // Cache tokens in ~/.local/share/google-filedatastore/CredentialCacheFolder on Linux/Mac DataStore = new FileDataStore ("CredentialCacheFolder", false), Scopes = new [] { "https://mail.google.com/" }, ClientSecrets = clientSecrets, LoginHint = GMailAccount }); // Note: For a web app, you'll want to use AuthorizationCodeWebApp instead. var codeReceiver = new LocalServerCodeReceiver (); var authCode = new AuthorizationCodeInstalledApp (codeFlow, codeReceiver); var credential = await authCode.AuthorizeAsync (GMailAccount, CancellationToken.None); if (credential.Token.IsStale) await credential.RefreshTokenAsync (CancellationToken.None); var oauth2 = new SaslMechanismOAuthBearer (credential.UserId, credential.Token.AccessToken); using (var client = new ImapClient ()) { await client.ConnectAsync ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect); await client.AuthenticateAsync (oauth2); await client.DisconnectAsync (true); } ``` ## Authenticating an ASP.NET Web App with the OAuth2 Client ID and Secret Now that you have the **Client ID** and **Client Secret** strings, you'll need to plug those values into your application. The following sample code uses the [Google.Apis.Auth](https://www.nuget.org/packages/Google.Apis.Auth/) nuget package for obtaining the access token which will be needed by MailKit to pass on to the GMail server. Add Google Authentication processor to your **Program.cs**. ```csharp builder.Services.AddAuthentication (options => { // This forces challenge results to be handled by Google OpenID Handler, so there's no // need to add an AccountController that emits challenges for Login. options.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme; // This forces forbid results to be handled by Google OpenID Handler, which checks if // extra scopes are required and does automatic incremental auth. options.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme; // Default scheme that will handle everything else. // Once a user is authenticated, the OAuth2 token info is stored in cookies. options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie (options => { options.ExpireTimeSpan = TimeSpan.FromMinutes (5); }) .AddGoogleOpenIdConnect (options => { var secrets = GoogleClientSecrets.FromFile ("client_secret.json").Secrets; options.ClientId = secrets.ClientId; options.ClientSecret = secrets.ClientSecret; }); ``` Ensure that you are using Authorization and HttpsRedirection in your **Program.cs**: ```csharp app.UseHttpsRedirection (); app.UseStaticFiles (); app.UseRouting (); app.UseAuthentication (); app.UseAuthorization (); ``` Now, using the **GoogleScopedAuthorizeAttribute**, you can request scopes saved in a library as constants and request tokens for these scopes. ```csharp [GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)] public async Task AuthenticateAsync ([FromServices] IGoogleAuthProvider auth) { GoogleCredential? googleCred = await auth.GetCredentialAsync (); string token = await googleCred.UnderlyingCredential.GetAccessTokenForRequestAsync (); var oauth2 = new SaslMechanismOAuthBearer ("UserEmail", token); using var emailClient = new ImapClient (); await emailClient.ConnectAsync ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect); await emailClient.AuthenticateAsync (oauth2); await emailClient.DisconnectAsync (true); } ``` All of that and more has been described in Google's [OAuth 2.0](https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web-applications-aspnet-mvc) documentation. However, be careful since [Asp.Net MVC](https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web-applications-asp.net-mvc) does not work for Asp.Net Core. ================================================ FILE: LICENSE ================================================ MIT License Copyright (C) 2013-2026 .NET Foundation and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MailKit/AccessControl.cs ================================================ // // AccessControl.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections.Generic; namespace MailKit { /// /// An Access Control. /// ////// An Access Control is a set of permissions available for a particular identity, /// controlling whether or not that identity has the ability to perform various tasks. /// ////// public class AccessControl { ///////// Initializes a new instance of the ///class. /// /// Creates a new /// The identifier name. /// The access rights. ///with the given name and /// access rights. /// /// public AccessControl (string name, IEnumerable/// is . -or- ////// is . rights) { if (name == null) throw new ArgumentNullException (nameof (name)); Rights = new AccessRights (rights); Name = name; } /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The identifier name. /// The access rights. ///with the given name and /// access rights. /// /// public AccessControl (string name, string rights) { if (name == null) throw new ArgumentNullException (nameof (name)); Rights = new AccessRights (rights); Name = name; } ////// is . -or- ////// is . /// Initializes a new instance of the ///class. /// /// Creates a new /// The identifier name. ///with the given name and no /// access rights. /// /// public AccessControl (string name) { if (name == null) throw new ArgumentNullException (nameof (name)); Rights = new AccessRights (); Name = name; } ///is . /// /// The identifier name for the access control. /// ////// The identifier name for the access control. /// ////// //////The identifier name. public string Name { get; private set; } ////// Get the access rights. /// ////// Gets the access rights. /// ////// //////The access rights. public AccessRights Rights { get; private set; } } } ================================================ FILE: MailKit/AccessControlList.cs ================================================ // // AccessControlList.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System.Collections.Generic; namespace MailKit { /// /// An Access Control List (ACL) /// ////// An Access Control List (ACL) is a list of access controls defining the permissions /// various identities have available. /// ////// public class AccessControlList : List///{ /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The list of access controls. ///. /// /// public AccessControlList (IEnumerableis . /// controls) : base (controls) { } /// /// Initializes a new instance of the ///class. /// /// Creates a new public AccessControlList () { } } } ================================================ FILE: MailKit/AccessRight.cs ================================================ // // AccessRight.cs // // Author: Jeffrey Stedfast. /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// An individual Access Right to be used with ACLs. /// ////// public readonly struct AccessRight : IEquatableAn individual Access Right meant to be used with /// ///. For more information on what rights are available, /// see https://tools.ietf.org/html/rfc4314#section-2.1 /// ///{ /// /// The access right for folder lookups. /// ////// Allows the public static readonly AccessRight LookupFolder = new AccessRight ('l'); ///to be visible when listing folders. /// /// The access right for opening a folder and getting the status. /// ////// Provides access for opening and getting the status of the folder. /// public static readonly AccessRight OpenFolder = new AccessRight ('r'); ////// The access right for adding or removing the Seen flag on messages in the folder. /// ////// Provides access to add or remove the public static readonly AccessRight SetMessageSeen = new AccessRight ('s'); ///flag on messages within the /// . /// /// The access right for adding or removing flags (other than Seen and Deleted) /// on messages in a folder. /// ////// Provides access to add or remove the public static readonly AccessRight SetMessageFlags = new AccessRight ('w'); ///on messages /// (other than and /// ) within the folder. /// /// The access right allowing messages to be appended or copied into the folder. /// ////// Provides access to append or copy messages into the folder. /// public static readonly AccessRight AppendMessages = new AccessRight ('i'); ////// The access right allowing subfolders to be created. /// ////// Provides access to create subfolders. /// public static readonly AccessRight CreateFolder = new AccessRight ('k'); ////// The access right for deleting a folder and/or its subfolders. /// ////// Provides access to delete the folder and/or any subfolders. /// public static readonly AccessRight DeleteFolder = new AccessRight ('x'); ////// The access right for adding or removing the Deleted flag to messages within a folder. /// ////// Provides access to add or remove the public static readonly AccessRight SetMessageDeleted = new AccessRight ('t'); ///flag from /// messages within the folder. It also provides access for setting the /// flag when appending a message to a folder. /// /// The access right for expunging deleted messages in a folder. /// ////// Provides access to expunge deleted messages in a folder. /// public static readonly AccessRight ExpungeFolder = new AccessRight ('e'); ////// The access right for administering the ACLs of a folder. /// ////// Provides administrative access to change the ACLs for the folder. /// public static readonly AccessRight Administer = new AccessRight ('a'); ////// The character representing the particular access right. /// ////// Represents the character value of the access right. /// public readonly char Right; ////// Initializes a new instance of the ///struct. /// /// Creates a new /// The access right. public AccessRight (char right) { Right = right; } #region IEquatable implementation ///struct. /// /// Determines whether the specified ///is equal to the current . /// /// Determines whether the specified /// Theis equal to the current . /// to compare with the current . /// public bool Equals (AccessRight other) { return other.Right == Right; } #endregion /// if the specified is equal to the current /// ; otherwise, . /// Determines whether two access rights are equal. /// ////// Determines whether two access rights are equal. /// ////// The first access right to compare. /// The second access right to compare. public static bool operator == (AccessRight right1, AccessRight right2) { return right1.Right == right2.Right; } /// if and are equal; otherwise, . /// Determines whether two access rights are not equal. /// ////// Determines whether two access rights are not equal. /// ////// The first access right to compare. /// The second access right to compare. public static bool operator != (AccessRight right1, AccessRight right2) { return right1.Right != right2.Right; } /// if and are not equal; otherwise, . /// Determines whether the specified ///is equal to the current . /// /// Determines whether the specified /// Theis equal to the current . /// to compare with the current . /// public override bool Equals (object? obj) { return obj is AccessRight right && right.Right == Right; } /// if the specified is equal to the current ; /// otherwise, . /// Serves as a hash function for a ///object. /// /// Serves as a hash function for a ///object. /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table. public override int GetHashCode () { return Right.GetHashCode (); } ////// Returns a ///that represents the current . /// /// Returns a ///that represents the current . /// A public override string ToString () { return Right.ToString (); } } } ================================================ FILE: MailKit/AccessRights.cs ================================================ // // AccessRights.cs // // Author: Jeffrey Stedfastthat represents the current . // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections; using System.Collections.Generic; namespace MailKit { /// /// A set of access rights. /// ////// The set of access rights for a particular identity. /// public class AccessRights : ICollection{ readonly List list = new List (); /// /// Initializes a new instance of the ///class. /// /// Creates a new set of access rights. /// /// The access rights. ////// public AccessRights (IEnumerableis . /// rights) { AddRange (rights); } /// /// Initializes a new instance of the ///class. /// /// Creates a new set of access rights. /// /// The access rights. ////// public AccessRights (string rights) { AddRange (rights); } ///is . /// /// Initializes a new instance of the ///class. /// /// Creates an empty set of access rights. /// public AccessRights () { } ////// Get the number of access rights in the collection. /// ////// Gets the number of access rights in the collection. /// ///The count. public int Count { get { return list.Count; } } ////// Get whether or not this set of access rights is read only. /// ////// Gets whether or not this set of access rights is read only. /// ///public bool IsReadOnly { get { return false; } } /// if this collection is read only; otherwise, . /// Add the specified access right. /// ////// Adds the specified access right if it is not already included. /// /// The access right. void ICollection.Add (AccessRight right) { Add (right); } /// /// Add the specified access right. /// ////// Adds the specified access right if it is not already included. /// ////// The access right. public bool Add (AccessRight right) { if (list.Contains (right)) return false; list.Add (right); return true; } /// if the right was added; otherwise, . /// Add the specified right. /// ////// Adds the right specified by the given character. /// ////// The right. public bool Add (char right) { return Add (new AccessRight (right)); } /// if the right was added; otherwise, . /// Add the rights specified by the characters in the given string. /// ////// Adds the rights specified by the characters in the given string. /// /// The rights. ////// public void AddRange (string rights) { if (rights == null) throw new ArgumentNullException (nameof (rights)); for (int i = 0; i < rights.Length; i++) Add (new AccessRight (rights[i])); } ///is . /// /// Add the range of specified rights. /// ////// Adds the range of specified rights. /// /// The rights. ////// public void AddRange (IEnumerableis . /// rights) { if (rights == null) throw new ArgumentNullException (nameof (rights)); foreach (var right in rights) Add (right); } /// /// Clears the access rights. /// ////// Removes all of the access rights. /// public void Clear () { list.Clear (); } ////// Checks if the set of access rights contains the specified right. /// ////// Determines whether or not the set of access rights already contains the specified right /// ////// The access right. public bool Contains (AccessRight right) { return list.Contains (right); } /// if the specified right exists; otherwise, . /// Copies all of the access rights to the specified array. /// ////// Copies all of the access rights into the array, /// starting at the specified array index. /// /// The array. /// The array index. ////// ///is . /// /// public void CopyTo (AccessRight[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException (nameof (array)); if (arrayIndex < 0 || arrayIndex + Count > array.Length) throw new ArgumentOutOfRangeException (nameof (arrayIndex)); list.CopyTo (array, arrayIndex); } ///is out of range. /// /// Removes the specified access right. /// ////// Removes the specified access right. /// ////// The access right. public bool Remove (AccessRight right) { return list.Remove (right); } /// if the access right was removed; otherwise, . /// Get the access right at the specified index. /// ////// Gets the access right at the specified index. /// ///The access right at the specified index. /// The index. ////// public AccessRight this [int index] { get { if (index < 0 || index >= list.Count) throw new ArgumentOutOfRangeException (nameof (index)); return list[index]; } } #region IEnumerable implementation ///is out of range. /// /// Get the access rights enumerator. /// ////// Gets the access rights enumerator. /// ///The enumerator. public IEnumeratorGetEnumerator () { return list.GetEnumerator (); } #endregion #region IEnumerable implementation /// /// Get the access rights enumerator. /// ////// Gets the access rights enumerator. /// ///The enumerator. IEnumerator IEnumerable.GetEnumerator () { return list.GetEnumerator (); } #endregion ////// Return a ///that represents the current . /// /// Returns a ///that represents the current . /// A public override string ToString () { var rights = new char[list.Count]; for (int i = 0; i < list.Count; i++) rights[i] = list[i].Right; return new string (rights); } } } ================================================ FILE: MailKit/AlertEventArgs.cs ================================================ // // AlertEventArgs.cs // // Author: Jeffrey Stedfastthat represents the current . // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// Alert event arguments. /// ////// Some public class AlertEventArgs : EventArgs { ///implementations, such as /// , will emit Alert /// events when they receive alert messages from the server. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The alert message. ///. /// /// public AlertEventArgs (string message) { if (message == null) throw new ArgumentNullException (nameof (message)); Message = message; } ///is . /// /// Gets the alert message. /// ////// The alert message will be the exact message received from the server. /// ///The alert message. public string Message { get; private set; } } } ================================================ FILE: MailKit/Annotation.cs ================================================ // // Annotation.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections.Generic; namespace MailKit { /// /// An annotation. /// ////// public class Annotation { ///An annotation. ///For more information about annotations, see /// rfc5257. ////// Initializes a new instance of the ///class. /// /// Creates a new /// The annotation entry. ///. /// /// public Annotation (AnnotationEntry entry) { if (entry is null) throw new ArgumentNullException (nameof (entry)); Properties = new Dictionaryis . /// (); Entry = entry; } /// /// Get the annotation tag. /// ////// Gets the annotation tag. /// ///The annotation tag. public AnnotationEntry Entry { get; private set; } ////// Get the annotation properties. /// ////// Gets the annotation properties. /// ///The annotation properties. public DictionaryProperties { get; private set; } } } ================================================ FILE: MailKit/AnnotationAccess.cs ================================================ // // AnnotationAccess.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // namespace MailKit { /// /// An annotation access level. /// ////// public enum AnnotationAccess { ///An annotation access level. ///For more information about annotations, see /// rfc5257. ////// Annotations are not supported. /// None, ////// Annotations are read-only. /// ReadOnly, ////// Annotations are read-write. /// ReadWrite } } ================================================ FILE: MailKit/AnnotationAttribute.cs ================================================ // // AnnotationAttribute.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// An annotation attribute. /// ////// public class AnnotationAttribute : IEquatableAn annotation attribute. ///For more information about annotations, see /// rfc5257. ///{ static readonly char[] Wildcards = { '*', '%' }; /// /// The annotation value. /// ////// Used to get or set both the private and shared values of an annotation. /// public static readonly AnnotationAttribute Value = new AnnotationAttribute ("value", AnnotationScope.Both); ////// The shared annotation value. /// ////// Used to get or set the shared value of an annotation. /// public static readonly AnnotationAttribute SharedValue = new AnnotationAttribute ("value", AnnotationScope.Shared); ////// The private annotation value. /// ////// Used to get or set the private value of an annotation. /// public static readonly AnnotationAttribute PrivateValue = new AnnotationAttribute ("value", AnnotationScope.Private); ////// The size of an annotation value. /// ////// Used to get the size of the both the private and shared annotation values. /// public static readonly AnnotationAttribute Size = new AnnotationAttribute ("size", AnnotationScope.Both); ////// The size of a shared annotation value. /// ////// Used to get the size of a shared annotation value. /// public static readonly AnnotationAttribute SharedSize = new AnnotationAttribute ("size", AnnotationScope.Shared); ////// The size of a private annotation value. /// ////// Used to get the size of a private annotation value. /// public static readonly AnnotationAttribute PrivateSize = new AnnotationAttribute ("size", AnnotationScope.Private); AnnotationAttribute (string name, AnnotationScope scope) { switch (scope) { case AnnotationScope.Shared: Specifier = string.Format ("{0}.shared", name); break; case AnnotationScope.Private: Specifier = string.Format ("{0}.priv", name); break; default: Specifier = name; break; } Scope = scope; Name = name; } ////// Initializes a new instance of the ///class. /// /// Creates a new /// The annotation attribute specifier. ///. /// /// ///is . /// /// public AnnotationAttribute (string specifier) { if (specifier == null) throw new ArgumentNullException (nameof (specifier)); if (specifier.Length == 0) throw new ArgumentException ("Annotation attribute specifiers cannot be empty.", nameof (specifier)); // TODO: improve validation if (specifier.IndexOfAny (Wildcards) != -1) throw new ArgumentException ("Annotation attribute specifiers cannot contain '*' or '%'.", nameof (specifier)); Specifier = specifier; if (specifier.EndsWith (".shared", StringComparison.Ordinal)) { Name = specifier.Substring (0, specifier.Length - ".shared".Length); Scope = AnnotationScope.Shared; } else if (specifier.EndsWith (".priv", StringComparison.Ordinal)) { Name = specifier.Substring (0, specifier.Length - ".priv".Length); Scope = AnnotationScope.Private; } else { Scope = AnnotationScope.Both; Name = specifier; } } ///contains illegal characters. /// /// Get the name of the annotation attribute. /// ////// Gets the name of the annotation attribute. /// ///The name of the annotation attribute. public string Name { get; private set; } ////// Get the scope of the annotation attribute. /// ////// Gets the scope of the annotation attribute. /// ///The scope of the annotation attribute. public AnnotationScope Scope { get; private set; } ////// Get the annotation attribute specifier. /// ////// Gets the annotation attribute specifier. /// ///The annotation attribute specifier. public string Specifier { get; private set; } #region IEquatable implementation ////// Determines whether the specified ///is equal to the current . /// /// Determines whether the specified /// Theis equal to the current . /// to compare with the current . /// public bool Equals (AnnotationAttribute? other) { return other?.Specifier == Specifier; } #endregion /// if the specified is equal to the current /// ; otherwise, . /// Determines whether two annotation attributes are equal. /// ////// Determines whether two annotation attributes are equal. /// ////// The first annotation attribute to compare. /// The second annotation attribute to compare. public static bool operator == (AnnotationAttribute attr1, AnnotationAttribute attr2) { return attr1?.Specifier == attr2?.Specifier; } /// if and are equal; otherwise, . /// Determines whether two annotation attributes are not equal. /// ////// Determines whether two annotation attributes are not equal. /// ////// The first annotation attribute to compare. /// The second annotation attribute to compare. public static bool operator != (AnnotationAttribute attr1, AnnotationAttribute attr2) { return attr1?.Specifier != attr2?.Specifier; } /// if and are not equal; otherwise, . /// Determine whether the specified ///is equal to the current . /// /// Determines whether the specified /// Theis equal to the current . /// to compare with the current . /// public override bool Equals (object? obj) { return obj is AnnotationAttribute attribute && attribute.Specifier == Specifier; } /// if the specified is equal to the current /// ; otherwise, . /// Serves as a hash function for a ///object. /// /// Serves as a hash function for a ///object. /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table. public override int GetHashCode () { return Specifier.GetHashCode (); } ////// Returns a ///that represents the current . /// /// Returns a ///that represents the current . /// A public override string ToString () { return Specifier; } } } ================================================ FILE: MailKit/AnnotationEntry.cs ================================================ // // AnnotationEntry.cs // // Author: Jeffrey Stedfastthat represents the current . // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// An annotation entry. /// ////// public class AnnotationEntry : IEquatableAn annotation entry. ///For more information about annotations, see /// rfc5257. ///{ /// /// An annotation entry for a comment on a message. /// ////// Used to get or set a comment on a message. /// public static readonly AnnotationEntry Comment = new AnnotationEntry ("/comment", AnnotationScope.Both); ////// An annotation entry for a private comment on a message. /// ////// Used to get or set a private comment on a message. /// public static readonly AnnotationEntry PrivateComment = new AnnotationEntry ("/comment", AnnotationScope.Private); ////// An annotation entry for a shared comment on a message. /// ////// Used to get or set a shared comment on a message. /// public static readonly AnnotationEntry SharedComment = new AnnotationEntry ("/comment", AnnotationScope.Shared); ////// An annotation entry for flags on a message. /// ////// Used to get or set flags on a message. /// public static readonly AnnotationEntry Flags = new AnnotationEntry ("/flags", AnnotationScope.Both); ////// An annotation entry for private flags on a message. /// ////// Used to get or set private flags on a message. /// public static readonly AnnotationEntry PrivateFlags = new AnnotationEntry ("/flags", AnnotationScope.Private); ////// Aa annotation entry for shared flags on a message. /// ////// Used to get or set shared flags on a message. /// public static readonly AnnotationEntry SharedFlags = new AnnotationEntry ("/flags", AnnotationScope.Shared); ////// An annotation entry for an alternate subject on a message. /// ////// Used to get or set an alternate subject on a message. /// public static readonly AnnotationEntry AltSubject = new AnnotationEntry ("/altsubject", AnnotationScope.Both); ////// An annotation entry for a private alternate subject on a message. /// ////// Used to get or set a private alternate subject on a message. /// public static readonly AnnotationEntry PrivateAltSubject = new AnnotationEntry ("/altsubject", AnnotationScope.Private); ////// An annotation entry for a shared alternate subject on a message. /// ////// Used to get or set a shared alternate subject on a message. /// public static readonly AnnotationEntry SharedAltSubject = new AnnotationEntry ("/altsubject", AnnotationScope.Shared); static void ValidatePath (string path) { if (path == null) throw new ArgumentNullException (nameof (path)); if (path.Length == 0) throw new ArgumentException ("Annotation entry paths cannot be empty.", nameof (path)); if (path[0] != '/' && path[0] != '*' && path[0] != '%') throw new ArgumentException ("Annotation entry paths must begin with '/'.", nameof (path)); if (path.Length > 1 && path[1] >= '0' && path[1] <= '9') throw new ArgumentException ("Annotation entry paths must not include a part-specifier.", nameof (path)); if (path == "*" || path == "%") return; char pc = path[0]; for (int i = 1; i < path.Length; i++) { char c = path[i]; if (c > 127) throw new ArgumentException ($"Invalid character in annotation entry path: '{c}'.", nameof (path)); if (c >= '0' && c <= '9' && pc == '/') throw new ArgumentException ("Invalid annotation entry path.", nameof (path)); if ((pc == '/' || pc == '.') && (c == '/' || c == '.')) throw new ArgumentException ("Invalid annotation entry path.", nameof (path)); pc = c; } int endIndex = path.Length - 1; if (path[endIndex] == '/') throw new ArgumentException ("Annotation entry paths must not end with '/'.", nameof (path)); if (path[endIndex] == '.') throw new ArgumentException ("Annotation entry paths must not end with '.'.", nameof (path)); } static void ValidatePartSpecifier (string partSpecifier) { if (partSpecifier == null) throw new ArgumentNullException (nameof (partSpecifier)); char pc = '\0'; for (int i = 0; i < partSpecifier.Length; i++) { char c = partSpecifier[i]; if (!((c >= '0' && c <= '9') || c == '.') || (c == '.' && (pc == '.' || pc == '\0'))) throw new ArgumentException ("Invalid part-specifier.", nameof (partSpecifier)); pc = c; } if (pc == '.') throw new ArgumentException ("Invalid part-specifier.", nameof (partSpecifier)); } AnnotationEntry (string? partSpecifier, string entry, string path, AnnotationScope scope) { PartSpecifier = partSpecifier; Entry = entry; Path = path; Scope = scope; } ////// Initializes a new instance of the ///struct. /// /// Creates a new /// The annotation entry path. /// The scope of the annotation. ///. /// /// ///is . /// /// public AnnotationEntry (string path, AnnotationScope scope = AnnotationScope.Both) { ValidatePath (path); switch (scope) { case AnnotationScope.Private: Entry = path + ".priv"; break; case AnnotationScope.Shared: Entry = path + ".shared"; break; default: Entry = path; break; } PartSpecifier = null; Path = path; Scope = scope; } ///is invalid. /// /// Initializes a new instance of the ///struct. /// /// Creates a new /// The part-specifier of the body part of the message. /// The annotation entry path. /// The scope of the annotation. ///for an individual body part of a message. /// /// ////// is . -or- ////// is . /// public AnnotationEntry (string partSpecifier, string path, AnnotationScope scope = AnnotationScope.Both) { ValidatePartSpecifier (partSpecifier); ValidatePath (path); switch (scope) { case AnnotationScope.Private: Entry = string.Format ("/{0}{1}.priv", partSpecifier, path); break; case AnnotationScope.Shared: Entry = string.Format ("/{0}{1}.shared", partSpecifier, path); break; default: Entry = string.Format ("/{0}{1}", partSpecifier, path); break; } PartSpecifier = partSpecifier; Path = path; Scope = scope; } ////// is invalid. -or- ////// is invalid. /// Initializes a new instance of the ///struct. /// /// Creates a new /// The body part of the message. /// The annotation entry path. /// The scope of the annotation. ///for an individual body part of a message. /// /// ////// is . -or- ////// is . /// public AnnotationEntry (BodyPart part, string path, AnnotationScope scope = AnnotationScope.Both) { if (part == null) throw new ArgumentNullException (nameof (part)); ValidatePath (path); switch (scope) { case AnnotationScope.Private: Entry = string.Format ("/{0}{1}.priv", part.PartSpecifier, path); break; case AnnotationScope.Shared: Entry = string.Format ("/{0}{1}.shared", part.PartSpecifier, path); break; default: Entry = string.Format ("/{0}{1}", part.PartSpecifier, path); break; } PartSpecifier = part.PartSpecifier; Path = path; Scope = scope; } ///is invalid. /// /// Get the annotation entry specifier. /// ////// Gets the annotation entry specifier. /// ///The annotation entry specifier. public string Entry { get; private set; } ////// Get the part-specifier component of the annotation entry. /// ////// Gets the part-specifier component of the annotation entry. /// ///The part-specifier. public string? PartSpecifier { get; private set; } ////// Get the path component of the annotation entry. /// ////// Gets the path component of the annotation entry. /// ///The path. public string Path { get; private set; } ////// Get the scope of the annotation. /// ////// Gets the scope of the annotation. /// ///The scope. public AnnotationScope Scope { get; private set; } #region IEquatable implementation ////// Determines whether the specified ///is equal to the current . /// /// Determines whether the specified /// Theis equal to the current . /// to compare with the current . /// public bool Equals (AnnotationEntry? other) { return other?.Entry == Entry; } #endregion /// if the specified is equal to the current /// ; otherwise, . /// Determines whether two annotation entries are equal. /// ////// Determines whether two annotation entries are equal. /// ////// The first annotation entry to compare. /// The second annotation entry to compare. public static bool operator == (AnnotationEntry entry1, AnnotationEntry entry2) { return entry1?.Entry == entry2?.Entry; } /// if and are equal; otherwise, . /// Determines whether two annotation entries are not equal. /// ////// Determines whether two annotation entries are not equal. /// ////// The first annotation entry to compare. /// The second annotation entry to compare. public static bool operator != (AnnotationEntry entry1, AnnotationEntry entry2) { return entry1?.Entry != entry2?.Entry; } /// if and are not equal; otherwise, . /// Determine whether the specified ///is equal to the current . /// /// Determines whether the specified /// Theis equal to the current . /// to compare with the current . /// public override bool Equals (object? obj) { return obj is AnnotationEntry entry && entry.Entry == Entry; } /// if the specified is equal to the current /// ; otherwise, . /// Serves as a hash function for a ///object. /// /// Serves as a hash function for a ///object. /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table. public override int GetHashCode () { return Entry.GetHashCode (); } ////// Returns a ///that represents the current . /// /// Returns a ///that represents the current . /// A public override string ToString () { return Entry; } ///that represents the current . /// Parse an annotation entry. /// ////// Parses an annotation entry. /// /// The annotation entry. ///The parsed annotation entry. ////// ///is . /// /// public static AnnotationEntry Parse (string entry) { if (entry == null) throw new ArgumentNullException (nameof (entry)); if (entry.Length == 0) throw new FormatException ("An annotation entry cannot be empty."); if (entry[0] != '/' && entry[0] != '*' && entry[0] != '%') throw new FormatException ("An annotation entry must begin with a '/' character."); var scope = AnnotationScope.Both; int startIndex = 0, endIndex; string? partSpecifier = null; var component = 0; var pc = entry[0]; string path; for (int i = 1; i < entry.Length; i++) { char c = entry[i]; if (c >= '0' && c <= '9' && pc == '/') { if (component > 0) throw new FormatException ("Invalid annotation entry."); startIndex = i; endIndex = i + 1; pc = c; while (endIndex < entry.Length) { c = entry[endIndex]; if (c == '/') { if (pc == '.') throw new FormatException ("Invalid part-specifier in annotation entry."); break; } if (!(c >= '0' && c <= '9') && c != '.') throw new FormatException ($"Invalid character in part-specifier: '{c}'."); if (c == '.' && pc == '.') throw new FormatException ("Invalid part-specifier in annotation entry."); endIndex++; pc = c; } if (endIndex >= entry.Length) throw new FormatException ("Incomplete part-specifier in annotation entry."); partSpecifier = entry.Substring (startIndex, endIndex - startIndex); i = startIndex = endIndex; component++; } else if (c == '/' || c == '.') { if (pc == '/' || pc == '.') throw new FormatException ("Invalid annotation entry path."); if (c == '/') component++; } else if (c > 127) { throw new FormatException ($"Invalid character in annotation entry path: '{c}'."); } pc = c; } if (pc == '/' || pc == '.') throw new FormatException ("Invalid annotation entry path."); if (entry.EndsWith (".shared", StringComparison.Ordinal)) { endIndex = entry.Length - ".shared".Length; scope = AnnotationScope.Shared; } else if (entry.EndsWith (".priv", StringComparison.Ordinal)) { endIndex = entry.Length - ".priv".Length; scope = AnnotationScope.Private; } else { endIndex = entry.Length; } path = entry.Substring (startIndex, endIndex - startIndex); return new AnnotationEntry (partSpecifier, entry, path, scope); } internal static AnnotationEntry Create (string entry) { switch (entry) { case "/comment": return Comment; case "/comment.priv": return PrivateComment; case "/comment.shared": return SharedComment; case "/flags": return Flags; case "/flags.priv": return PrivateFlags; case "/flags.shared": return SharedFlags; case "/altsubject": return AltSubject; case "/altsubject.priv": return PrivateAltSubject; case "/altsubject.shared": return SharedAltSubject; default: return Parse (entry); } } } } ================================================ FILE: MailKit/AnnotationScope.cs ================================================ // // AnnotationScope.cs // // Author: Jeffrey Stedfastdoes not conform to the annotation entry syntax. /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// The scope of an annotation. /// ////// [Flags] public enum AnnotationScope { ///Represents the scope of an annotation. ///For more information about annotations, see /// rfc5257. ////// No scopes. /// None, ////// The private annotation scope. /// Private, ////// The shared annotation scope. /// Shared, ////// Both private and shared scopes. /// Both = Private | Shared } } ================================================ FILE: MailKit/AnnotationsChangedEventArgs.cs ================================================ // // AnnotationsChangedEventArgs.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Linq; using System.Collections.Generic; using System.Collections.ObjectModel; namespace MailKit { /// /// Event args used when an annotation changes. /// ////// Event args used when an annotation changes. /// public class AnnotationsChangedEventArgs : MessageEventArgs { ////// Initializes a new instance of the ///class. /// /// Creates a new /// The message index. /// The annotations that changed. ///. /// /// public AnnotationsChangedEventArgs (int index, IEnumerableis . /// annotations) : base (index) { if (annotations == null) throw new ArgumentNullException (nameof (annotations)); Annotations = new ReadOnlyCollection (annotations.ToArray ()); } /// /// Get the annotations that changed. /// ////// Gets the annotations that changed. /// ///The annotation. public IListAnnotations { get; internal set; } /// /// Gets the updated mod-sequence value of the message, if available. /// ////// Gets the updated mod-sequence value of the message, if available. /// ///The mod-sequence value. public ulong? ModSeq { get; internal set; } } } ================================================ FILE: MailKit/AppendRequest.cs ================================================ // // AppendRequest.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections.Generic; using MimeKit; namespace MailKit { /// /// A request for appending a message to a folder. /// ////// A request for appending a message to a folder. /// public class AppendRequest : IAppendRequest { ////// Initializes a new instance of the ///class. /// /// Creates a new /// The message. /// The message flags. ///. /// /// public AppendRequest (MimeMessage message, MessageFlags flags = MessageFlags.None) { if (message == null) throw new ArgumentNullException (nameof (message)); Message = message; Flags = flags; } ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The message. /// The message flags. /// The message keywords. ///. /// /// public AppendRequest (MimeMessage message, MessageFlags flags, IEnumerable/// is . -or- ////// is . keywords) { if (message == null) throw new ArgumentNullException (nameof (message)); if (keywords == null) throw new ArgumentNullException (nameof (keywords)); Keywords = keywords as ISet ?? new HashSet (keywords); Message = message; Flags = flags; } /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The message. /// The message flags. /// The internal date of the message. ///. /// /// public AppendRequest (MimeMessage message, MessageFlags flags, DateTimeOffset internalDate) { if (message == null) throw new ArgumentNullException (nameof (message)); Message = message; Flags = flags; InternalDate = internalDate; } ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The message. /// The message flags. /// The message keywords. /// The internal date of the message. ///. /// /// public AppendRequest (MimeMessage message, MessageFlags flags, IEnumerable/// is . -or- ////// is . keywords, DateTimeOffset internalDate) { if (message == null) throw new ArgumentNullException (nameof (message)); if (keywords == null) throw new ArgumentNullException (nameof (keywords)); Keywords = keywords as ISet ?? new HashSet (keywords); Message = message; Flags = flags; InternalDate = internalDate; } /// /// Get the message that should be appended to the folder. /// ////// Gets the message that should be appended to the folder. /// ///The message. public MimeMessage Message { get; private set; } ////// Get or set the message flags that should be set on the message. /// ////// Gets or sets the message flags that should be set on the message. /// ///The message flags. public MessageFlags Flags { get; set; } ////// Get or set the keywords that should be set on the message. /// ////// Gets or sets the keywords that should be set on the message. /// ///The keywords. public ISet? Keywords { get; set; } /// /// Get or set the timestamp that should be used by folder as the ///. /// /// Gets or sets the timestamp that should be used by folder as the ///. /// The date and time to use for the INTERNALDATE or public DateTimeOffset? InternalDate { get; set; } ///if it should be left up to the folder to decide. /// Get or set the list of annotations that should be set on the message. /// ////// ///Gets or sets the list of annotations that should be set on the message. ////// ///This feature is not supported by all folders. ///Use ///with the enum value /// to determine if this feature is supported. The list of annotations. public IList? Annotations { get; set; } /// /// Get or set the transfer progress reporting mechanism. /// ////// Gets or sets the transfer progress reporting mechanism. /// ///The transfer progress mechanism. public ITransferProgress? TransferProgress { get; set; } } } ================================================ FILE: MailKit/AuthenticatedEventArgs.cs ================================================ // // AuthenticatedEventArgs.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// Authenticated event arguments. /// ////// Some servers, such as GMail IMAP, will send some free-form text in /// the response to a successful login. /// public class AuthenticatedEventArgs : EventArgs { ////// Initializes a new instance of the ///class. /// /// Creates a new /// The free-form text. ///. /// /// public AuthenticatedEventArgs (string message) { if (message == null) throw new ArgumentNullException (nameof (message)); Message = message; } ///is . /// /// Get the free-form text sent by the server. /// ////// Gets the free-form text sent by the server. /// ///The free-form text sent by the server. public string Message { get; private set; } } } ================================================ FILE: MailKit/BodyPart.cs ================================================ // // BodyPart.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Text; using System.Globalization; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using MimeKit; using MimeKit.Utils; namespace MailKit { /// /// An abstract body part of a message. /// ////// Each body part will actually be a ///, /// , , or /// . /// /// public abstract class BodyPart { ///////// Initializes a new instance of the ///class. /// /// Creates a new [Obsolete ("Use BodyPart (ContentType, string) instead.")] protected BodyPart () { ContentType = new ContentType ("application", "octet-stream"); PartSpecifier = string.Empty; } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The content type. /// The part specifier. ///. /// /// protected BodyPart (ContentType contentType, string partSpecifier) { if (contentType == null) throw new ArgumentNullException (nameof (contentType)); if (partSpecifier == null) throw new ArgumentNullException (nameof (partSpecifier)); ContentType = contentType; PartSpecifier = partSpecifier; } ////// is . -or- ////// is . /// Gets the Content-Type of the body part. /// ////// Gets the Content-Type of the body part. /// ///The content type. public ContentType ContentType { get; set; } ////// Gets the part specifier. /// ////// Gets the part specifier. /// ////// //////The part specifier. public string PartSpecifier { get; set; } ////// Dispatches to the specific visit method for this MIME body part. /// ////// This default implementation for /// The visitor. ///nodes /// calls . Override this /// method to call into a more specific method on a derived visitor class /// of the class. However, it should still /// support unknown visitors by calling /// . /// /// public abstract void Accept (BodyPartVisitor visitor); internal static void Encode (StringBuilder builder, uint value) { builder.Append (value.ToString (CultureInfo.InvariantCulture)); } internal static void Encode (StringBuilder builder, string? value) { if (value != null) MimeUtils.AppendQuoted (builder, value); else builder.Append ("NIL"); } internal static void Encode (StringBuilder builder, Uri? location) { if (location != null) MimeUtils.AppendQuoted (builder, location.ToString ()); else builder.Append ("NIL"); } internal static void Encode (StringBuilder builder, string[]? values) { if (values == null || values.Length == 0) { builder.Append ("NIL"); return; } builder.Append ('('); for (int i = 0; i < values.Length; i++) { if (i > 0) builder.Append (' '); Encode (builder, values[i]); } builder.Append (')'); } internal static void Encode (StringBuilder builder, IListis . /// parameters) { if (parameters == null || parameters.Count == 0) { builder.Append ("NIL"); return; } builder.Append ('('); for (int i = 0; i < parameters.Count; i++) { if (i > 0) builder.Append (' '); Encode (builder, parameters[i].Name); builder.Append (' '); Encode (builder, parameters[i].Value); } builder.Append (')'); } internal static void Encode (StringBuilder builder, ContentDisposition? disposition) { if (disposition == null) { builder.Append ("NIL"); return; } builder.Append ('('); Encode (builder, disposition.Disposition); builder.Append (' '); Encode (builder, disposition.Parameters); builder.Append (')'); } internal static void Encode (StringBuilder builder, ContentType contentType) { Encode (builder, contentType.MediaType); builder.Append (' '); Encode (builder, contentType.MediaSubtype); builder.Append (' '); Encode (builder, contentType.Parameters); } internal static void Encode (StringBuilder builder, BodyPartCollection parts) { if (parts == null || parts.Count == 0) { builder.Append ("NIL"); return; } for (int i = 0; i < parts.Count; i++) { if (i > 0) builder.Append (' '); Encode (builder, parts[i]); } } internal static void Encode (StringBuilder builder, Envelope? envelope) { if (envelope == null) { builder.Append ("NIL"); return; } envelope.Encode (builder); } internal static void Encode (StringBuilder builder, BodyPart? body) { if (body == null) { builder.Append ("NIL"); return; } builder.Append ('('); body.Encode (builder); builder.Append (')'); } /// /// Encodes the ///into the . /// /// Encodes the /// The string builder. protected abstract void Encode (StringBuilder builder); ///into the . /// /// Returns a ///that represents the current . /// /// ///Returns a ///that represents the current . The syntax of the string returned, while similar to IMAP's BODYSTRUCTURE syntax, /// is not completely compatible. ///A public override string ToString () { var builder = new StringBuilder (); builder.Append ('('); Encode (builder); builder.Append (')'); return builder.ToString (); } static bool IsNIL (string text, int index) { return string.Compare (text, index, "NIL", 0, 3, StringComparison.Ordinal) == 0; } static bool TryParse (string text, ref int index, out uint value) { while (index < text.Length && text[index] == ' ') index++; int startIndex = index; value = 0; while (index < text.Length && char.IsDigit (text[index])) value = (value * 10) + (uint) (text[index++] - '0'); return index > startIndex; } static bool TryParse (string text, ref int index, out string? nstring) { nstring = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length) return false; if (text[index] != '"') { if (index + 3 <= text.Length && IsNIL (text, index)) { index += 3; return true; } return false; } var token = new StringBuilder (); bool escaped = false; index++; while (index < text.Length) { if (text[index] == '"' && !escaped) break; if (escaped || text[index] != '\\') { token.Append (text[index]); escaped = false; } else { escaped = true; } index++; } if (index >= text.Length) return false; nstring = token.ToString (); index++; return true; } static bool TryParse (string text, ref int index, out string[]? values) { values = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length) return false; if (text[index] != '(') { if (index + 3 <= text.Length && IsNIL (text, index)) { index += 3; return true; } return false; } index++; if (index >= text.Length) return false; var list = new Listthat represents the current . (); do { if (text[index] == ')') break; if (!TryParse (text, ref index, out string? value)) return false; if (value != null) list.Add (value); } while (index < text.Length); if (index >= text.Length || text[index] != ')') return false; values = list.ToArray (); index++; return true; } static bool TryParse (string text, ref int index, out Uri? uri) { uri = null; if (!TryParse (text, ref index, out string? nstring)) return false; if (!string.IsNullOrEmpty (nstring)) { if (Uri.IsWellFormedUriString (nstring, UriKind.Absolute)) uri = new Uri (nstring, UriKind.Absolute); else if (Uri.IsWellFormedUriString (nstring, UriKind.Relative)) uri = new Uri (nstring, UriKind.Relative); } return true; } static bool TryParse (string text, ref int index, [NotNullWhen (true)] out IList ? parameters) { parameters = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length) return false; if (text[index] != '(') { if (index + 3 <= text.Length && IsNIL (text, index)) { parameters = new List (); index += 3; return true; } return false; } index++; if (index >= text.Length) return false; parameters = new List (); do { if (text[index] == ')') break; if (!TryParse (text, ref index, out string? name) || name == null) return false; if (!TryParse (text, ref index, out string? value) || value == null) return false; parameters.Add (new Parameter (name, value)); } while (index < text.Length); if (index >= text.Length || text[index] != ')') return false; index++; return true; } static bool TryParse (string text, ref int index, out ContentDisposition? disposition) { disposition = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length) return false; if (text[index] != '(') { if (index + 3 <= text.Length && IsNIL (text, index)) { index += 3; return true; } return false; } index++; if (!TryParse (text, ref index, out string? value) || value == null) return false; if (!TryParse (text, ref index, out IList ? parameters)) return false; if (index >= text.Length || text[index] != ')') return false; index++; disposition = new ContentDisposition (value); foreach (var param in parameters) disposition.Parameters.Add (param); return true; } static bool TryParse (string text, ref int index, bool multipart, [NotNullWhen (true)] out ContentType? contentType) { string? type, subtype; contentType = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length) return false; if (!multipart) { if (!TryParse (text, ref index, out type)) return false; } else { type = "multipart"; } if (!TryParse (text, ref index, out subtype)) return false; if (!TryParse (text, ref index, out IList ? parameters)) return false; contentType = new ContentType (type ?? "application", subtype ?? "octet-stream"); foreach (var param in parameters) contentType.Parameters.Add (param); return true; } static bool TryParse (string text, ref int index, string prefix, [NotNullWhen (true)] out BodyPartCollection? bodyParts) { string path; int id = 1; bodyParts = null; if (index >= text.Length) return false; bodyParts = new BodyPartCollection (); do { if (text[index] != '(') break; path = prefix + id; if (!TryParse (text, ref index, path, out BodyPart? part)) return false; while (index < text.Length && text[index] == ' ') index++; if (part != null) bodyParts.Add (part); id++; } while (index < text.Length); return index < text.Length; } static bool TryParse (string text, ref int index, string path, out BodyPart? part) { ContentDisposition? disposition; ContentType? contentType; string[]? array; Uri? location; part = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length || text[index] != '(') { if (index + 3 <= text.Length && IsNIL (text, index)) { index += 3; return true; } return false; } index++; if (index >= text.Length) return false; if (text[index] == '(' || IsNIL (text, index)) { var prefix = path.Length > 0 ? path + "." : string.Empty; BodyPartCollection? bodyParts = null; if (text[index] == '(') { if (!TryParse (text, ref index, prefix, out bodyParts)) return false; } else { index += "NIL".Length; } if (!TryParse (text, ref index, true, out contentType)) return false; var multipart = new BodyPartMultipart (contentType, path, bodyParts ?? new BodyPartCollection ()); if (!TryParse (text, ref index, out disposition)) return false; multipart.ContentDisposition = disposition; if (!TryParse (text, ref index, out array)) return false; multipart.ContentLanguage = array; if (!TryParse (text, ref index, out location)) return false; multipart.ContentLocation = location; part = multipart; } else { BodyPartMessage? message = null; BodyPartText? txt = null; BodyPartBasic? basic; string? nstring; if (!TryParse (text, ref index, false, out contentType)) return false; if (contentType.IsMimeType ("message", "rfc822")) basic = message = new BodyPartMessage (contentType, path); else if (contentType.IsMimeType ("text", "*")) basic = txt = new BodyPartText (contentType, path); else basic = new BodyPartBasic (contentType, path); if (!TryParse (text, ref index, out nstring)) return false; basic.ContentId = nstring; if (!TryParse (text, ref index, out nstring)) return false; basic.ContentDescription = nstring; if (!TryParse (text, ref index, out nstring)) return false; basic.ContentTransferEncoding = nstring; if (!TryParse (text, ref index, out uint number)) return false; basic.Octets = number; if (!TryParse (text, ref index, out nstring)) return false; basic.ContentMd5 = nstring; if (!TryParse (text, ref index, out disposition)) return false; basic.ContentDisposition = disposition; if (!TryParse (text, ref index, out array)) return false; basic.ContentLanguage = array; if (!TryParse (text, ref index, out location)) return false; basic.ContentLocation = location; if (message != null) { if (!Envelope.TryParse (text, ref index, out Envelope? envelope)) return false; message.Envelope = envelope; if (!TryParse (text, ref index, path, out BodyPart? body)) return false; message.Body = body; if (!TryParse (text, ref index, out number)) return false; message.Lines = number; } else if (txt != null) { if (!TryParse (text, ref index, out number)) return false; txt.Lines = number; } part = basic; } if (index >= text.Length || text[index] != ')') return false; index++; return true; } /// /// Tries to parse the given text into a new ///instance. /// /// ///Parses a body part from the specified text. ///This syntax, while similar to IMAP's BODYSTRUCTURE syntax, is not completely /// compatible. ////// The text to parse. /// The parsed body part. /// if the body part was successfully parsed; otherwise, . /// public static bool TryParse (string text, out BodyPart? part) { if (text == null) throw new ArgumentNullException (nameof (text)); int index = 0; return TryParse (text, ref index, string.Empty, out part) && index == text.Length; } } } ================================================ FILE: MailKit/BodyPartBasic.cs ================================================ // // BodyPartBasic.cs // // Author: Jeffrey Stedfastis . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Text; using MimeKit; namespace MailKit { /// /// A basic message body part. /// ////// Represents any message body part that is not a multipart, /// message/rfc822 part, or a text part. /// ////// public class BodyPartBasic : BodyPart { ///////// Initializes a new instance of the ///class. /// /// Creates a new [Obsolete ("Use BodyPartBasic (ContentType, string) instead.")] public BodyPartBasic () : base () { } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The content type. /// The part specifier. ///. /// /// public BodyPartBasic (ContentType contentType, string partSpecifier) : base (contentType, partSpecifier) { } ////// is . -or- ////// is . /// Gets the Content-Id of the body part, if available. /// ////// Gets the Content-Id of the body part, if available. /// ///The content identifier. public string? ContentId { get; set; } ////// Gets the Content-Description of the body part, if available. /// ////// Gets the Content-Description of the body part, if available. /// ///The content description. public string? ContentDescription { get; set; } ////// Gets the Content-Transfer-Encoding of the body part. /// ////// ///Gets the Content-Transfer-Encoding of the body part. ///Hint: Use the MimeUtils.TryParse /// method to parse this value into a usable ///. The content transfer encoding. public string? ContentTransferEncoding { get; set; } ////// Gets the size of the body part, in bytes. /// ////// ///Gets the size of the body part, in bytes. ///Note that this size is the size in its transfer encoding /// and not the resulting size after any decoding. ///The number of octets. public uint Octets { get; set; } ////// Gets the MD5 hash of the content, if available. /// ////// Gets the MD5 hash of the content, if available. /// ///The content md5. public string? ContentMd5 { get; set; } ////// Gets the Content-Disposition of the body part, if available. /// ////// ///Gets the Content-Disposition of the body part, if available. ///The Content-Disposition value is only retrieved if the /// ///flag is used when fetching /// summary information from an . The content disposition. public ContentDisposition? ContentDisposition { get; set; } ////// Gets the Content-Language of the body part, if available. /// ////// ///Gets the Content-Language of the body part, if available. ///The Content-Language value is only retrieved if the /// ///flag is used when fetching /// summary information from an . The content language. public string[]? ContentLanguage { get; set; } ////// Gets the Content-Location of the body part, if available. /// ////// ///Gets the Content-Location of the body part, if available. ///The Content-Location value is only retrieved if the /// ///flag is used when fetching /// summary information from an . The content location. public Uri? ContentLocation { get; set; } ////// Determines whether or not the body part is an attachment. /// ////// ///Determines whether or not the body part is an attachment based on the value of /// the Content-Disposition. ///Since the value of the Content-Disposition header is needed, it /// is necessary to include the ///flag when /// fetching summary information from an . public bool IsAttachment { get { return ContentDisposition != null && ContentDisposition.IsAttachment; } } /// if this part is an attachment; otherwise, . /// Get the name of the file. /// ////// ///First checks for the "filename" parameter on the Content-Disposition header. If /// that does not exist, then the "name" parameter on the Content-Type header is used. ///Since the value of the Content-Disposition header is needed, it is /// necessary to include the ///flag when /// fetching summary information from an . The name of the file. public string? FileName { get { string? filename = null; if (ContentDisposition != null) filename = ContentDisposition.FileName; filename ??= ContentType.Name; return filename?.Trim (); } } ////// Dispatches to the specific visit method for this MIME body part. /// ////// This default implementation for /// The visitor. ///nodes /// calls . Override this /// method to call into a more specific method on a derived visitor class /// of the class. However, it should still /// support unknown visitors by calling /// . /// /// public override void Accept (BodyPartVisitor visitor) { if (visitor == null) throw new ArgumentNullException (nameof (visitor)); visitor.VisitBodyPartBasic (this); } ///is . /// /// Encodes the ///into the . /// /// Encodes the /// The string builder. protected override void Encode (StringBuilder builder) { Encode (builder, ContentType); builder.Append (' '); Encode (builder, ContentId); builder.Append (' '); Encode (builder, ContentDescription); builder.Append (' '); Encode (builder, ContentTransferEncoding); builder.Append (' '); Encode (builder, Octets); builder.Append (' '); Encode (builder, ContentMd5); builder.Append (' '); Encode (builder, ContentDisposition); builder.Append (' '); Encode (builder, ContentLanguage); builder.Append (' '); Encode (builder, ContentLocation); } } } ================================================ FILE: MailKit/BodyPartCollection.cs ================================================ // // BodyPartCollection.cs // // Author: Jeffrey Stedfastinto the . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Linq; using System.Collections; using System.Collections.Generic; using MimeKit.Utils; namespace MailKit { /// /// A ///collection. /// /// A public class BodyPartCollection : ICollectioncollection. /// { readonly List collection = new List (); /// /// Initializes a new instance of the ///class. /// /// Creates a new public BodyPartCollection () { } ///. /// /// Get the number of body parts in the collection. /// ////// Gets the number of body parts in the collection. /// ///The count. public int Count { get { return collection.Count; } } ////// Get whether or not this body part collection is read only. /// ////// Gets whether or not this body part collection is read only. /// ///public bool IsReadOnly { get { return false; } } /// if this collection is read only; otherwise, . /// Add the specified body part to the collection. /// ////// Adds the specified body part to the collection. /// /// The body part. ////// public void Add (BodyPart part) { if (part == null) throw new ArgumentNullException (nameof (part)); collection.Add (part); } ///is . /// /// Clears the body part collection. /// ////// Removes all of the body parts from the collection. /// public void Clear () { collection.Clear (); } ////// Checks if the collection contains the specified body part. /// ////// Determines whether or not the collection contains the specified body part. /// ////// The body part. /// if the specified body part exists; otherwise, . /// public bool Contains (BodyPart part) { if (part == null) throw new ArgumentNullException (nameof (part)); return collection.Contains (part); } ///is . /// /// Copies all of the body parts in the collection to the specified array. /// ////// Copies all of the body parts within the collection into the array, /// starting at the specified array index. /// /// The array. /// The array index. ////// ///is . /// /// public void CopyTo (BodyPart[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException (nameof (array)); if (arrayIndex < 0 || arrayIndex + Count > array.Length) throw new ArgumentOutOfRangeException (nameof (arrayIndex)); collection.CopyTo (array, arrayIndex); } ///is out of range. /// /// Removes the specified body part. /// ////// Removes the specified body part. /// ////// The body part. /// if the body part was removed; otherwise, . /// public bool Remove (BodyPart part) { if (part == null) throw new ArgumentNullException (nameof (part)); return collection.Remove (part); } ///is . /// /// Get the body part at the specified index. /// ////// Gets the body part at the specified index. /// ///The body part at the specified index. /// The index. ////// public BodyPart this [int index] { get { if (index < 0 || index >= collection.Count) throw new ArgumentOutOfRangeException (nameof (index)); return collection[index]; } } ///is out of range. /// /// Gets the index of the body part matching the specified URI. /// ////// ///Finds the index of the body part matching the specified URI, if it exists. ///If the URI scheme is ///"cid" , then matching is performed based on the Content-Id header /// values, otherwise the Content-Location headers are used. If the provided URI is absolute and a child /// part's Content-Location is relative, then then the child part's Content-Location URI will be combined /// with the value of its Content-Base header, if available, otherwise it will be combined with the /// multipart/related part's Content-Base header in order to produce an absolute URI that can be /// compared with the provided absolute URI.The index of the part matching the specified URI if found; otherwise /// The URI of the body part. ///-1 ./// public int IndexOf (Uri uri) { if (uri == null) throw new ArgumentNullException (nameof (uri)); bool cid = uri.IsAbsoluteUri && uri.Scheme.Equals ("cid", StringComparison.OrdinalIgnoreCase); for (int index = 0; index < Count; index++) { if (this[index] is not BodyPartBasic bodyPart) continue; if (uri.IsAbsoluteUri) { if (cid) { if (!string.IsNullOrEmpty (bodyPart.ContentId)) { // Note: we might have a Content-Id in the form "is . /// ", so attempt to decode it var id = MimeUtils.EnumerateReferences (bodyPart.ContentId!).FirstOrDefault () ?? bodyPart.ContentId; if (id == uri.AbsolutePath) return index; } } else if (bodyPart.ContentLocation != null) { if (!bodyPart.ContentLocation.IsAbsoluteUri) continue; if (bodyPart.ContentLocation == uri) return index; } } else if (bodyPart.ContentLocation == uri) { return index; } } return -1; } #region IEnumerable implementation /// /// Get the body part enumerator. /// ////// Gets the body part enumerator. /// ///The enumerator. public IEnumeratorGetEnumerator () { return collection.GetEnumerator (); } #endregion #region IEnumerable implementation /// /// Get the body part enumerator. /// ////// Gets the body part enumerator. /// ///The enumerator. IEnumerator IEnumerable.GetEnumerator () { return GetEnumerator (); } #endregion } } ================================================ FILE: MailKit/BodyPartMessage.cs ================================================ // // BodyPartMessage.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Text; using MimeKit; namespace MailKit { /// /// A message/rfc822 body part. /// ////// Represents a message/rfc822 body part. /// public class BodyPartMessage : BodyPartBasic { ////// Initializes a new instance of the ///class. /// /// Creates a new [Obsolete ("Use BodyPartMessage (ContentType, string) instead.")] public BodyPartMessage () : this (new ContentType ("message", "rfc822"), string.Empty) { } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The content type. /// The part specifier. ///. /// /// public BodyPartMessage (ContentType contentType, string partSpecifier) : base (contentType, partSpecifier) { } ////// is . -or- ////// is . /// Gets the envelope of the message, if available. /// ////// Gets the envelope of the message, if available. /// ///The envelope. public Envelope? Envelope { get; set; } ////// Gets the body structure of the message. /// ////// Gets the body structure of the message. /// ///The body structure. public BodyPart? Body { get; set; } ////// Gets the length of the message, in lines. /// ////// Gets the length of the message, in lines. /// ///The number of lines. public uint Lines { get; set; } ////// Dispatches to the specific visit method for this MIME body part. /// ////// This default implementation for /// The visitor. ///nodes /// calls . Override this /// method to call into a more specific method on a derived visitor class /// of the class. However, it should still /// support unknown visitors by calling /// . /// /// public override void Accept (BodyPartVisitor visitor) { if (visitor == null) throw new ArgumentNullException (nameof (visitor)); visitor.VisitBodyPartMessage (this); } ///is . /// /// Encodes the ///into the . /// /// Encodes the /// The string builder. protected override void Encode (StringBuilder builder) { base.Encode (builder); builder.Append (' '); Encode (builder, Envelope); builder.Append (' '); Encode (builder, Body); builder.Append (' '); Encode (builder, Lines); } } } ================================================ FILE: MailKit/BodyPartMultipart.cs ================================================ // // BodyPartMultipart.cs // // Author: Jeffrey Stedfastinto the . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Text; using MimeKit; namespace MailKit { /// /// A multipart body part. /// ////// A multipart body part. /// public class BodyPartMultipart : BodyPart { ////// Initializes a new instance of the ///class. /// /// Creates a new [Obsolete ("Use BodyPartMultipart (ContentType, string) instead.")] public BodyPartMultipart () : this (new ContentType ("multipart", "mixed"), string.Empty) { } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The content type. /// The part specifier. ///. /// /// public BodyPartMultipart (ContentType contentType, string partSpecifier) : base (contentType, partSpecifier) { BodyParts = new BodyPartCollection (); } ////// is . -or- ////// is . /// Initializes a new instance of the ///class. /// /// Creates a new /// The content type. /// The part specifier. /// The child body parts of the multipart. ///. /// /// public BodyPartMultipart (ContentType contentType, string partSpecifier, BodyPartCollection bodyParts) : base (contentType, partSpecifier) { if (bodyParts is null) throw new ArgumentNullException (nameof (bodyParts)); BodyParts = bodyParts; } ////// is . -or- ////// is . -or- ////// is . /// Gets the child body parts. /// ////// Gets the child body parts. /// ///The child body parts. public BodyPartCollection BodyParts { get; private set; } ////// Gets the Content-Disposition of the body part, if available. /// ////// Gets the Content-Disposition of the body part, if available. /// ///The content disposition. public ContentDisposition? ContentDisposition { get; set; } ////// Gets the Content-Language of the body part, if available. /// ////// Gets the Content-Language of the body part, if available. /// ///The content language. public string[]? ContentLanguage { get; set; } ////// Gets the Content-Location of the body part, if available. /// ////// Gets the Content-Location of the body part, if available. /// ///The content location. public Uri? ContentLocation { get; set; } ////// Dispatches to the specific visit method for this MIME body part. /// ////// This default implementation for /// The visitor. ///nodes /// calls . Override this /// method to call into a more specific method on a derived visitor class /// of the class. However, it should still /// support unknown visitors by calling /// . /// /// public override void Accept (BodyPartVisitor visitor) { if (visitor == null) throw new ArgumentNullException (nameof (visitor)); visitor.VisitBodyPartMultipart (this); } ///is . /// /// Encodes the ///into the . /// /// Encodes the /// The string builder. protected override void Encode (StringBuilder builder) { Encode (builder, BodyParts); builder.Append (' '); Encode (builder, ContentType.MediaSubtype); builder.Append (' '); Encode (builder, ContentType.Parameters); builder.Append (' '); Encode (builder, ContentDisposition); builder.Append (' '); Encode (builder, ContentLanguage); builder.Append (' '); Encode (builder, ContentLocation); } } } ================================================ FILE: MailKit/BodyPartText.cs ================================================ // // BodyPartText.cs // // Author: Jeffrey Stedfastinto the . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Text; using MimeKit; namespace MailKit { /// /// A textual body part. /// ////// Represents any body part with a media type of "text". /// ////// public class BodyPartText : BodyPartBasic { ///////// Initializes a new instance of the ///class. /// /// Creates a new [Obsolete ("Use BodyPartText (ContentType, string) instead.")] public BodyPartText () : this (new ContentType ("text", "plain"), string.Empty) { } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The content type. /// The part specifier. ///. /// /// public BodyPartText (ContentType contentType, string partSpecifier) : base (contentType, partSpecifier) { } ////// is . -or- ////// is . /// Gets whether or not this text part contains plain text. /// ////// Checks whether or not the text part's Content-Type is text/plain. /// ///public bool IsPlain { get { return ContentType.IsMimeType ("text", "plain"); } } /// if the text is html; otherwise, . /// Gets whether or not this text part contains HTML. /// ////// Checks whether or not the text part's Content-Type is text/html. /// ///public bool IsHtml { get { return ContentType.IsMimeType ("text", "html"); } } /// if the text is html; otherwise, . /// Gets the length of the text, in lines. /// ////// Gets the length of the text, in lines. /// ///The number of lines. public uint Lines { get; set; } ////// Dispatches to the specific visit method for this MIME body part. /// ////// This default implementation for /// The visitor. ///nodes /// calls . Override this /// method to call into a more specific method on a derived visitor class /// of the class. However, it should still /// support unknown visitors by calling /// . /// /// public override void Accept (BodyPartVisitor visitor) { if (visitor == null) throw new ArgumentNullException (nameof (visitor)); visitor.VisitBodyPartText (this); } ///is . /// /// Encodes the ///into the . /// /// Encodes the /// The string builder. protected override void Encode (StringBuilder builder) { base.Encode (builder); builder.Append (' '); Encode (builder, Lines); } } } ================================================ FILE: MailKit/BodyPartVisitor.cs ================================================ // // BodyPartVisitor.cs // // Author: Jeffrey Stedfastinto the . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // namespace MailKit { /// /// Represents a visitor for a tree of MIME body parts. /// ////// This class is designed to be inherited to create more specialized classes whose /// functionality requires traversing, examining or copying a tree of MIME body parts. /// public abstract class BodyPartVisitor { ////// Initialize a new instance of the ///class. /// /// Creates a new protected BodyPartVisitor () { } ///. /// /// Dispatches the entity to one of the more specialized visit methods in this class. /// ////// Dispatches the entity to one of the more specialized visit methods in this class. /// /// The MIME body part. public virtual void Visit (BodyPart body) { body?.Accept (this); } ////// Visit the abstract MIME body part. /// ////// Visits the abstract MIME body part. /// /// The MIME body part. protected internal virtual void VisitBodyPart (BodyPart entity) { } ////// Visit the basic MIME body part. /// ////// Visits the basic MIME body part. /// /// The basic MIME body part. protected internal virtual void VisitBodyPartBasic (BodyPartBasic entity) { VisitBodyPart (entity); } ////// Visit the message contained within a message/rfc822 or message/news MIME entity. /// ////// Visits the message contained within a message/rfc822 or message/news MIME entity. /// /// The body part representing the message/rfc822 message. protected virtual void VisitMessage (BodyPart message) { message.Accept (this); } ////// Visit the message/rfc822 or message/news MIME entity. /// ////// Visits the message/rfc822 or message/news MIME entity. /// /// The message/rfc822 or message/news body part. protected internal virtual void VisitBodyPartMessage (BodyPartMessage entity) { VisitBodyPartBasic (entity); if (entity.Body != null) VisitMessage (entity.Body); } ////// Visit the children of a ///. /// /// Visits the children of a /// The multipart. protected virtual void VisitChildren (BodyPartMultipart multipart) { for (int i = 0; i < multipart.BodyParts.Count; i++) multipart.BodyParts[i].Accept (this); } ///. /// /// Visit the abstract multipart MIME entity. /// ////// Visits the abstract multipart MIME entity. /// /// The multipart body part. protected internal virtual void VisitBodyPartMultipart (BodyPartMultipart multipart) { VisitBodyPart (multipart); VisitChildren (multipart); } ////// Visit the text-based MIME part entity. /// ////// Visits the text-based MIME part entity. /// /// The text-based body part. protected internal virtual void VisitBodyPartText (BodyPartText entity) { VisitBodyPartBasic (entity); } } } ================================================ FILE: MailKit/ByteArrayBuilder.cs ================================================ // // ByteArrayBuilder.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Text; using System.Buffers; namespace MailKit { class ByteArrayBuilder : IDisposable { byte[] buffer; int length; public ByteArrayBuilder (int initialCapacity) { buffer = ArrayPool .Shared.Rent (initialCapacity); length = 0; } public int Length { get { return length; } } void EnsureCapacity (int capacity) { if (capacity > buffer.Length) { var resized = ArrayPool .Shared.Rent (capacity); Buffer.BlockCopy (buffer, 0, resized, 0, length); ArrayPool .Shared.Return (buffer); buffer = resized; } } public void Append (byte c) { EnsureCapacity (length + 1); buffer[length++] = c; } public void Append (byte[] text, int startIndex, int count) { EnsureCapacity (length + count); Buffer.BlockCopy (text, startIndex, buffer, length, count); length += count; } public void Clear () { length = 0; } public byte[] ToArray () { var array = new byte[length]; Buffer.BlockCopy (buffer, 0, array, 0, length); return array; } public string ToString (Encoding encoding, Encoding fallback) { try { return encoding.GetString (buffer, 0, length); } catch (DecoderFallbackException) { return fallback.GetString (buffer, 0, length); } } public override string ToString () { return ToString (TextEncodings.UTF8, TextEncodings.Latin1); } public bool Equals (string value, bool ignoreCase = false) { if (length == value.Length) { if (ignoreCase) { for (int i = 0; i < length; i++) { uint a = (uint) buffer[i]; uint b = (uint) value[i]; if ((a - 'a') <= 'z' - 'a') a -= 0x20; if ((b - 'a') <= 'z' - 'a') b -= 0x20; if (a != b) return false; } } else { for (int i = 0; i < length; i++) { if (value[i] != (char) buffer[i]) return false; } } return true; } return false; } public void TrimNewLine () { // Trim the sequence from the end of the line. if (length > 0 && buffer[length - 1] == (byte) '\n') { length--; if (length > 0 && buffer[length - 1] == (byte) '\r') length--; } } // FIXME: This should be moved somewhere else... internal static bool TryParse (byte[] text, ref int index, int endIndex, out int value) { int startIndex = index; value = 0; while (index < endIndex && text[index] >= (byte) '0' && text[index] <= (byte) '9') { int digit = text[index] - (byte) '0'; if (value > int.MaxValue / 10) { // integer overflow return false; } if (value == int.MaxValue / 10 && digit > int.MaxValue % 10) { // integer overflow return false; } value = (value * 10) + digit; index++; } return index > startIndex; } // FIXME: Does this make sense to have here? Or should I have an extensions class for byte[] that has this? public bool TryParse (int startIndex, int endIndex, out int value) { int index = startIndex; return TryParse (buffer, ref index, endIndex, out value); } public void Dispose () { if (length != -1) { ArrayPool .Shared.Return (buffer); length = -1; } } } } ================================================ FILE: MailKit/CommandException.cs ================================================ // // CommandException.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; #if SERIALIZABLE using System.Security; using System.Runtime.Serialization; #endif namespace MailKit { /// /// The exception that is thrown when there is a command error. /// ////// A #if SERIALIZABLE [Serializable] #endif public abstract class CommandException : Exception { #if SERIALIZABLE ///can be thrown by any of the various client /// methods in MailKit. Unlike a , a /// is typically non-fatal (meaning that it does /// not force the client to disconnect). /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The serialization info. /// The streaming context. ///. /// /// [SecuritySafeCritical] [Obsolete ("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.")] protected CommandException (SerializationInfo info, StreamingContext context) : base (info, context) { } #endif ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The error message. /// An inner exception. protected CommandException (string message, Exception innerException) : base (message, innerException) { HelpLink = "https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog"; } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The error message. protected CommandException (string message) : base (message) { HelpLink = "https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog"; } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new protected CommandException () { HelpLink = "https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog"; } } } ================================================ FILE: MailKit/CompressedStream.cs ================================================ // // CompressedStream.cs // // Author: Jeffrey Stedfast. /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Org.BouncyCastle.Utilities.Zlib; namespace MailKit { /// /// A compressed stream. /// class CompressedStream : Stream { readonly ZStream zIn, zOut; bool eos, disposed; public CompressedStream (Stream innerStream) { InnerStream = innerStream; zOut = new ZStream (); zOut.deflateInit (5, true); zOut.next_out = new byte[4096]; zIn = new ZStream (); zIn.inflateInit (true); zIn.next_in = new byte[4096]; } ////// Gets the inner stream. /// ///The inner stream. public Stream InnerStream { get; private set; } ////// Gets whether the stream supports reading. /// ///public override bool CanRead { get { return InnerStream.CanRead; } } /// if the stream supports reading; otherwise, . /// Gets whether the stream supports writing. /// ///public override bool CanWrite { get { return InnerStream.CanWrite; } } /// if the stream supports writing; otherwise, . /// Gets whether the stream supports seeking. /// ///public override bool CanSeek { get { return false; } } /// if the stream supports seeking; otherwise, . /// Gets whether the stream supports I/O timeouts. /// ///public override bool CanTimeout { get { return InnerStream.CanTimeout; } } /// if the stream supports I/O timeouts; otherwise, . /// Gets or sets a value, in milliseconds, that determines how long the stream will attempt to read before timing out. /// ///A value, in milliseconds, that determines how long the stream will attempt to read before timing out. ///The read timeout. public override int ReadTimeout { get { return InnerStream.ReadTimeout; } set { InnerStream.ReadTimeout = value; } } ////// Gets or sets a value, in milliseconds, that determines how long the stream will attempt to write before timing out. /// ///A value, in milliseconds, that determines how long the stream will attempt to write before timing out. ///The write timeout. public override int WriteTimeout { get { return InnerStream.WriteTimeout; } set { InnerStream.WriteTimeout = value; } } ////// Gets or sets the position within the current stream. /// ///The current position within the stream. ///The position of the stream. ////// The stream does not support seeking. /// public override long Position { get { throw new NotSupportedException (); } set { throw new NotSupportedException (); } } ////// Gets the length in bytes of the stream. /// ///A long value representing the length of the stream in bytes. ///The length of the stream. ////// The stream does not support seeking. /// public override long Length { get { throw new NotSupportedException (); } } static void ValidateArguments (byte[] buffer, int offset, int count) { if (buffer == null) throw new ArgumentNullException (nameof (buffer)); if (offset < 0 || offset > buffer.Length) throw new ArgumentOutOfRangeException (nameof (offset)); if (count < 0 || count > (buffer.Length - offset)) throw new ArgumentOutOfRangeException (nameof (count)); } void CheckDisposed () { if (disposed) throw new ObjectDisposedException (nameof (CompressedStream)); } ////// Reads a sequence of bytes from the stream and advances the position /// within the stream by the number of bytes read. /// ///The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many /// bytes are not currently available, or zero (0) if the end of the stream has been reached. /// The buffer. /// The buffer offset. /// The number of bytes to read. ////// ///is . /// /// ////// is less than zero or greater than the length of . -or- ///The ///is not large enough to contain bytes starting /// at the specified . /// The stream has been disposed. /// ////// An I/O error occurred. /// public override int Read (byte[] buffer, int offset, int count) { CheckDisposed (); ValidateArguments (buffer, offset, count); if (count == 0) return 0; zIn.next_out = buffer; zIn.next_out_index = offset; zIn.avail_out = count; do { if (zIn.avail_in == 0 && !eos) { zIn.avail_in = InnerStream.Read (zIn.next_in, 0, zIn.next_in.Length); eos = zIn.avail_in == 0; zIn.next_in_index = 0; } int retval = zIn.inflate (JZlib.Z_FULL_FLUSH); if (retval == JZlib.Z_STREAM_END) break; if (eos && retval == JZlib.Z_BUF_ERROR) return 0; if (retval != JZlib.Z_OK) throw new IOException ("Error inflating: " + zIn.msg); } while (zIn.avail_out == count); return count - zIn.avail_out; } ////// Reads a sequence of bytes from the stream and advances the position /// within the stream by the number of bytes read. /// ///The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many /// bytes are not currently available, or zero (0) if the end of the stream has been reached. /// The buffer. /// The buffer offset. /// The number of bytes to read. /// The cancellation token. ////// ///is . /// /// ////// is less than zero or greater than the length of . -or- ///The ///is not large enough to contain bytes starting /// at the specified . /// The stream has been disposed. /// ////// An I/O error occurred. /// public override async TaskReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken) { CheckDisposed (); ValidateArguments (buffer, offset, count); if (count == 0) return 0; zIn.next_out = buffer; zIn.next_out_index = offset; zIn.avail_out = count; do { if (zIn.avail_in == 0 && !eos) { cancellationToken.ThrowIfCancellationRequested (); zIn.avail_in = await InnerStream.ReadAsync (zIn.next_in, 0, zIn.next_in.Length, cancellationToken).ConfigureAwait (false); eos = zIn.avail_in == 0; zIn.next_in_index = 0; } int retval = zIn.inflate (JZlib.Z_FULL_FLUSH); if (retval == JZlib.Z_STREAM_END) break; if (eos && retval == JZlib.Z_BUF_ERROR) return 0; if (retval != JZlib.Z_OK) throw new IOException ("Error inflating: " + zIn.msg); } while (zIn.avail_out == count); return count - zIn.avail_out; } /// /// Writes a sequence of bytes to the stream and advances the current /// position within this stream by the number of bytes written. /// /// The buffer to write. /// The offset of the first byte to write. /// The number of bytes to write. ////// ///is . /// /// ////// is less than zero or greater than the length of . -or- ///The ///is not large enough to contain bytes starting /// at the specified . /// The stream has been disposed. /// ////// The stream does not support writing. /// ////// An I/O error occurred. /// public override void Write (byte[] buffer, int offset, int count) { CheckDisposed (); ValidateArguments (buffer, offset, count); if (count == 0) return; zOut.next_in = buffer; zOut.next_in_index = offset; zOut.avail_in = count; do { zOut.avail_out = zOut.next_out.Length; zOut.next_out_index = 0; if (zOut.deflate (JZlib.Z_FULL_FLUSH) != JZlib.Z_OK) throw new IOException ("Error deflating: " + zOut.msg); InnerStream.Write (zOut.next_out, 0, zOut.next_out.Length - zOut.avail_out); } while (zOut.avail_in > 0 || zOut.avail_out == 0); } ////// Writes a sequence of bytes to the stream and advances the current /// position within this stream by the number of bytes written. /// ///A task that represents the asynchronous write operation. /// The buffer to write. /// The offset of the first byte to write. /// The number of bytes to write. /// The cancellation token. ////// ///is . /// /// ////// is less than zero or greater than the length of . -or- ///The ///is not large enough to contain bytes starting /// at the specified . /// The stream has been disposed. /// ////// The stream does not support writing. /// ////// An I/O error occurred. /// public override async Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken) { CheckDisposed (); ValidateArguments (buffer, offset, count); if (count == 0) return; zOut.next_in = buffer; zOut.next_in_index = offset; zOut.avail_in = count; do { cancellationToken.ThrowIfCancellationRequested (); zOut.avail_out = zOut.next_out.Length; zOut.next_out_index = 0; if (zOut.deflate (JZlib.Z_FULL_FLUSH) != JZlib.Z_OK) throw new IOException ("Error deflating: " + zOut.msg); await InnerStream.WriteAsync (zOut.next_out, 0, zOut.next_out.Length - zOut.avail_out, cancellationToken).ConfigureAwait (false); } while (zOut.avail_in > 0 || zOut.avail_out == 0); } ////// Clears all output buffers for this stream and causes any buffered data to be written /// to the underlying device. /// ////// The stream has been disposed. /// ////// The stream does not support writing. /// ////// An I/O error occurred. /// public override void Flush () { CheckDisposed (); InnerStream.Flush (); } ////// Clears all output buffers for this stream and causes any buffered data to be written /// to the underlying device. /// ///A task that represents the asynchronous flush operation. ////// The stream has been disposed. /// ////// The stream does not support writing. /// ////// An I/O error occurred. /// public override Task FlushAsync (CancellationToken cancellationToken) { CheckDisposed (); return InnerStream.FlushAsync (cancellationToken); } ////// Sets the position within the current stream. /// ///The new position within the stream. /// The offset into the stream relative to the. /// The origin to seek from. /// /// The stream does not support seeking. /// public override long Seek (long offset, SeekOrigin origin) { throw new NotSupportedException (); } ////// Sets the length of the stream. /// /// The desired length of the stream in bytes. ////// The stream does not support setting the length. /// public override void SetLength (long value) { throw new NotSupportedException (); } ////// Releases the unmanaged resources used by the ///and /// optionally releases the managed resources. /// to release both managed and unmanaged resources; /// to release only the unmanaged resources. protected override void Dispose (bool disposing) { if (disposing && !disposed) { InnerStream.Dispose (); disposed = true; zOut.free (); zIn.free (); } base.Dispose (disposing); } } } ================================================ FILE: MailKit/ConnectedEventArgs.cs ================================================ // // ConnectedEventArgs.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using MailKit.Security; namespace MailKit { /// /// Connected event arguments. /// ////// When a public class ConnectedEventArgs : EventArgs { ///is connected, it will emit a /// event. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The name of the host that the client connected to. /// The port that the client connected to on the remote host. /// The SSL/TLS options that were used when connecting to the remote host. public ConnectedEventArgs (string host, int port, SecureSocketOptions options) { Options = options; Host = host; Port = port; } ///. /// /// Get the name of the remote host. /// ////// Gets the name of the remote host. /// ///The host name of the server. public string Host { get; private set; } ////// Get the port. /// ////// Gets the port. /// ///The port. public int Port { get; private set; } ////// Get the SSL/TLS options. /// ////// Gets the SSL/TLS options. /// ///The SSL/TLS options. public SecureSocketOptions Options { get; private set; } } } ================================================ FILE: MailKit/DeliveryStatusNotification.cs ================================================ // // DeliveryStatusNotification.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// Delivery status notification types. /// ////// A set of flags that may be bitwise-or'd together to specify /// when a delivery status notification should be sent for a /// particular recipient. /// ////// [Flags] public enum DeliveryStatusNotification { ///////// Never send delivery status notifications. /// Never = 0, ////// Send a notification on successful delivery to the recipient. /// Success = (1 << 0), ////// Send a notification on failure to deliver to the recipient. /// Failure = (1 << 1), ////// Send a notification when the delivery to the recipient has /// been delayed for an unusual amount of time. /// Delay = (1 << 2) } } ================================================ FILE: MailKit/DeliveryStatusNotificationType.cs ================================================ // // DeliveryStatusNotificationReturnType.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // FIXME: Move this to the MailKit namespace. It wasn't ever supposed to be in MailKit.Net.Smtp! namespace MailKit.Net.Smtp { /// /// Delivery status notification type. /// ////// The delivery status notification type specifies whether or not /// the full message should be included in any failed DSN issued for /// a message transmission as opposed to just the headers. /// ////// public enum DeliveryStatusNotificationType { ///////// The return type is unspecified, allowing the server to choose. /// Unspecified, ////// The full message should be included in any failed delivery status notification issued by the server. /// Full, ////// Only the headers should be included in any failed delivery status notification issued by the server. /// HeadersOnly, } } ================================================ FILE: MailKit/DisconnectedEventArgs.cs ================================================ // // DisconnectedEventArgs.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using MailKit.Security; namespace MailKit { /// /// Disconnected event arguments. /// ////// When a public class DisconnectedEventArgs : ConnectedEventArgs { ///gets disconnected, it will emit a /// event. /// /// Initializes a new instance of the ///class. /// /// Initializes a new instance of the /// The name of the host that the client was connected to. /// The port that the client was connected to. /// The SSL/TLS options that were used by the client. /// Ifclass. /// , the was disconnected via the /// method. public DisconnectedEventArgs (string host, int port, SecureSocketOptions options, bool requested) : base (host, port, options) { IsRequested = requested; } /// /// Get whether or not the service was explicitly asked to disconnect. /// ////// If the ///was disconnected via the /// method, then /// the value of will be . If the connection was unexpectedly /// dropped, then the value will be . /// public bool IsRequested { get; private set; } } } ================================================ FILE: MailKit/DuplexStream.cs ================================================ // // DuplexStream.cs // // Author: Jeffrey Stedfast if the disconnect was explicitly requested; otherwise, . // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.IO; using System.Threading; using System.Threading.Tasks; namespace MailKit { /// /// A duplex stream. /// class DuplexStream : Stream { bool disposed; ////// Initializes a new instance of the /// The stream to use for input. /// The stream to use for output. ///class. /// /// public DuplexStream (Stream istream, Stream ostream) { if (istream == null) throw new ArgumentNullException (nameof (istream)); if (ostream == null) throw new ArgumentNullException (nameof (ostream)); InputStream = istream; OutputStream = ostream; } ////// is . -or- ////// is . /// Gets the input stream. /// ///The input stream. public Stream InputStream { get; private set; } ////// Gets the output stream. /// ///The output stream. public Stream OutputStream { get; private set; } ////// Gets whether the stream supports reading. /// ///public override bool CanRead { get { return true; } } /// if the stream supports reading; otherwise, . /// Gets whether the stream supports writing. /// ///public override bool CanWrite { get { return true; } } /// if the stream supports writing; otherwise, . /// Gets whether the stream supports seeking. /// ///public override bool CanSeek { get { return false; } } /// if the stream supports seeking; otherwise, . /// Gets whether the stream supports I/O timeouts. /// ///public override bool CanTimeout { get { return InputStream.CanTimeout && OutputStream.CanTimeout; } } /// if the stream supports I/O timeouts; otherwise, . /// Gets or sets a value, in milliseconds, that determines how long the stream will attempt to read before timing out. /// ///A value, in milliseconds, that determines how long the stream will attempt to read before timing out. ///The read timeout. public override int ReadTimeout { get { return InputStream.ReadTimeout; } set { InputStream.ReadTimeout = value; } } ////// Gets or sets a value, in milliseconds, that determines how long the stream will attempt to write before timing out. /// ///A value, in milliseconds, that determines how long the stream will attempt to write before timing out. ///The write timeout. public override int WriteTimeout { get { return OutputStream.WriteTimeout; } set { OutputStream.WriteTimeout = value; } } ////// Gets or sets the position within the current stream. /// ///The current position within the stream. ///The position of the stream. ////// The stream does not support seeking. /// public override long Position { get { throw new NotSupportedException (); } set { throw new NotSupportedException (); } } ////// Gets the length in bytes of the stream. /// ///A long value representing the length of the stream in bytes. ///The length of the stream. ////// The stream does not support seeking. /// public override long Length { get { throw new NotSupportedException (); } } static void ValidateArguments (byte[] buffer, int offset, int count) { if (buffer == null) throw new ArgumentNullException (nameof (buffer)); if (offset < 0 || offset > buffer.Length) throw new ArgumentOutOfRangeException (nameof (offset)); if (count < 0 || count > (buffer.Length - offset)) throw new ArgumentOutOfRangeException (nameof (count)); } void CheckDisposed () { if (disposed) throw new ObjectDisposedException (nameof (DuplexStream)); } ////// Reads a sequence of bytes from the stream and advances the position /// within the stream by the number of bytes read. /// ///The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many /// bytes are not currently available, or zero (0) if the end of the stream has been reached. /// The buffer. /// The buffer offset. /// The number of bytes to read. ////// ///is . /// /// ////// is less than zero or greater than the length of . -or- ///The ///is not large enough to contain bytes starting /// at the specified . /// The stream has been disposed. /// ////// An I/O error occurred. /// public override int Read (byte[] buffer, int offset, int count) { CheckDisposed (); ValidateArguments (buffer, offset, count); return InputStream.Read (buffer, offset, count); } ////// Reads a sequence of bytes from the stream and advances the position /// within the stream by the number of bytes read. /// ///The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many /// bytes are not currently available, or zero (0) if the end of the stream has been reached. /// The buffer. /// The buffer offset. /// The number of bytes to read. /// The cancellation token. ////// ///is . /// /// ////// is less than zero or greater than the length of . -or- ///The ///is not large enough to contain bytes starting /// at the specified . /// The stream has been disposed. /// ////// An I/O error occurred. /// public override TaskReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken) { CheckDisposed (); ValidateArguments (buffer, offset, count); return InputStream.ReadAsync (buffer, offset, count, cancellationToken); } /// /// Writes a sequence of bytes to the stream and advances the current /// position within this stream by the number of bytes written. /// /// The buffer to write. /// The offset of the first byte to write. /// The number of bytes to write. ////// ///is . /// /// ////// is less than zero or greater than the length of . -or- ///The ///is not large enough to contain bytes starting /// at the specified . /// The stream has been disposed. /// ////// The stream does not support writing. /// ////// An I/O error occurred. /// public override void Write (byte[] buffer, int offset, int count) { CheckDisposed (); ValidateArguments (buffer, offset, count); OutputStream.Write (buffer, offset, count); } ////// Writes a sequence of bytes to the stream and advances the current /// position within this stream by the number of bytes written. /// ///A task that represents the asynchronous write operation. /// The buffer to write. /// The offset of the first byte to write. /// The number of bytes to write. /// The cancellation token. ////// ///is . /// /// ////// is less than zero or greater than the length of . -or- ///The ///is not large enough to contain bytes starting /// at the specified . /// The stream has been disposed. /// ////// The stream does not support writing. /// ////// An I/O error occurred. /// public override Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken) { CheckDisposed (); ValidateArguments (buffer, offset, count); return OutputStream.WriteAsync (buffer, offset, count, cancellationToken); } ////// Clears all output buffers for this stream and causes any buffered data to be written /// to the underlying device. /// ////// The stream has been disposed. /// ////// The stream does not support writing. /// ////// An I/O error occurred. /// public override void Flush () { CheckDisposed (); OutputStream.Flush (); } ////// Clears all output buffers for this stream and causes any buffered data to be written /// to the underlying device. /// ///A task that represents the asynchronous flush operation. /// The cancellation token. ////// The stream has been disposed. /// ////// The stream does not support writing. /// ////// An I/O error occurred. /// public override Task FlushAsync (CancellationToken cancellationToken) { CheckDisposed (); return OutputStream.FlushAsync (cancellationToken); } ////// Sets the position within the current stream. /// ///The new position within the stream. /// The offset into the stream relative to the. /// The origin to seek from. /// /// The stream does not support seeking. /// public override long Seek (long offset, SeekOrigin origin) { throw new NotSupportedException (); } ////// Sets the length of the stream. /// /// The desired length of the stream in bytes. ////// The stream does not support setting the length. /// public override void SetLength (long value) { throw new NotSupportedException (); } ////// Releases the unmanaged resources used by the ///and /// optionally releases the managed resources. /// to release both managed and unmanaged resources; /// to release only the unmanaged resources. protected override void Dispose (bool disposing) { if (disposing && !disposed) { OutputStream.Dispose (); InputStream.Dispose (); disposed = true; } base.Dispose (disposing); } } } ================================================ FILE: MailKit/Envelope.cs ================================================ // // Envelope.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Text; using System.Linq; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using MimeKit; using MimeKit.Utils; namespace MailKit { /// /// A message envelope containing a brief summary of the message. /// ////// The envelope of a message contains information such as the /// date the message was sent, the subject of the message, /// the sender of the message, who the message was sent to, /// which message(s) the message may be in reply to, /// and the message id. /// public class Envelope { ////// Initializes a new instance of the ///class. /// /// Creates a new public Envelope () { From = new InternetAddressList (); Sender = new InternetAddressList (); ReplyTo = new InternetAddressList (); To = new InternetAddressList (); Cc = new InternetAddressList (); Bcc = new InternetAddressList (); } ///. /// /// Gets the address(es) that the message is from. /// ////// Gets the address(es) that the message is from. /// ///The address(es) that the message is from. public InternetAddressList From { get; private set; } ////// Gets the actual sender(s) of the message. /// ////// The senders may differ from the addresses in ///if /// the message was sent by someone on behalf of someone else. /// The actual sender(s) of the message. public InternetAddressList Sender { get; private set; } ////// Gets the address(es) that replies should be sent to. /// ////// The senders of the message may prefer that replies are sent /// somewhere other than the address they used to send the message. /// ///The address(es) that replies should be sent to. public InternetAddressList ReplyTo { get; private set; } ////// Gets the list of addresses that the message was sent to. /// ////// Gets the list of addresses that the message was sent to. /// ///The address(es) that the message was sent to. public InternetAddressList To { get; private set; } ////// Gets the list of addresses that the message was carbon-copied to. /// ////// Gets the list of addresses that the message was carbon-copied to. /// ///The address(es) that the message was carbon-copied to. public InternetAddressList Cc { get; private set; } ////// Gets the list of addresses that the message was blind-carbon-copied to. /// ////// Gets the list of addresses that the message was blind-carbon-copied to. /// ///The address(es) that the message was carbon-copied to. public InternetAddressList Bcc { get; private set; } ////// The Message-Id that the message is replying to. /// ////// The Message-Id that the message is replying to. /// ///The Message-Id that the message is replying to. public string? InReplyTo { get; set; } ////// Gets the date that the message was sent on, if available. /// ////// Gets the date that the message was sent on, if available. /// ///The date the message was sent. public DateTimeOffset? Date { get; set; } ////// Gets the ID of the message, if available. /// ////// Gets the ID of the message, if available. /// ///The message identifier. public string? MessageId { get; set; } ////// Gets the subject of the message. /// ////// Gets the subject of the message. /// ///The subject. public string? Subject { get; set; } static void EncodeMailbox (StringBuilder builder, MailboxAddress mailbox) { builder.Append ('('); if (mailbox.Name != null) { MimeUtils.AppendQuoted (builder, mailbox.Name); builder.Append (' '); } else { builder.Append ("NIL "); } if (mailbox.Route.Count != 0) { MimeUtils.AppendQuoted (builder, mailbox.Route.ToString ()); builder.Append (' '); } else { builder.Append ("NIL "); } int at = mailbox.Address.LastIndexOf ('@'); if (at >= 0) { var domain = mailbox.Address.Substring (at + 1); var user = mailbox.Address.Substring (0, at); MimeUtils.AppendQuoted (builder, user); builder.Append (' '); MimeUtils.AppendQuoted (builder, domain); } else { MimeUtils.AppendQuoted (builder, mailbox.Address); builder.Append (" \"localhost\""); } builder.Append (')'); } static void EncodeInternetAddressListAddresses (StringBuilder builder, InternetAddressList addresses) { foreach (var addr in addresses) { if (addr is MailboxAddress mailbox) EncodeMailbox (builder, mailbox); else if (addr is GroupAddress group) EncodeGroup (builder, group); } } static void EncodeGroup (StringBuilder builder, GroupAddress group) { builder.Append ("(NIL NIL "); MimeUtils.AppendQuoted (builder, group.Name ?? string.Empty); builder.Append (" NIL)"); EncodeInternetAddressListAddresses (builder, group.Members); builder.Append ("(NIL NIL NIL NIL)"); } static void EncodeAddressList (StringBuilder builder, InternetAddressList list) { builder.Append ('('); EncodeInternetAddressListAddresses (builder, list); builder.Append (')'); } internal void Encode (StringBuilder builder) { builder.Append ('('); if (Date.HasValue) { builder.Append ('"'); builder.Append (DateUtils.FormatDate (Date.Value)); builder.Append ("\" "); } else { builder.Append ("NIL "); } if (Subject != null) { MimeUtils.AppendQuoted (builder, Subject); builder.Append (' '); } else { builder.Append ("NIL "); } if (From.Count > 0) { EncodeAddressList (builder, From); builder.Append (' '); } else { builder.Append ("NIL "); } if (Sender.Count > 0) { EncodeAddressList (builder, Sender); builder.Append (' '); } else { builder.Append ("NIL "); } if (ReplyTo.Count > 0) { EncodeAddressList (builder, ReplyTo); builder.Append (' '); } else { builder.Append ("NIL "); } if (To.Count > 0) { EncodeAddressList (builder, To); builder.Append (' '); } else { builder.Append ("NIL "); } if (Cc.Count > 0) { EncodeAddressList (builder, Cc); builder.Append (' '); } else { builder.Append ("NIL "); } if (Bcc.Count > 0) { EncodeAddressList (builder, Bcc); builder.Append (' '); } else { builder.Append ("NIL "); } if (InReplyTo != null) { string inReplyTo; if (InReplyTo.Length > 1 && InReplyTo[0] != '<' && InReplyTo[InReplyTo.Length - 1] != '>') inReplyTo = '<' + InReplyTo + '>'; else inReplyTo = InReplyTo; MimeUtils.AppendQuoted (builder, inReplyTo); builder.Append (' '); } else { builder.Append ("NIL "); } if (MessageId != null) { string messageId; if (MessageId.Length > 1 && MessageId[0] != '<' && MessageId[MessageId.Length - 1] != '>') messageId = '<' + MessageId + '>'; else messageId = MessageId; MimeUtils.AppendQuoted (builder, messageId); } else { builder.Append ("NIL"); } builder.Append (')'); } ////// Returns a ///that represents the current . /// /// ///The returned string can be parsed by ///. The syntax of the string returned, while similar to IMAP's ENVELOPE syntax, /// is not completely compatible. ///A public override string ToString () { var builder = new StringBuilder (); Encode (builder); return builder.ToString (); } static bool IsNIL (string text, int index) { return string.Compare (text, index, "NIL", 0, 3, StringComparison.Ordinal) == 0; } static bool TryParse (string text, ref int index, out string? nstring) { nstring = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length) return false; if (text[index] != '"') { if (index + 3 <= text.Length && IsNIL (text, index)) { index += 3; return true; } return false; } var token = new StringBuilder (); bool escaped = false; index++; while (index < text.Length) { if (text[index] == '"' && !escaped) break; if (escaped || text[index] != '\\') { token.Append (text[index]); escaped = false; } else { escaped = true; } index++; } if (index >= text.Length) return false; nstring = token.ToString (); index++; return true; } static bool TryParse (string text, ref int index, out InternetAddress? addr) { addr = null; if (text[index] != '(') return false; index++; if (!TryParse (text, ref index, out string? name)) return false; if (!TryParse (text, ref index, out string? route)) return false; if (!TryParse (text, ref index, out string? user)) return false; if (!TryParse (text, ref index, out string? domain)) return false; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length || text[index] != ')') return false; index++; if (domain != null) { user ??= "NIL"; // Note: The serializer injects "localhost" as the domain when provided a UNIX mailbox or the special <> mailbox. var address = domain == "localhost" ? user : user + "@" + domain; if (route != null && DomainList.TryParse (route, out var domains)) addr = new MailboxAddress (name, domains, address); else addr = new MailboxAddress (name, address); } else if (user != null) { addr = new GroupAddress (user); } return true; } static bool TryParse (string text, ref int index, [NotNullWhen (true)] out InternetAddressList? list) { list = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length) return false; if (text[index] != '(') { if (index + 3 <= text.Length && IsNIL (text, index)) { list = new InternetAddressList (); index += 3; return true; } return false; } index++; if (index >= text.Length) return false; list = new InternetAddressList (); var stack = new Listthat represents the current . (); int sp = 0; stack.Add (list); do { if (text[index] == ')') break; if (!TryParse (text, ref index, out InternetAddress? addr)) return false; if (addr != null) { stack[sp].Add (addr); if (addr is GroupAddress group) { stack.Add (group.Members); sp++; } } else if (sp > 0) { stack.RemoveAt (sp); sp--; } while (index < text.Length && text[index] == ' ') index++; } while (index < text.Length); // Note: technically, we should check that sp == 0 as well, since all groups should // be popped off the stack, but in the interest of being liberal in what we accept, // we'll ignore that. if (index >= text.Length) return false; index++; return true; } internal static bool TryParse (string text, ref int index, out Envelope? envelope) { DateTimeOffset? date = null; envelope = null; while (index < text.Length && text[index] == ' ') index++; if (index >= text.Length || text[index] != '(') { if (index + 3 <= text.Length && IsNIL (text, index)) { index += 3; return true; } return false; } index++; if (!TryParse (text, ref index, out string? nstring)) return false; if (nstring != null) { if (!DateUtils.TryParse (nstring, out DateTimeOffset value)) return false; date = value; } if (!TryParse (text, ref index, out string? subject)) return false; if (!TryParse (text, ref index, out InternetAddressList? from)) return false; if (!TryParse (text, ref index, out InternetAddressList? sender)) return false; if (!TryParse (text, ref index, out InternetAddressList? replyto)) return false; if (!TryParse (text, ref index, out InternetAddressList? to)) return false; if (!TryParse (text, ref index, out InternetAddressList? cc)) return false; if (!TryParse (text, ref index, out InternetAddressList? bcc)) return false; if (!TryParse (text, ref index, out string? inreplyto)) return false; if (!TryParse (text, ref index, out string? messageid)) return false; if (index >= text.Length || text[index] != ')') return false; index++; envelope = new Envelope { Date = date, Subject = subject, From = from, Sender = sender, ReplyTo = replyto, To = to, Cc = cc, Bcc = bcc, InReplyTo = inreplyto != null ? MimeUtils.EnumerateReferences (inreplyto).FirstOrDefault () ?? inreplyto : null, MessageId = messageid != null ? MimeUtils.EnumerateReferences (messageid).FirstOrDefault () ?? messageid : null }; return true; } /// /// Tries to parse the given text into a new ///instance. /// /// ///Parses an Envelope value from the specified text. ///This syntax, while similar to IMAP's ENVELOPE syntax, is not /// completely compatible. ////// The text to parse. /// The parsed envelope. /// , if the envelope was successfully parsed, otherwise. /// public static bool TryParse (string text, out Envelope? envelope) { if (text == null) throw new ArgumentNullException (nameof (text)); int index = 0; return TryParse (text, ref index, out envelope) && index == text.Length; } } } ================================================ FILE: MailKit/FetchRequest.cs ================================================ // // FetchRequest.cs // // Author: Jeffrey Stedfastis . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections.Generic; using MimeKit; namespace MailKit { /// /// A request for fetching various properties of a message. /// ////// A request for fetching various properties of a message. /// public class FetchRequest : IFetchRequest { ////// Initializes a new instance of the ///class. /// /// Creates a new public FetchRequest () { } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The items to fetch. public FetchRequest (MessageSummaryItems items) { Items = items; } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The items to fetch. /// The specific set of headers to fetch. ///. /// /// ///is . /// /// One or more of the specified public FetchRequest (MessageSummaryItems items, IEnumerableis invalid. /// headers) : this (items) { Headers = (headers is HeaderSet set) ? set : new HeaderSet (headers); } /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The items to fetch. /// The specific set of headers to fetch. ///. /// /// ///is . /// /// One or more of the specified public FetchRequest (MessageSummaryItems items, IEnumerableis invalid. /// headers) : this (items) { Headers = (headers is HeaderSet set) ? set : new HeaderSet (headers); } /// /// Get or set the mod-sequence value that indicates the last known state of the messages being requested. /// ////// ///Gets or sets the mod-sequence value that indicates the last known state of the messages being requested. ///If this property is set, the results returned by Fetch /// or FetchAsync will only include the message summaries which /// have a higher mod-sequence value than the one specified. ///If the mail store supports quick resynchronization and the application has enabled this feature via /// ///, then the Fetch or FetchAsync method /// will emit events for messages that were expunged from the folder after /// the change specified by the mod-sequence value. It should be noted that if another client has modified any message in the folder, the mail service may choose /// to return information that was not explicitly requested. It is therefore important to be prepared to handle both /// additional fields on a ///for messages that were requested as well as summaries for /// messages that were not requested at all. The mod-sequence value that indicates the last known state of the messages being requested. public ulong? ChangedSince { get; set; } ////// Get or set the message summary items to fetch. /// ////// Gets or sets the message summary items to fetch. /// ///The message summary items. public MessageSummaryItems Items { get; set; } ////// Get the set of headers that will be fetched. /// ////// Gets the set of headers that will be fetched. /// ///The set of headers to be fetched. public HeaderSet? Headers { get; set; } #if ENABLE_LAZY_PREVIEW_API ////// Get or set options to use when fetching ///. /// /// public PreviewOptions PreviewOptions { get; set; } #endif } } ================================================ FILE: MailKit/FolderAccess.cs ================================================ // // FolderMode.cs // // Author: Jeffrey StedfastGets or sets options to use when fetching ///. These options are only used if ///includes the /// value. // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // namespace MailKit { /// /// A folder access mode. /// ////// A folder access mode. /// ////// public enum FolderAccess { ///////// The folder is not open. /// None, ////// The folder is read-only. /// ReadOnly, ////// The folder is read/write. /// ReadWrite } } ================================================ FILE: MailKit/FolderAttributes.cs ================================================ // // FolderAttributes.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// Folder attributes as used by ///. /// /// Folder attributes as used by [Flags] public enum FolderAttributes { ///. /// /// The folder does not have any attributes. /// None = 0, ////// It is not possible for any subfolders to exist under the folder. /// NoInferiors = (1 << 0), ////// It is not possible to select the folder. /// NoSelect = (1 << 1), ////// The folder has been marked as possibly containing new messages /// since the folder was last selected. /// Marked = (1 << 2), ////// The folder does not contain any new messages since the folder /// was last selected. /// Unmarked = (1 << 3), ////// The folder does not exist, but is simply a place-holder. /// NonExistent = (1 << 4), ////// The folder is subscribed. /// Subscribed = (1 << 5), ////// The folder is remote. /// Remote = (1 << 6), ////// The folder has subfolders. /// HasChildren = (1 << 7), ////// The folder does not have any subfolders. /// HasNoChildren = (1 << 8), ////// The folder is a special "All" folder containing an aggregate of all messages. /// All = (1 << 9), ////// The folder is a special "Archive" folder. /// Archive = (1 << 10), ////// The folder is the special "Drafts" folder. /// Drafts = (1 << 11), ////// The folder is the special "Flagged" folder. /// Flagged = (1 << 12), ////// The folder is the special "Important" folder. /// Important = (1 << 13), ////// The folder is the special "Inbox" folder. /// Inbox = (1 << 14), ////// The folder is the special "Junk" folder. /// Junk = (1 << 15), ////// The folder is the special "Sent" folder. /// Sent = (1 << 16), ////// The folder is the special "Trash" folder. /// Trash = (1 << 17), } } ================================================ FILE: MailKit/FolderCreatedEventArgs.cs ================================================ // // FolderCreatedEventArgs.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// Event args used when a ///is created. /// /// Event args used when a public class FolderCreatedEventArgs : EventArgs { ///is created. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The newly created folder. ///. /// /// public FolderCreatedEventArgs (IMailFolder folder) { if (folder == null) throw new ArgumentNullException (nameof (folder)); Folder = folder; } ///is . /// /// Get the folder that was just created. /// ////// Gets the folder that was just created. /// ///The folder. public IMailFolder Folder { get; private set; } } } ================================================ FILE: MailKit/FolderFeature.cs ================================================ // // FolderFeature.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // namespace MailKit { /// /// An optional feature that an ///may support. /// /// An optional feature that an public enum FolderFeature { ///may support. /// /// Indicates that the folder supports access rights. /// AccessRights, ////// Indicates that the folder allows arbitrary annotations to be set on a message. /// Annotations, ////// Indicates that the folder allows arbitrary metadata to be set. /// Metadata, ////// Indicates that the folder uses modification sequences for every state change of a message. /// ModSequences, ////// Indicates that the folder supports quick resynchronization when opening. /// QuickResync, ////// Indicates that the folder supports quotas. /// Quotas, ////// Indicates that the folder supports sorting messages. /// Sorting, ////// Indicates that the folder supports threading messages. /// Threading, ////// Indicates that the folder supports the use of UTF-8. /// UTF8, } } ================================================ FILE: MailKit/FolderNamespace.cs ================================================ // // FolderNamespace.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// A folder namespace. /// ////// A folder namespace. /// public class FolderNamespace { ////// The directory separator for this folder namespace. /// ////// The directory separator for this folder namespace. /// public readonly char DirectorySeparator; ////// The base path for this folder namespace. /// ////// The base path for this folder namespace. /// public readonly string Path; ////// Initializes a new instance of the ///class. /// /// Creates a new folder namespace. /// /// The directory separator. /// The folder path. ////// public FolderNamespace (char directorySeparator, string path) { if (path == null) throw new ArgumentNullException (nameof (path)); DirectorySeparator = directorySeparator; Path = path; } } } ================================================ FILE: MailKit/FolderNamespaceCollection.cs ================================================ // // FolderNamespaceCollection.cs // // Author: Jeffrey Stedfastis . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Text; using System.Collections; using System.Collections.Generic; using MimeKit.Utils; namespace MailKit { /// /// A read-only collection of folder namespaces. /// ////// A read-only collection of folder namespaces. /// public class FolderNamespaceCollection : IEnumerable{ readonly List namespaces; /// /// Initializes a new instance of the ///class. /// /// Creates a new public FolderNamespaceCollection () { namespaces = new List. /// (); } #region ICollection implementation /// /// Gets the number of folder namespaces contained in the collection. /// ////// Gets the number of folder namespaces contained in the collection. /// ///The count. public int Count { get { return namespaces.Count; } } ////// Adds the specified namespace. /// ////// Adds the specified namespace. /// /// The namespace to add. ////// public void Add (FolderNamespace @namespace) { if (@namespace == null) throw new ArgumentNullException (nameof (@namespace)); namespaces.Add (@namespace); } ///is . /// /// Removes all namespaces from the collection. /// ////// Removes all namespaces from the collection. /// public void Clear () { namespaces.Clear (); } ////// Checks if the collection contains the specified namespace. /// ////// Checks if the collection contains the specified namespace. /// ////// The namespace. /// if the specified namespace exists; /// otherwise, . /// public bool Contains (FolderNamespace @namespace) { if (@namespace == null) throw new ArgumentNullException (nameof (@namespace)); return namespaces.Contains (@namespace); } ///is . /// /// Removes the first occurrence of the specified namespace. /// ////// Removes the first occurrence of the specified namespace. /// ////// The namespace. /// if the first occurrence of the specified /// namespace was removed; otherwise, . /// public bool Remove (FolderNamespace @namespace) { if (@namespace == null) throw new ArgumentNullException (nameof (@namespace)); return namespaces.Remove (@namespace); } ///is . /// /// Gets the ///at the specified index. /// /// Gets the ///at the specified index. /// The folder namespace at the specified index. /// The index. ////// ///is . /// /// public FolderNamespace this [int index] { get { if (index < 0 || index >= namespaces.Count) throw new ArgumentOutOfRangeException (nameof (index)); return namespaces[index]; } set { if (index < 0 || index >= namespaces.Count) throw new ArgumentOutOfRangeException (nameof (index)); if (value == null) throw new ArgumentNullException (nameof (value)); namespaces[index] = value; } } #endregion #region IEnumerable implementation ///is out of range. /// /// Gets the enumerator. /// ////// Gets the enumerator. /// ///The enumerator. public IEnumeratorGetEnumerator () { return namespaces.GetEnumerator (); } #endregion #region IEnumerable implementation /// /// Gets the enumerator. /// ////// Gets the enumerator. /// ///The enumerator. IEnumerator IEnumerable.GetEnumerator () { return namespaces.GetEnumerator (); } #endregion static bool Escape (char directorySeparator) { return directorySeparator == '\\' || directorySeparator == '"'; } ////// Returns a ///that represents the current . /// /// Returns a ///that represents the current . /// A public override string ToString () { var builder = new StringBuilder (); builder.Append ('('); for (int i = 0; i < namespaces.Count; i++) { builder.Append ("(\""); if (Escape (namespaces[i].DirectorySeparator)) builder.Append ('\\'); builder.Append (namespaces[i].DirectorySeparator); builder.Append ("\" "); MimeUtils.AppendQuoted (builder, namespaces[i].Path); builder.Append (')'); } builder.Append (')'); return builder.ToString (); } } } ================================================ FILE: MailKit/FolderNotFoundException.cs ================================================ // // FolderNotFoundException.cs // // Author: Jeffrey Stedfastthat represents the current . // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; #if SERIALIZABLE using System.Security; using System.Runtime.Serialization; #endif namespace MailKit { /// /// The exception that is thrown when a folder could not be found. /// ////// This exception is thrown by #if SERIALIZABLE [Serializable] #endif public class FolderNotFoundException : Exception { #if SERIALIZABLE ///. /// /// Initializes a new instance of the ///class. /// /// Deserializes a /// The serialization info. /// The streaming context. ///. /// /// [Obsolete ("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.")] protected FolderNotFoundException (SerializationInfo info, StreamingContext context) : base (info, context) { FolderName = info.GetString ("FolderName"); } #endif ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The error message. /// The name of the folder. /// The inner exception. ///. /// /// public FolderNotFoundException (string message, string folderName, Exception innerException) : base (message, innerException) { if (folderName == null) throw new ArgumentNullException (nameof (folderName)); FolderName = folderName; } ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The error message. /// The name of the folder. ///. /// /// public FolderNotFoundException (string message, string folderName) : base (message) { if (folderName == null) throw new ArgumentNullException (nameof (folderName)); FolderName = folderName; } ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The name of the folder. ///. /// /// public FolderNotFoundException (string folderName) : this ("The requested folder could not be found.", folderName) { } ///is . /// /// Gets the name of the folder that could not be found. /// ////// Gets the name of the folder that could not be found. /// ///The name of the folder. public string FolderName { get; private set; } #if SERIALIZABLE ////// When overridden in a derived class, sets the ////// with information about the exception. /// /// Serializes the state of the /// The serialization info. /// The streaming context. ///. /// /// [SecurityCritical] #if NET8_0_OR_GREATER [Obsolete ("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.")] #endif public override void GetObjectData (SerializationInfo info, StreamingContext context) { base.GetObjectData (info, context); info.AddValue ("FolderName", FolderName); } #endif } } ================================================ FILE: MailKit/FolderNotOpenException.cs ================================================ // // FolderNotOpenException.cs // // Author: Jeffrey Stedfastis . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; #if SERIALIZABLE using System.Runtime.Serialization; #endif namespace MailKit { /// /// The exception that is thrown when a folder is not open. /// ////// This exception is thrown when an operation on a folder could not be completed /// due to the folder being in a closed state. For example, the /// #if SERIALIZABLE [Serializable] #endif public class FolderNotOpenException : InvalidOperationException { #if SERIALIZABLE ////// method will throw a if the folder is not /// current open. /// /// Initializes a new instance of the ///class. /// /// Deserializes a /// The serialization info. /// The streaming context. ///. /// /// [Obsolete ("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.")] protected FolderNotOpenException (SerializationInfo info, StreamingContext context) : base (info, context) { var value = info.GetString ("FolderAccess"); if (!Enum.TryParse (value, out FolderAccess access)) FolderAccess = FolderAccess.ReadOnly; else FolderAccess = access; FolderName = info.GetString ("FolderName"); } #endif ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The folder name. /// The minimum folder access required by the operation. /// The error message. /// The inner exception. ///. /// /// public FolderNotOpenException (string folderName, FolderAccess access, string message, Exception innerException) : base (message, innerException) { if (folderName == null) throw new ArgumentNullException (nameof (folderName)); FolderName = folderName; FolderAccess = access; } ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The folder name. /// The minimum folder access required by the operation. /// The error message. ///. /// /// public FolderNotOpenException (string folderName, FolderAccess access, string message) : base (message) { if (folderName == null) throw new ArgumentNullException (nameof (folderName)); FolderName = folderName; FolderAccess = access; } ///is . /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The folder name. /// The minimum folder access required by the operation. ///. /// /// public FolderNotOpenException (string folderName, FolderAccess access) : this (folderName, access, GetDefaultMessage (access)) { } ///is . /// /// Get the name of the folder. /// ////// Gets the name of the folder. /// ///The name of the folder. public string FolderName { get; private set; } ////// Get the minimum folder access required by the operation. /// ////// Gets the minimum folder access required by the operation. /// ///The minimum required folder access. public FolderAccess FolderAccess { get; private set; } static string GetDefaultMessage (FolderAccess access) { if (access == FolderAccess.ReadWrite) return "The folder is not currently open in read-write mode."; return "The folder is not currently open."; } #if SERIALIZABLE ////// When overridden in a derived class, sets the ////// with information about the exception. /// /// Serializes the state of the /// The serialization info. /// The streaming context. ///. /// /// #if NET8_0_OR_GREATER [Obsolete ("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.")] #endif public override void GetObjectData (SerializationInfo info, StreamingContext context) { base.GetObjectData (info, context); info.AddValue ("FolderAccess", FolderAccess.ToString ()); info.AddValue ("FolderName", FolderName); } #endif } } ================================================ FILE: MailKit/FolderQuota.cs ================================================ // // FolderQuota.cs // // Author: Jeffrey Stedfastis . /// // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // namespace MailKit { /// /// A folder quota. /// ////// A ///is returned by . /// /// public class FolderQuota { ///////// Initializes a new instance of the ///class. /// /// Creates a new /// The quota root. public FolderQuota (IMailFolder? quotaRoot) { QuotaRoot = quotaRoot; } ///with the specified root. /// /// Get the quota root. /// ////// Gets the quota root. If the quota root is ///, then /// it suggests that the folder does not have a quota. /// /// //////The quota root. public IMailFolder? QuotaRoot { get; private set; } ////// Get or set the message limit. /// ////// Gets or sets the message limit. /// ////// //////The message limit. public uint? MessageLimit { get; set; } ////// Get or set the storage limit, in kilobytes. /// ////// Gets or sets the storage limit, in kilobytes. /// ////// //////The storage limit, in kilobytes. public uint? StorageLimit { get; set; } ////// Get or set the current message count. /// ////// Gets or sets the current message count. /// ////// //////The current message count. public uint? CurrentMessageCount { get; set; } ////// Gets or sets the size of the current storage, in kilobytes. /// ////// Gets or sets the size of the current storage, in kilobytes. /// ////// //////The size of the current storage, in kilobytes. public uint? CurrentStorageSize { get; set; } } } ================================================ FILE: MailKit/FolderRenamedEventArgs.cs ================================================ // // FolderRenamedEventArgs.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; namespace MailKit { /// /// Event args used when a ///is renamed. /// /// Event args used when a public class FolderRenamedEventArgs : EventArgs { ///is renamed. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The old name of the folder. /// The new name of the folder. ///. /// /// public FolderRenamedEventArgs (string oldName, string newName) { if (oldName == null) throw new ArgumentNullException (nameof (oldName)); if (newName == null) throw new ArgumentNullException (nameof (newName)); OldName = oldName; NewName = newName; } ////// is . -or- ////// is . /// The old name of the folder. /// ////// The old name of the folder. /// ///The old name. public string OldName { get; private set; } ////// The new name of the folder. /// ////// The new name of the folder. /// ///The new name. public string NewName { get; private set; } } } ================================================ FILE: MailKit/HeaderSet.cs ================================================ // // HeaderSet.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections; using System.Collections.Generic; using MimeKit; namespace MailKit { /// /// A set of headers. /// ////// A set of headers. /// public class HeaderSet : ICollection{ const string AtomSafeCharacters = "!#$%&'*+-/=?^_`{|}~"; /// /// A set of headers that only includes all headers. /// ////// When used with a public static readonly HeaderSet All = new HeaderSet () { Exclude = true, IsReadOnly = true }; ///, this pre-computed set of headers can be used /// to fetch the entire list of headers for a message. /// /// A set of headers that only includes the standard envelope headers. /// ////// When used with a public static readonly HeaderSet Envelope = new HeaderSet (new HeaderId[] { HeaderId.Sender, HeaderId.From, HeaderId.ReplyTo, HeaderId.To, HeaderId.Cc, HeaderId.Bcc, HeaderId.Subject, HeaderId.Date, HeaderId.MessageId, HeaderId.InReplyTo }) { IsReadOnly = true }; ///, this pre-computed set of headers can be used /// to fetch the standard envelope headers for a message. /// /// A set of headers that only includes the ///References header. ////// When used with a public static readonly HeaderSet References = new HeaderSet (new HeaderId[] { HeaderId.References }) { IsReadOnly = true }; readonly HashSet, this pre-computed set of headers can be used /// to fetch the References header for a message. Generally, this should be used in /// combination within order to have all of the /// information needed to thread messages using the /// threading algorithm. /// hash = new HashSet (StringComparer.Ordinal); bool exclude; /// /// Initializes a new instance of the ///class. /// /// Creates a new public HeaderSet () { } ///. /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The headers to include. public HeaderSet (IEnumerable. /// headers) { AddRange (headers); } /// /// Initializes a new instance of the ///class. /// /// Creates a new /// The headers to include. public HeaderSet (IEnumerable. /// headers) { AddRange (headers); } void CheckReadOnly () { if (IsReadOnly) throw new InvalidOperationException ("The HeaderSet is read-only."); } /// /// Get the number of headers in the set. /// ////// Gets the number of headers in the set. /// ///The number of headers. public int Count { get { return hash.Count; } } ////// Get or set whether this set of headers is meant to be excluded when used with a ///. /// /// Get or set whether this set of headers is meant to be excluded when used with a ///. /// /// if the headers are meant to be excluded; otherwise, . /// The operation is invalid because the public bool Exclude { get { return exclude; } set { CheckReadOnly (); exclude = value; } } ///is read-only. /// /// Get whether or not the set of headers is read-only. /// ////// Gets whether or not the set of headers is read-only. /// ///public bool IsReadOnly { get; private set; } static bool IsAsciiAtom (char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || AtomSafeCharacters.IndexOf (c) != -1; } static bool IsValid (string header) { if (header.Length == 0) return false; for (int i = 0; i < header.Length; i++) { if (header[i] < 127 && !IsAsciiAtom (header[i])) return false; } return true; } /// if this instance is read only; otherwise, . /// Add the specified header. /// ////// Adds the specified header to the set of headers. /// ////// The header to add. /// if the header was added to the set; otherwise, . /// ///is not a valid . /// /// The operation is invalid because the public bool Add (HeaderId header) { if (header == HeaderId.Unknown) throw new ArgumentOutOfRangeException (nameof (header)); CheckReadOnly (); return hash.Add (header.ToHeaderName ().ToUpperInvariant ()); } ///is read-only. /// /// Add the specified header. /// ////// Adds the specified header to the set of headers. /// ////// The header to add. /// if the header was added to the set; otherwise, . /// ///is . /// /// The operation is invalid because the public bool Add (string header) { if (header == null) throw new ArgumentNullException (nameof (header)); if (!IsValid (header)) throw new ArgumentException ("The header field is invalid.", nameof (header)); CheckReadOnly (); return hash.Add (header.ToUpperInvariant ()); } ///is read-only. /// /// Add the specified header. /// ////// Adds the specified header to the set of headers. /// /// The header to add. ////// ///is . /// /// The operation is invalid because the void ICollectionis read-only. /// .Add (string item) { Add (item); } /// /// Add a collection of headers. /// ////// Adds the specified headers to the set of headers. /// /// The headers to add. ////// ///is . /// /// One or more of the specified ///is invalid. /// /// The operation is invalid because the public void AddRange (IEnumerableis read-only. /// headers) { if (headers == null) throw new ArgumentNullException (nameof (headers)); CheckReadOnly (); foreach (var header in headers) { if (header == HeaderId.Unknown) throw new ArgumentException ("One or more of the headers is invalid.", nameof (headers)); hash.Add (header.ToHeaderName ().ToUpperInvariant ()); } } /// /// Add a collection of headers. /// ////// Adds the specified headers to the set of headers. /// /// The headers to add. ////// ///is . /// /// One or more of the specified ///is invalid. /// /// The operation is invalid because the public void AddRange (IEnumerableis read-only. /// headers) { if (headers == null) throw new ArgumentNullException (nameof (headers)); CheckReadOnly (); foreach (var header in headers) { if (header == null || !IsValid (header)) throw new ArgumentException ("One or more of the headers is invalid.", nameof (headers)); hash.Add (header.ToUpperInvariant ()); } } /// /// Clear the set of headers. /// ////// Clears the set of headers. /// ////// The operation is invalid because the public void Clear () { CheckReadOnly (); hash.Clear (); } ///is read-only. /// /// Copy all of the headers in the ///to the specified array. /// /// Copies all of the headers within the /// The array to copy the headers to. /// The index into the array. ///into the array, /// starting at the specified array index. /// /// ///is . /// /// public void CopyTo (string[] array, int arrayIndex) { hash.CopyTo (array, arrayIndex); } ///is out of range. /// /// Check if the set of headers contains the specified header. /// ////// Determines whether or not the set of headers contains the specified header. /// ////// The header identifier. /// if the specified header exists; /// otherwise, . /// public bool Contains (HeaderId header) { if (header == HeaderId.Unknown) throw new ArgumentOutOfRangeException (nameof (header)); return hash.Contains (header.ToHeaderName ().ToUpperInvariant ()); } ///is not a valid . /// /// Check if the set of headers contains the specified header. /// ////// Determines whether or not the set of headers contains the specified header. /// ////// The name of the header. /// if the specified header exists; /// otherwise, . /// public bool Contains (string header) { if (header == null) throw new ArgumentNullException (nameof (header)); return hash.Contains (header.ToUpperInvariant ()); } ///is . /// /// Remove the specified header. /// ////// Removes the specified header if it exists. /// ////// The header. /// if the specified header was removed; /// otherwise, . /// ///is not a valid . /// /// The operation is invalid because the public bool Remove (HeaderId header) { if (header == HeaderId.Unknown) throw new ArgumentOutOfRangeException (nameof (header)); CheckReadOnly (); return hash.Remove (header.ToHeaderName ().ToUpperInvariant ()); } ///is read-only. /// /// Remove the specified header. /// ////// Removes the specified header if it exists. /// ////// The header. /// if the specified header was removed; /// otherwise, . /// ///is . /// /// The operation is invalid because the public bool Remove (string header) { if (header == null) throw new ArgumentNullException (nameof (header)); CheckReadOnly (); return hash.Remove (header.ToUpperInvariant ()); } ///is read-only. /// /// Get an enumerator for the set of headers. /// ////// Gets an enumerator for the set of headers. /// ///The enumerator. public IEnumeratorGetEnumerator () { return hash.GetEnumerator (); } /// /// Get an enumerator for the set of headers. /// ////// Gets an enumerator for the set of headers. /// ///The enumerator. IEnumerator IEnumerable.GetEnumerator () { return hash.GetEnumerator (); } } } ================================================ FILE: MailKit/IAppendRequest.cs ================================================ // // IAppendRequest.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections.Generic; using MimeKit; namespace MailKit { /// /// A request for appending a message to a folder. /// ////// A request for appending a message to a folder. /// public interface IAppendRequest { ////// Get the message that should be appended to the folder. /// ////// Gets the message that should be appended to the folder. /// ///The message. MimeMessage Message { get; } ////// Get or set the message flags that should be set on the message. /// ////// Gets or sets the message flags that should be set on the message. /// ///The message flags. MessageFlags Flags { get; set; } ////// Get or set the keywords that should be set on the message. /// ////// Gets or sets the keywords that should be set on the message. /// ///The keywords. ISet? Keywords { get; set; } /// /// Get or set the timestamp that should be used by folder as the ///. /// /// Gets or sets the timestamp that should be used by folder as the ///. /// The date and time to use for the INTERNALDATE or DateTimeOffset? InternalDate { get; set; } ///if it should be left up to the folder to decide. /// Get or set the list of annotations that should be set on the message. /// ////// ///Gets or sets the list of annotations that should be set on the message. ////// ///This feature is not supported by all folders. ///Use ///with the enum value /// to determine if this feature is supported. The list of annotations. IList? Annotations { get; set; } /// /// Get or set the transfer progress reporting mechanism. /// ////// Gets or sets the transfer progress reporting mechanism. /// ///The transfer progress mechanism. ITransferProgress? TransferProgress { get; set; } } } ================================================ FILE: MailKit/IAuthenticationSecretDetector.cs ================================================ // // IAuthenticationSecretDetector.cs // // Author: Jeffrey Stedfast// // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.Collections.Generic; namespace MailKit { /// /// An authentication secret. /// ////// An authentication secret. /// public struct AuthenticationSecret { ////// Get the starting offset of the secret within a buffer. /// ////// Gets the starting offset of the secret within a buffer. /// ///The start offset of the secret. public int StartIndex { get; private set; } ////// Get the length of the secret within a buffer. /// ////// Gets the length of the secret within a buffer. /// ///The length of the secret. public int Length { get; private set; } ////// Create a new ///. /// /// Creates a new /// The start index of the secret. /// The length of the secret. public AuthenticationSecret (int startIndex, int length) { StartIndex = startIndex; Length = length; } } ///. /// /// An interface for detecting authentication secrets. /// ////// An interface for detecting authentication secrets. /// public interface IAuthenticationSecretDetector { ////// Detect a list of secrets within a buffer. /// ////// Detects a list of secrets within a buffer. /// /// The buffer. /// The buffer offset. /// The length of the buffer. ///A list of secrets. IListDetectSecrets (byte[] buffer, int offset, int count); } } ================================================ FILE: MailKit/IFetchRequest.cs ================================================ // // IFetchRequest.cs // // Author: Jeffrey Stedfast // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // namespace MailKit { /// /// A request for fetching various properties of a message. /// ////// A request for fetching various properties of a message. /// public interface IFetchRequest { ////// Get or set the mod-sequence value that indicates the last known state of the messages being requested. /// ////// ///Gets or sets the mod-sequence value that indicates the last known state of the messages being requested. ///If this property is set, the results returned by Fetch /// or FetchAsync will only include the message summaries which /// have a higher mod-sequence value than the one specified. ///If the mail store supports quick resynchronization and the application has enabled this feature via /// ///, then the Fetch or FetchAsync method /// will emit events for messages that were expunged from the folder after /// the change specified by the mod-sequence value. It should be noted that if another client has modified any message in the folder, the mail service may choose /// to return information that was not explicitly requested. It is therefore important to be prepared to handle both /// additional fields on a ///for messages that were requested as well as summaries for /// messages that were not requested at all. The mod-sequence value that indicates the last known state of the messages being requested. ulong? ChangedSince { get; set; } ////// Get or set the message summary items to fetch. /// ////// Gets or sets the message summary items to fetch. /// ///The message summary items. MessageSummaryItems Items { get; set; } ////// Get the set of headers that will be fetched. /// ////// Gets the set of headers that will be fetched. /// ///The set of headers to be fetched. HeaderSet? Headers { get; } #if ENABLE_LAZY_PREVIEW_API ////// Get the options to use when fetching ///. /// /// PreviewOptions PreviewOptions { get; } #endif } } ================================================ FILE: MailKit/IMailFolder.cs ================================================ // // IMailFolder.cs // // Author: Jeffrey StedfastGets the options to use when fetching ///. These options are only used if ///includes the /// value. // // Copyright (c) 2013-2026 .NET Foundation and Contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.IO; using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; using MimeKit; using MailKit.Search; #if NET5_0_OR_GREATER using IReadOnlySetOfStrings = System.Collections.Generic.IReadOnlySet ; #else using IReadOnlySetOfStrings = System.Collections.Generic.ISet ; #endif namespace MailKit { /// /// An interface for a mailbox folder as used by ///. /// /// Implemented by message stores such as public interface IMailFolder : IEnumerable/// { /// /// Gets an object that can be used to synchronize access to the folder. /// ////// Gets an object that can be used to synchronize access to the folder. /// ///The sync root. object SyncRoot { get; } ////// Get the parent folder. /// ////// Root-level folders do not have a parent folder. /// ///The parent folder. IMailFolder? ParentFolder { get; } ////// Get the folder attributes. /// ////// Gets the folder attributes. /// ///The folder attributes. FolderAttributes Attributes { get; } ////// Get the annotation access level. /// ////// If annotations are supported, this property can be used to determine whether or not /// the ///supports reading and writing annotations. /// The annotation access level. AnnotationAccess AnnotationAccess { get; } ////// Get the supported annotation scopes. /// ////// If annotations are supported, this property can be used to determine which /// annotation scopes are supported by the ///. /// The supported annotation scopes. AnnotationScope AnnotationScopes { get; } ////// Get the maximum size of annotation values supported by the folder. /// ////// If annotations are supported, this property can be used to determine the /// maximum size of annotation values supported by the ///. /// The maximum size of annotation values supported by the folder. uint MaxAnnotationSize { get; } ////// Get the permanent flags. /// ////// ///The permanent flags are the message flags that will persist between sessions. ///If the ///flag is set, then the folder allows /// storing of user-defined (custom) message flags. The permanent flags. MessageFlags PermanentFlags { get; } ////// Get the permanent keywords. /// ////// ///The permanent keywords are the keywords that will persist between sessions. ///If the ///flag is set in , /// then the folder allows storing of user-defined keywords as well. The permanent keywords. IReadOnlySetOfStrings PermanentKeywords { get; } ////// Get the accepted flags. /// ////// The accepted flags are the message flags that will be accepted and persist /// for the current session. For the set of flags that will persist between /// sessions, see the ///property. /// The accepted flags. MessageFlags AcceptedFlags { get; } ////// Get the accepted keywords. /// ////// The accepted keywords are the keywords that will be accepted and persist /// for the current session. For the set of keywords that will persist between /// sessions, see the ///property. /// The accepted keywords. IReadOnlySetOfStrings AcceptedKeywords { get; } ////// Get the directory separator. /// ////// Gets the directory separator. /// ///The directory separator. char DirectorySeparator { get; } ////// Get the read/write access of the folder. /// ////// Gets the read/write access of the folder. /// ///The read/write access. FolderAccess Access { get; } ////// Get whether or not the folder is a namespace folder. /// ////// Gets whether or not the folder is a namespace folder. /// ///bool IsNamespace { get; } /// if the folder is a namespace folder; otherwise, . /// Get the full name of the folder. /// ////// This is the equivalent of the full path of a file on a file system. /// ///The full name of the folder. string FullName { get; } ////// Get the name of the folder. /// ////// This is the equivalent of the file name of a file on the file system. /// ///The name of the folder. string Name { get; } ////// Get the unique identifier for the folder, if available. /// ////// ///Gets a unique identifier for the folder, if available. This is useful for clients /// implementing a message cache that want to track the folder after it is renamed by another /// client. ///This property will only be available if the server supports the /// OBJECTID extension. ///The unique folder identifier. string? Id { get; } ////// Get whether or not the folder is subscribed. /// ////// Gets whether or not the folder is subscribed. /// ///bool IsSubscribed { get; } /// if the folder is subscribed; otherwise, . /// Get whether or not the folder is currently open. /// ////// Gets whether or not the folder is currently open. /// ///bool IsOpen { get; } /// if the folder is currently open; otherwise, . /// Get whether or not the folder can be opened. /// ////// Gets whether or not the folder can be opened. /// ///bool CanOpen { get; } /// if the folder can be opened; otherwise, . /// Get whether or not the folder exists. /// ////// Gets whether or not the folder exists. /// ///bool Exists { get; } /// if the folder exists; otherwise, . /// Get the highest mod-sequence value of all messages in the mailbox. /// ////// Gets the highest mod-sequence value of all messages in the mailbox. /// ///The highest mod-sequence value. ulong HighestModSeq { get; } ////// Get the Unique ID validity. /// ////// ///UIDs are only valid so long as the UID validity value remains unchanged. If and when /// the folder's ///is changed, a client MUST discard its cache of UIDs /// along with any summary information that it may have and re-query the folder. The ///will only be set after the folder has been opened. The UID validity. uint UidValidity { get; } ////// Get the UID that the next message that is added to the folder will be assigned. /// ////// This value will only be set after the folder has been opened. /// ///The next UID. UniqueId? UidNext { get; } ////// Get the maximum size of a message that can be appended to the folder. /// ////// ///Gets the maximum size of a message that can be appended to the folder. ///If the value is not set, then the limit is unspecified. ///The append limit. uint? AppendLimit { get; } ////// Get the size of the folder. /// ////// ///Gets the size of the folder in bytes. ///If the value is not set, then the size is unspecified. ///The size of the folder, in bytes. ulong? Size { get; } ////// Get the index of the first unread message in the folder. /// ////// ///Gets the index of the first unread message in the folder. ////// This value will only be set after the folder has been opened. ///A value of -1 indicates that there are no unread messages in the folder or that the server /// has not provided the index of the first unread message.The index of the first unread message or int FirstUnread { get; } ///-1 if there are no unread messages in the folder./// Get the number of unread messages in the folder. /// ////// ///Gets the number of unread messages in the folder. ///This value will only be set after calling /// ////// with . The number of unread messages. int Unread { get; } ////// Get the number of recently delivered messages in the folder. /// ////// ///Gets the number of recently delivered messages in the folder. ////// This value will only be set after calling /// ////// with . The number of recently delivered messages. int Recent { get; } ////// Get the total number of messages in the folder. /// ////// Gets the total number of messages in the folder. /// ////// //////The total number of messages. int Count { get; } ////// Get the threading algorithms supported by the folder. /// ////// Gets the threading algorithms supported by the folder. /// ///The supported threading algorithms. HashSetThreadingAlgorithms { get; } /// /// Determine whether or not an ///supports a feature. /// /// Determines whether or not an /// The desired feature. ///supports a feature. /// bool Supports (FolderFeature feature); /// if the feature is supported; otherwise, . /// Opens the folder using the requested folder access. /// ////// ///This variant of the ////// method is meant for quick resynchronization of the folder. Before calling this method, /// the method MUST be called. You should also make sure to add listeners to the ///and /// events to get notifications of changes since /// the last time the folder was opened. The /// The requested folder access. /// The last knownstate of the folder. value. /// The last known value. /// The last known list of unique message identifiers. /// The cancellation token. /// /// ///is not a valid value. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///does not exist. /// /// The quick resynchronization feature has not been enabled. /// ////// The mail store does not support the quick resynchronization feature. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// FolderAccess Open (FolderAccess access, uint uidValidity, ulong highestModSeq, IListuids, CancellationToken cancellationToken = default); /// /// Asynchronously opens the folder using the requested folder access. /// ////// ///This variant of the ////// method is meant for quick resynchronization of the folder. Before calling this method, /// the method MUST be called. You should also make sure to add listeners to the ///and /// events to get notifications of changes since /// the last time the folder was opened. The /// The requested folder access. /// The last knownstate of the folder. value. /// The last known value. /// The last known list of unique message identifiers. /// The cancellation token. /// /// ///is not a valid value. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///does not exist. /// /// The quick resynchronization feature has not been enabled. /// ////// The mail store does not support the quick resynchronization feature. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskOpenAsync (FolderAccess access, uint uidValidity, ulong highestModSeq, IList uids, CancellationToken cancellationToken = default); /// /// Open the folder using the requested folder access. /// ////// Opens the folder using the requested folder access. /// ///The /// The requested folder access. /// The cancellation token. ///state of the folder. /// ///is not a valid value. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// FolderAccess Open (FolderAccess access, CancellationToken cancellationToken = default); ////// Asynchronously open the folder using the requested folder access. /// ////// Asynchronously opens the folder using the requested folder access. /// ///The /// The requested folder access. /// The cancellation token. ///state of the folder. /// ///is not a valid value. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskOpenAsync (FolderAccess access, CancellationToken cancellationToken = default); /// /// Close the folder, optionally expunging the messages marked for deletion. /// ////// Closes the folder, optionally expunging the messages marked for deletion. /// /// If set to, expunge. /// The cancellation token. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Close (bool expunge = false, CancellationToken cancellationToken = default); ////// Asynchronously close the folder, optionally expunging the messages marked for deletion. /// ////// Asynchronously closes the folder, optionally expunging the messages marked for deletion. /// ///An asynchronous task context. /// If set to, expunge. /// The cancellation token. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task CloseAsync (bool expunge = false, CancellationToken cancellationToken = default); ////// Create a new subfolder with the given name. /// ////// Creates a new subfolder with the given name. /// ///The created folder. /// The name of the folder to create. ///if the folder will be used to contain messages; otherwise, . /// The cancellation token. /// /// ///is . /// /// ///is empty. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is nil, and thus child folders cannot be created. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IMailFolder? Create (string name, bool isMessageFolder, CancellationToken cancellationToken = default); ////// Asynchronously create a new subfolder with the given name. /// ////// Asynchronously creates a new subfolder with the given name. /// ///The created folder. /// The name of the folder to create. ///if the folder will be used to contain messages; otherwise, . /// The cancellation token. /// /// ///is . /// /// ///is empty. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is nil, and thus child folders cannot be created. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskCreateAsync (string name, bool isMessageFolder, CancellationToken cancellationToken = default); /// /// Create a new subfolder with the given name. /// ////// Creates a new subfolder with the given name. /// ///The created folder. /// The name of the folder to create. /// A list of special uses for the folder being created. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///is empty. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is nil, and thus child folders cannot be created. /// /// The ///does not support the creation of special folders. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IMailFolder? Create (string name, IEnumerablespecialUses, CancellationToken cancellationToken = default); /// /// Asynchronously create a new subfolder with the given name. /// ////// Asynchronously creates a new subfolder with the given name. /// ///The created folder. /// The name of the folder to create. /// A list of special uses for the folder being created. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///is empty. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is nil, and thus child folders cannot be created. /// /// The ///does not support the creation of special folders. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskCreateAsync (string name, IEnumerable specialUses, CancellationToken cancellationToken = default); /// /// Create a new subfolder with the given name. /// ////// Creates a new subfolder with the given name. /// ///The created folder. /// The name of the folder to create. /// The special use for the folder being created. /// The cancellation token. ////// ///is . /// /// ///is empty. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is nil, and thus child folders cannot be created. /// /// The ///does not support the creation of special folders. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IMailFolder? Create (string name, SpecialFolder specialUse, CancellationToken cancellationToken = default); ////// Asynchronously create a new subfolder with the given name. /// ////// Asynchronously creates a new subfolder with the given name. /// ///The created folder. /// The name of the folder to create. /// The special use for the folder being created. /// The cancellation token. ////// ///is . /// /// ///is empty. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is nil, and thus child folders cannot be created. /// /// The ///does not support the creation of special folders. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskCreateAsync (string name, SpecialFolder specialUse, CancellationToken cancellationToken = default); /// /// Rename the folder. /// ////// Renames the folder. /// /// The new parent folder. /// The new name of the folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ////// does not belong to the . -or- ////// is not a legal folder name. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder cannot be renamed (it is either a namespace or the Inbox). /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Rename (IMailFolder parent, string name, CancellationToken cancellationToken = default); ////// Asynchronously rename the folder. /// ////// Asynchronously renames the folder. /// ///An asynchronous task context. /// The new parent folder. /// The new name of the folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ////// does not belong to the . -or- ////// is not a legal folder name. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder cannot be renamed (it is either a namespace or the Inbox). /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task RenameAsync (IMailFolder parent, string name, CancellationToken cancellationToken = default); ////// Delete the folder. /// ////// Deletes the folder. /// /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder cannot be deleted (it is either a namespace or the Inbox). /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Delete (CancellationToken cancellationToken = default); ////// Asynchronously delete the folder. /// ////// Asynchronously deletes the folder. /// ///An asynchronous task context. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder cannot be deleted (it is either a namespace or the Inbox). /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task DeleteAsync (CancellationToken cancellationToken = default); ////// Subscribe to the folder. /// ////// Subscribes to the folder. /// /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Subscribe (CancellationToken cancellationToken = default); ////// Asynchronously subscribe to the folder. /// ////// Asynchronously subscribes to the folder. /// ///An asynchronous task context. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder cannot be deleted (it is either a namespace or the Inbox). /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task SubscribeAsync (CancellationToken cancellationToken = default); ////// Unsubscribe from the folder. /// ////// Unsubscribes from the folder. /// /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Unsubscribe (CancellationToken cancellationToken = default); ////// Asynchronously unsubscribe from the folder. /// ////// Asynchronously unsubscribes from the folder. /// ///An asynchronous task context. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task UnsubscribeAsync (CancellationToken cancellationToken = default); ////// Get the subfolders. /// ////// ///Gets the subfolders as well as queries the server for the status of the requested items. ///When the ///argument is non-empty, this has the equivalent functionality /// of calling and then calling /// on each of the returned folders. Using this method is potentially more efficient than querying the status of each returned folder. ///The subfolders. /// The status items to pre-populate. /// If set to, only subscribed folders will be listed. /// The cancellation token. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListGetSubfolders (StatusItems items, bool subscribedOnly = false, CancellationToken cancellationToken = default); /// /// Asynchronously get the subfolders. /// ////// ///Asynchronously gets the subfolders as well as queries the server for the status of the requested items. ///When the ///argument is non-empty, this has the equivalent functionality /// of calling and then calling /// on each of the returned folders. The subfolders. /// The status items to pre-populate. /// If set to, only subscribed folders will be listed. /// The cancellation token. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> GetSubfoldersAsync (StatusItems items, bool subscribedOnly = false, CancellationToken cancellationToken = default); /// /// Get the subfolders. /// ////// Gets the subfolders. /// ///The subfolders. /// If set to, only subscribed folders will be listed. /// The cancellation token. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListGetSubfolders (bool subscribedOnly = false, CancellationToken cancellationToken = default); /// /// Asynchronously get the subfolders. /// ////// Asynchronously gets the subfolders. /// ///The subfolders. /// If set to, only subscribed folders will be listed. /// The cancellation token. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> GetSubfoldersAsync (bool subscribedOnly = false, CancellationToken cancellationToken = default); /// /// Get the specified subfolder. /// ////// Gets the specified subfolder. /// ///The subfolder. /// The name of the subfolder. /// The cancellation token. ////// ///is . /// /// ///is either an empty string or contains the . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The requested folder could not be found. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IMailFolder GetSubfolder (string name, CancellationToken cancellationToken = default); ////// Asynchronously get the specified subfolder. /// ////// Asynchronously gets the specified subfolder. /// ///The subfolder. /// The name of the subfolder. /// The cancellation token. ////// ///is . /// /// ///is either an empty string or contains the . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The requested folder could not be found. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetSubfolderAsync (string name, CancellationToken cancellationToken = default); /// /// Force the server to flush its state for the folder. /// ////// Forces the server to flush its state for the folder. /// /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Check (CancellationToken cancellationToken = default); ////// Asynchronously force the server to flush its state for the folder. /// ////// Asynchronously forces the server to flush its state for the folder. /// ///An asynchronous task context. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task CheckAsync (CancellationToken cancellationToken = default); ////// Update the values of the specified items. /// ////// /// The items to update. /// The cancellation token. ///Updates the values of the specified items. ///The ///method /// MUST NOT be used on a folder that is already in the opened state. Instead, other ways /// of getting the desired information should be used. For example, a common use for the ////// method is to get the number of unread messages in the folder. When the folder is open, however, it is /// possible to use the /// method to query for the list of unread messages. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///does not exist. /// /// The mail store does not support the STATUS command. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Status (StatusItems items, CancellationToken cancellationToken = default); ////// Asynchronously update the values of the specified items. /// ////// ///Updates the values of the specified items. ///The ///method /// MUST NOT be used on a folder that is already in the opened state. Instead, other ways /// of getting the desired information should be used. For example, a common use for the ////// method is to get the number of unread messages in the folder. When the folder is open, however, it is /// possible to use the /// method to query for the list of unread messages. An asynchronous task context. /// The items to update. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///does not exist. /// /// The mail store does not support the STATUS command. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task StatusAsync (StatusItems items, CancellationToken cancellationToken = default); ////// Get the complete access control list for the folder. /// ////// Gets the complete access control list for the folder. /// ///The access control list. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// AccessControlList GetAccessControlList (CancellationToken cancellationToken = default); ////// Asynchronously get the complete access control list for the folder. /// ////// Asynchronously gets the complete access control list for the folder. /// ///The access control list. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetAccessControlListAsync (CancellationToken cancellationToken = default); /// /// Get the access rights for a particular identifier. /// ////// Gets the access rights for a particular identifier. /// ///The access rights. /// The identifier name. /// The cancellation token. ////// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// AccessRights GetAccessRights (string name, CancellationToken cancellationToken = default); ////// Asynchronously get the access rights for a particular identifier. /// ////// Asynchronously gets the access rights for a particular identifier. /// ///The access rights. /// The identifier name. /// The cancellation token. ////// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetAccessRightsAsync (string name, CancellationToken cancellationToken = default); /// /// Get the access rights for the current authenticated user. /// ////// Gets the access rights for the current authenticated user. /// ///The access rights. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// AccessRights GetMyAccessRights (CancellationToken cancellationToken = default); ////// Asynchronously get the access rights for the current authenticated user. /// ////// Asynchronously gets the access rights for the current authenticated user. /// ///The access rights. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetMyAccessRightsAsync (CancellationToken cancellationToken = default); /// /// Add access rights for the specified identity. /// ////// Adds the given access rights for the specified identity. /// /// The identity name. /// The access rights. /// The cancellation token. ////// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void AddAccessRights (string name, AccessRights rights, CancellationToken cancellationToken = default); ////// Asynchronously add access rights for the specified identity. /// ////// Asynchronously adds the given access rights for the specified identity. /// ///An asynchronous task context. /// The identity name. /// The access rights. /// The cancellation token. ////// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task AddAccessRightsAsync (string name, AccessRights rights, CancellationToken cancellationToken = default); ////// Remove access rights for the specified identity. /// ////// Removes the given access rights for the specified identity. /// /// The identity name. /// The access rights. /// The cancellation token. ////// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void RemoveAccessRights (string name, AccessRights rights, CancellationToken cancellationToken = default); ////// Asynchronously remove access rights for the specified identity. /// ////// Asynchronously removes the given access rights for the specified identity. /// ///An asynchronous task context. /// The identity name. /// The access rights. /// The cancellation token. ////// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task RemoveAccessRightsAsync (string name, AccessRights rights, CancellationToken cancellationToken = default); ////// Set the access rights for the specified identity. /// ////// Sets the access rights for the specified identity. /// /// The identity name. /// The access rights. /// The cancellation token. ////// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void SetAccessRights (string name, AccessRights rights, CancellationToken cancellationToken = default); ////// Asynchronously set the access rights for the specified identity. /// ////// Asynchronously sets the access rights for the specified identity. /// ///An asynchronous task context. /// The identity name. /// The access rights. /// The cancellation token. ////// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task SetAccessRightsAsync (string name, AccessRights rights, CancellationToken cancellationToken = default); ////// Remove all access rights for the given identity. /// ////// Removes all access rights for the given identity. /// /// The identity name. /// The cancellation token. ////// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void RemoveAccess (string name, CancellationToken cancellationToken = default); ////// Asynchronously remove all access rights for the given identity. /// ////// Asynchronously removes all access rights for the given identity. /// ///An asynchronous task context. /// The identity name. /// The cancellation token. ////// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support the ACL extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task RemoveAccessAsync (string name, CancellationToken cancellationToken = default); ////// Get the quota information for the folder. /// ////// ///Gets the quota information for the folder. ///To determine if a quotas are supported, check the /// ///property. The folder quota. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support quotas. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// FolderQuota GetQuota (CancellationToken cancellationToken = default); ////// Asynchronously get the quota information for the folder. /// ////// ///Asynchronously gets the quota information for the folder. ///To determine if a quotas are supported, check the /// ///property. The folder quota. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support quotas. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetQuotaAsync (CancellationToken cancellationToken = default); /// /// Set the quota limits for the folder. /// ////// ///Sets the quota limits for the folder. ///To determine if a quotas are supported, check the /// ///property. The updated folder quota. /// If not, sets the maximum number of messages to allow. /// If not , sets the maximum storage size (in kilobytes). /// The cancellation token. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support quotas. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// FolderQuota SetQuota (uint? messageLimit, uint? storageLimit, CancellationToken cancellationToken = default); ////// Asynchronously set the quota limits for the folder. /// ////// ///Asynchronously sets the quota limits for the folder. ///To determine if a quotas are supported, check the /// ///property. The updated folder quota. /// If not, sets the maximum number of messages to allow. /// If not , sets the maximum storage size (in kilobytes). /// The cancellation token. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The mail store does not support quotas. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskSetQuotaAsync (uint? messageLimit, uint? storageLimit, CancellationToken cancellationToken = default); /// /// Gets the specified metadata. /// ////// Gets the specified metadata. /// ///The requested metadata value. /// The metadata tag. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder does not support metadata. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// string? GetMetadata (MetadataTag tag, CancellationToken cancellationToken = default); ////// Asynchronously gets the specified metadata. /// ////// Asynchronously gets the specified metadata. /// ///The requested metadata value. /// The metadata tag. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder does not support metadata. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetMetadataAsync (MetadataTag tag, CancellationToken cancellationToken = default); /// /// Gets the specified metadata. /// ////// Gets the specified metadata. /// ///The requested metadata. /// The metadata tags. /// The cancellation token. ////// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder does not support metadata. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// MetadataCollection GetMetadata (IEnumerabletags, CancellationToken cancellationToken = default); /// /// Asynchronously gets the specified metadata. /// ////// Asynchronously gets the specified metadata. /// ///The requested metadata. /// The metadata tags. /// The cancellation token. ////// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder does not support metadata. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetMetadataAsync (IEnumerable tags, CancellationToken cancellationToken = default); /// /// Gets the specified metadata. /// ////// Gets the specified metadata. /// ///The requested metadata. /// The metadata options. /// The metadata tags. /// The cancellation token. ////// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder does not support metadata. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// MetadataCollection GetMetadata (MetadataOptions options, IEnumerabletags, CancellationToken cancellationToken = default); /// /// Asynchronously gets the specified metadata. /// ////// Asynchronously gets the specified metadata. /// ///The requested metadata. /// The metadata options. /// The metadata tags. /// The cancellation token. ////// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder does not support metadata. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetMetadataAsync (MetadataOptions options, IEnumerable tags, CancellationToken cancellationToken = default); /// /// Sets the specified metadata. /// ////// Sets the specified metadata. /// /// The metadata. /// The cancellation token. ////// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder does not support metadata. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void SetMetadata (MetadataCollection metadata, CancellationToken cancellationToken = default); ////// Asynchronously sets the specified metadata. /// ////// Asynchronously sets the specified metadata. /// ///An asynchronous task context. /// The metadata. /// The cancellation token. ////// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder does not support metadata. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task SetMetadataAsync (MetadataCollection metadata, CancellationToken cancellationToken = default); ////// Expunge the folder, permanently removing all messages marked for deletion. /// ////// /// The cancellation token. ///Expunges the folder, permanently removing all messages marked for deletion. ///Normally, an ///event will be emitted for each /// message that is expunged. However, if the mail store supports the quick /// resynchronization feature and it has been enabled via the /// method, then /// the event will be emitted rather than the /// event. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Expunge (CancellationToken cancellationToken = default); ////// Asynchronously expunge the folder, permanently removing all messages marked for deletion. /// ////// ///Asynchronously expunges the folder, permanently removing all messages marked for deletion. ///Normally, an ///event will be emitted for /// each message that is expunged. However, if the mail store supports the quick /// resynchronization feature and it has been enabled via the /// method, then /// the event will be emitted rather than the /// event. An asynchronous task context. /// The cancellation token. ////// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task ExpungeAsync (CancellationToken cancellationToken = default); ////// Expunge the specified uids, permanently removing them from the folder. /// ////// /// The message uids. /// The cancellation token. ///Expunges the specified uids, permanently removing them from the folder. ///Normally, an ///event will be emitted for /// each message that is expunged. However, if the mail store supports the quick /// resynchronization feature and it has been enabled via the /// method, then /// the event will be emitted rather than the /// event. /// ///is . /// /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Expunge (IListuids, CancellationToken cancellationToken = default); /// /// Asynchronously expunge the specified uids, permanently removing them from the folder. /// ////// ///Asynchronously expunges the specified uids, permanently removing them from the folder. ///Normally, an ///event will be emitted for /// each message that is expunged. However, if the mail store supports the quick /// resynchronization feature and it has been enabled via the /// method, then /// the event will be emitted rather than the /// event. An asynchronous task context. /// The message uids. /// The cancellation token. ////// ///is . /// /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task ExpungeAsync (IListuids, CancellationToken cancellationToken = default); /// /// Append a message to the folder. /// ////// Appends a message to the folder and returns the UniqueId assigned to the message. /// ///The UID of the appended message, if available; otherwise, /// The append request. /// The cancellation token. ///. /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ///-or- ///The request included annotations but the folder does not support annotations. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// UniqueId? Append (IAppendRequest request, CancellationToken cancellationToken = default); ////// Asynchronously append a message to the folder. /// ////// Asynchronously appends a message to the folder and returns the UniqueId assigned to the message. /// ///The UID of the appended message, if available; otherwise, /// The append request. /// The cancellation token. ///. /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ///-or- ///The request included annotations but the folder does not support annotations. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskAppendAsync (IAppendRequest request, CancellationToken cancellationToken = default); /// /// Append a message to the folder. /// ////// Appends a message to the folder and returns the UniqueId assigned to the message. /// ///The UID of the appended message, if available; otherwise, /// The formatting options. /// The append request. /// The cancellation token. ///. /// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ///-or- ///The request included annotations but the folder does not support annotations. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// UniqueId? Append (FormatOptions options, IAppendRequest request, CancellationToken cancellationToken = default); ////// Asynchronously append a message to the folder. /// ////// Asynchronously appends a message to the folder and returns the UniqueId assigned to the message. /// ///The UID of the appended message, if available; otherwise, /// The formatting options. /// The append request. /// The cancellation token. ///. /// ////// is . -or- ////// is . /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ///-or- ///The request included annotations but the folder does not support annotations. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskAppendAsync (FormatOptions options, IAppendRequest request, CancellationToken cancellationToken = default); /// /// Append multiple messages to the folder. /// ////// Appends multiple messages to the folder and returns the UniqueIds assigned to each of the messages. /// ///The UIDs of the appended messages, if available; otherwise, an empty array. /// The append requests. /// The cancellation token. ////// ///is . /// /// One or more of the ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ///-or- ///One ore more requests included annotations but the folder does not support annotations. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListAppend (IList requests, CancellationToken cancellationToken = default); /// /// Asynchronously append multiple messages to the folder. /// ////// Asynchronously appends multiple messages to the folder and returns the UniqueIds assigned to each of the messages. /// ///The UID of the appended message, if available; otherwise, an empty array. /// The append requests. /// The cancellation token. ////// ///is . /// /// One or more of the ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ///-or- ///One ore more requests included annotations but the folder does not support annotations. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> AppendAsync (IList requests, CancellationToken cancellationToken = default); /// /// Append multiple messages to the folder. /// ////// Appends multiple messages to the folder and returns the UniqueIds assigned to each of the messages. /// ///The UIDs of the appended messages, if available; otherwise, an empty array. /// The formatting options. /// The append requests. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ///-or- ///One ore more requests included annotations but the folder does not support annotations. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListAppend (FormatOptions options, IList requests, CancellationToken cancellationToken = default); /// /// Asynchronously append multiple messages to the folder. /// ////// Asynchronously appends multiple messages to the folder and returns the UniqueIds assigned to each of the messages. /// ///The UID of the appended message, if available; otherwise, an empty array. /// The formatting options. /// The append requests. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ///-or- ///One ore more requests included annotations but the folder does not support annotations. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> AppendAsync (FormatOptions options, IList requests, CancellationToken cancellationToken = default); /// /// Replace a message in the folder. /// ////// Replaces a message in the folder and returns the UniqueId assigned to the new message. /// ///The UID of the new message, if available; otherwise, /// The UID of the message to be replaced. /// The replace request. /// The cancellation token. ///. /// ////// is . /// ////// is invalid. -or- ///The destination folder does not belong to this ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The ///is not currently open in read-write mode. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The server replied with a NO or BAD response. /// UniqueId? Replace (UniqueId uid, IReplaceRequest request, CancellationToken cancellationToken = default); ////// Asynchronously replace a message in the folder. /// ////// Asynchronously replaces a message in the folder and returns the UniqueId assigned to the new message. /// ///The UID of the appended message, if available; otherwise, /// The UID of the message to be replaced. /// The replace request. /// The cancellation token. ///. /// ////// is . /// ////// is invalid. -or- ///The destination folder does not belong to this ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The ///is not currently open in read-write mode. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The server replied with a NO or BAD response. /// TaskReplaceAsync (UniqueId uid, IReplaceRequest request, CancellationToken cancellationToken = default); /// /// Replace a message in the folder. /// ////// Replaces a message in the folder and returns the UniqueId assigned to the new message. /// ///The UID of the new message, if available; otherwise, /// The formatting options. /// The UID of the message to be replaced. /// The replace request. /// The cancellation token. ///. /// ////// is . -or- ////// is . /// ////// is invalid. -or- ///The destination folder does not belong to this ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The ///is not currently open in read-write mode. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The server replied with a NO or BAD response. /// UniqueId? Replace (FormatOptions options, UniqueId uid, IReplaceRequest request, CancellationToken cancellationToken = default); ////// Asynchronously replace a message in the folder. /// ////// Asynchronously replaces a message in the folder and returns the UniqueId assigned to the new message. /// ///The UID of the new message, if available; otherwise, /// The formatting options. /// The UID of the message to be replaced. /// The replace request. /// The cancellation token. ///. /// ////// is . -or- ////// is . /// ////// is invalid. -or- ///The destination folder does not belong to this ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The ///is not currently open in read-write mode. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The server replied with a NO or BAD response. /// TaskReplaceAsync (FormatOptions options, UniqueId uid, IReplaceRequest request, CancellationToken cancellationToken = default); /// /// Replace a message in the folder. /// ////// Replaces a message in the folder and returns the UniqueId assigned to the new message. /// ///The UID of the new message, if available; otherwise, /// The index of the message to be replaced. /// The replace request. /// The cancellation token. ///. /// ////// is . /// ///is out of range. /// /// The destination folder does not belong to this ///. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The ///is not currently open in read-write mode. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The server replied with a NO or BAD response. /// UniqueId? Replace (int index, IReplaceRequest request, CancellationToken cancellationToken = default); ////// Asynchronously replace a message in the folder. /// ////// Asynchronously replaces a message in the folder and returns the UniqueId assigned to the new message. /// ///The UID of the appended message, if available; otherwise, /// The index of the message to be replaced. /// The replace request. /// The cancellation token. ///. /// ////// is . /// ///is out of range. /// /// The destination folder does not belong to this ///. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The ///is not currently open in read-write mode. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The server replied with a NO or BAD response. /// TaskReplaceAsync (int index, IReplaceRequest request, CancellationToken cancellationToken = default); /// /// Replace a message in the folder. /// ////// Replaces a message in the folder and returns the UniqueId assigned to the new message. /// ///The UID of the new message, if available; otherwise, /// The formatting options. /// The index of the message to be replaced. /// The replace request. /// The cancellation token. ///. /// ////// is . -or- ////// is . /// ///is out of range. /// /// The destination folder does not belong to this ///. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The ///is not currently open in read-write mode. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The server replied with a NO or BAD response. /// UniqueId? Replace (FormatOptions options, int index, IReplaceRequest request, CancellationToken cancellationToken = default); ////// Asynchronously replace a message in the folder. /// ////// Asynchronously replaces a message in the folder and returns the UniqueId assigned to the new message. /// ///The UID of the new message, if available; otherwise, /// The formatting options. /// The index of the message to be replaced. /// The replace request. /// The cancellation token. ///. /// ////// is . -or- ////// is . /// ///is out of range. /// /// The destination folder does not belong to this ///. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// Internationalized formatting was requested but has not been enabled. /// ////// The ///does not exist. /// /// The ///is not currently open in read-write mode. /// /// The operation was canceled via the cancellation token. /// ////// ///Internationalized formatting was requested but is not supported by the server. ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The server replied with a NO or BAD response. /// TaskReplaceAsync (FormatOptions options, int index, IReplaceRequest request, CancellationToken cancellationToken = default); /// /// Copy the specified message to the destination folder. /// ////// Copies the specified message to the destination folder. /// ///The UID of the message in the destination folder, if available; otherwise, /// The UID of the message to copy. /// The destination folder. /// The cancellation token. ///. /// ///is . /// /// ////// is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The mail store does not support the UIDPLUS extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// UniqueId? CopyTo (UniqueId uid, IMailFolder destination, CancellationToken cancellationToken = default); ////// Asynchronously copy the specified message to the destination folder. /// ////// Asynchronously copies the specified message to the destination folder. /// ///The UID of the message in the destination folder, if available; otherwise, /// The UID of the message to copy. /// The destination folder. /// The cancellation token. ///. /// ///is . /// /// ////// is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The mail store does not support the UIDPLUS extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskCopyToAsync (UniqueId uid, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Copy the specified messages to the destination folder. /// ////// Copies the specified messages to the destination folder. /// ///The UID mapping of the messages in the destination folder, if available; otherwise an empty mapping. /// The UIDs of the messages to copy. /// The destination folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///One or more of the ///is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The mail store does not support the UIDPLUS extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// UniqueIdMap CopyTo (IListuids, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Asynchronously copy the specified messages to the destination folder. /// ////// Asynchronously copies the specified messages to the destination folder. /// ///The UID mapping of the messages in the destination folder, if available; otherwise an empty mapping. /// The UIDs of the messages to copy. /// The destination folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///One or more of the ///is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The mail store does not support the UIDPLUS extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskCopyToAsync (IList uids, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Move the specified message to the destination folder. /// ////// Moves the specified message to the destination folder. /// ///The UID of the message in the destination folder, if available; otherwise, /// The UID of the message to move. /// The destination folder. /// The cancellation token. ///. /// ///is . /// /// ////// is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The mail store does not support the UIDPLUS extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// UniqueId? MoveTo (UniqueId uid, IMailFolder destination, CancellationToken cancellationToken = default); ////// Asynchronously move the specified message to the destination folder. /// ////// Asynchronously moves the specified message to the destination folder. /// ///The UID of the message in the destination folder, if available; otherwise, /// The UID of the message to move. /// The destination folder. /// The cancellation token. ///. /// ///is . /// /// ////// is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The mail store does not support the UIDPLUS extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskMoveToAsync (UniqueId uid, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Move the specified messages to the destination folder. /// ////// Moves the specified messages to the destination folder. /// ///The UID mapping of the messages in the destination folder, if available; otherwise an empty mapping. /// The UIDs of the messages to copy. /// The destination folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///One or more of the ///is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The mail store does not support the UIDPLUS extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// UniqueIdMap MoveTo (IListuids, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Asynchronously move the specified messages to the destination folder. /// ////// Asynchronously moves the specified messages to the destination folder. /// ///The UID mapping of the messages in the destination folder, if available; otherwise an empty mapping. /// The UIDs of the messages to copy. /// The destination folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///One or more of the ///is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The mail store does not support the UIDPLUS extension. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskMoveToAsync (IList uids, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Copy the specified message to the destination folder. /// ////// Copies the specified message to the destination folder. /// /// The index of the message to copy. /// The destination folder. /// The cancellation token. ////// ///is . /// /// ///does not refer to a valid message index. /// /// The destination folder does not belong to the ///. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void CopyTo (int index, IMailFolder destination, CancellationToken cancellationToken = default); ////// Asynchronously copy the specified message to the destination folder. /// ////// Asynchronously copies the specified message to the destination folder. /// ///An asynchronous task context. /// The indexes of the message to copy. /// The destination folder. /// The cancellation token. ////// ///is . /// /// ///does not refer to a valid message index. /// /// The destination folder does not belong to the ///. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task CopyToAsync (int index, IMailFolder destination, CancellationToken cancellationToken = default); ////// Copy the specified messages to the destination folder. /// ////// Copies the specified messages to the destination folder. /// /// The indexes of the messages to copy. /// The destination folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///One or more of the ///is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void CopyTo (IListindexes, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Asynchronously copy the specified messages to the destination folder. /// ////// Asynchronously copies the specified messages to the destination folder. /// ///An asynchronous task context. /// The indexes of the messages to copy. /// The destination folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///One or more of the ///is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task CopyToAsync (IListindexes, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Move the specified message to the destination folder. /// ////// Moves the specified message to the destination folder. /// /// The index of the message to move. /// The destination folder. /// The cancellation token. ////// ///is . /// /// ///does not refer to a valid message index. /// /// The destination folder does not belong to the ///. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void MoveTo (int index, IMailFolder destination, CancellationToken cancellationToken = default); ////// Asynchronously move the specified message to the destination folder. /// ////// Asynchronously moves the specified message to the destination folder. /// ///An asynchronous task context. /// The index of the message to move. /// The destination folder. /// The cancellation token. ////// ///is . /// /// ///does not refer to a valid message index. /// /// The destination folder does not belong to the ///. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task MoveToAsync (int index, IMailFolder destination, CancellationToken cancellationToken = default); ////// Move the specified messages to the destination folder. /// ////// Moves the specified messages to the destination folder. /// /// The indexes of the messages to move. /// The destination folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///One or more of the ///is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void MoveTo (IListindexes, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Asynchronously move the specified messages to the destination folder. /// ////// Asynchronously moves the specified messages to the destination folder. /// ///An asynchronous task context. /// The indexes of the messages to move. /// The destination folder. /// The cancellation token. ////// ////// is . -or- ////// is . /// ///One or more of the ///is invalid. -or- ///The destination folder does not belong to the ///. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task MoveToAsync (IListindexes, IMailFolder destination, CancellationToken cancellationToken = default); /// /// Fetch the message summaries for the specified message UIDs. /// ////// ///Fetches the message summaries for the specified message UIDs. ///It should be noted that if another client has modified any message /// in the folder, the mail service may choose to return information that was /// not explicitly requested. It is therefore important to be prepared to /// handle both additional fields on a ///for /// messages that were requested as well as summaries for messages that were /// not requested at all. /// //////An enumeration of summaries for the requested messages. /// The UIDs. /// The fetch request. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListFetch (IList uids, IFetchRequest request, CancellationToken cancellationToken = default); /// /// Asynchronously fetch the message summaries for the specified message UIDs. /// ////// ///Asynchronously fetches the message summaries for the specified message /// UIDs. ///It should be noted that if another client has modified any message /// in the folder, the mail service may choose to return information that was /// not explicitly requested. It is therefore important to be prepared to /// handle both additional fields on a ///for /// messages that were requested as well as summaries for messages that were /// not requested at all. An enumeration of summaries for the requested messages. /// The UIDs. /// The fetch request. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> FetchAsync (IList uids, IFetchRequest request, CancellationToken cancellationToken = default); /// /// Fetch the message summaries for the specified message indexes. /// ////// ///Fetches the message summaries for the specified message indexes. ///It should be noted that if another client has modified any message /// in the folder, the mail service may choose to return information that was /// not explicitly requested. It is therefore important to be prepared to /// handle both additional fields on a ///for /// messages that were requested as well as summaries for messages that were /// not requested at all. An enumeration of summaries for the requested messages. /// The indexes. /// The fetch request. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListFetch (IList indexes, IFetchRequest request, CancellationToken cancellationToken = default); /// /// Asynchronously fetch the message summaries for the specified message indexes. /// ////// ///Asynchronously fetches the message summaries for the specified message /// indexes. ///It should be noted that if another client has modified any message /// in the folder, the mail service may choose to return information that was /// not explicitly requested. It is therefore important to be prepared to /// handle both additional fields on a ///for /// messages that were requested as well as summaries for messages that were /// not requested at all. An enumeration of summaries for the requested messages. /// The indexes. /// The fetch request. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> FetchAsync (IList indexes, IFetchRequest request, CancellationToken cancellationToken = default); /// /// Fetch the message summaries for the messages between the two indexes, inclusive. /// ////// ///Fetches the message summaries for the messages between the two /// indexes, inclusive. ///It should be noted that if another client has modified any message /// in the folder, the mail service may choose to return information that was /// not explicitly requested. It is therefore important to be prepared to /// handle both additional fields on a ///for /// messages that were requested as well as summaries for messages that were /// not requested at all. An enumeration of summaries for the requested messages. /// The minimum index. /// The maximum index, or-1 to specify no upper bound. /// The fetch request. /// The cancellation token. ////// ///is . /// /// ////// is out of range. -or- ////// is out of range. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListFetch (int min, int max, IFetchRequest request, CancellationToken cancellationToken = default); /// /// Asynchronously fetch the message summaries for the messages between the two indexes, inclusive. /// ////// ///Asynchronously fetches the message summaries for the messages between /// the two indexes, inclusive. ///It should be noted that if another client has modified any message /// in the folder, the mail service may choose to return information that was /// not explicitly requested. It is therefore important to be prepared to /// handle both additional fields on a ///for /// messages that were requested as well as summaries for messages that were /// not requested at all. An enumeration of summaries for the requested messages. /// The minimum index. /// The maximum index, or-1 to specify no upper bound. /// The fetch request. /// The cancellation token. ////// ///is . /// /// ////// is out of range. -or- ////// is out of range. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> FetchAsync (int min, int max, IFetchRequest request, CancellationToken cancellationToken = default); /// /// Get the specified message headers. /// ////// Gets the specified message headers. /// ///The message headers. /// The UID of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message headers. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// HeaderList GetHeaders (UniqueId uid, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get the specified message headers. /// ////// Asynchronously gets the specified message headers. /// ///The message headers. /// The UID of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message headers. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetHeadersAsync (UniqueId uid, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get the specified body part headers. /// ////// Gets the specified body part headers. /// ///The body part headers. /// The UID of the message. /// The body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested body part headers. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// HeaderList GetHeaders (UniqueId uid, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get the specified body part headers. /// ////// Asynchronously gets the specified body part headers. /// ///The body part headers. /// The UID of the message. /// The body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested body part headers. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetHeadersAsync (UniqueId uid, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get the specified message headers. /// ////// Gets the specified message headers. /// ///The message headers. /// The index of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is out of range. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message headers. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// HeaderList GetHeaders (int index, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get the specified message headers. /// ////// Asynchronously gets the specified message headers. /// ///The message headers. /// The index of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is out of range. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message headers. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetHeadersAsync (int index, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get the specified body part headers. /// ////// Gets the specified body part headers. /// ///The body part headers. /// The index of the message. /// The body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is out of range. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested body part headers. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// HeaderList GetHeaders (int index, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get the specified body part headers. /// ////// Asynchronously gets the specified body part headers. /// ///The body part headers. /// The index of the message. /// The body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is out of range. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested body part headers. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetHeadersAsync (int index, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get the specified message. /// ////// Gets the specified message. /// ////// //////The message. /// The UID of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// MimeMessage GetMessage (UniqueId uid, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get the specified message. /// ////// Asynchronously gets the specified message. /// ////// //////The message. /// The UID of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetMessageAsync (UniqueId uid, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get the specified message. /// ////// Gets the specified message. /// ////// //////The message. /// The index of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is out of range. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// MimeMessage GetMessage (int index, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get the specified message. /// ////// Asynchronously gets the specified message. /// ////// //////The message. /// The index of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is out of range. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetMessageAsync (int index, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get the specified body part. /// ////// Gets the specified body part. /// ////// //////The body part. /// The UID of the message. /// The body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message body. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// MimeEntity GetBodyPart (UniqueId uid, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get the specified body part. /// ////// Asynchronously gets the specified body part. /// ////// //////The body part. /// The UID of the message. /// The body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message body. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetBodyPartAsync (UniqueId uid, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get the specified body part. /// ////// Gets the specified body part. /// ///The body part. /// The index of the message. /// The body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ///is out of range. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message body. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// MimeEntity GetBodyPart (int index, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get the specified body part. /// ////// Asynchronously gets the specified body part. /// ///The body part. /// The index of the message. /// The body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ///is out of range. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message body. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetBodyPartAsync (int index, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a message stream. /// ////// Gets a message stream. /// ////// //////The message stream. /// The UID of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (UniqueId uid, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a message stream. /// ////// Asynchronously gets a message stream. /// ////// //////The message stream. /// The UID of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (UniqueId uid, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a message stream. /// ////// Gets a message stream. /// ////// //////The message stream. /// The index of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ////// is out of range. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (int index, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a message stream. /// ////// Asynchronously gets a message stream. /// ////// //////The message stream. /// The index of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ////// is out of range. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (int index, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a substream of the specified message. /// ////// Gets a substream of the message. If the starting offset is beyond /// the end of the message, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the message, a truncated stream /// will be returned. /// ///The stream. /// The UID of the message. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (UniqueId uid, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a substream of the specified message. /// ////// Asynchronously gets a substream of the message. If the starting offset is beyond /// the end of the message, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the message, a truncated stream /// will be returned. /// ///The stream. /// The UID of the message. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (UniqueId uid, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a substream of the specified message. /// ////// Gets a substream of the message. If the starting offset is beyond /// the end of the message, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the message, a truncated stream /// will be returned. /// ///The stream. /// The index of the message. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ////// is out of range. -or- ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (int index, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a substream of the specified message. /// ////// Asynchronously gets a substream of the message. If the starting offset is beyond /// the end of the message, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the message, a truncated stream /// will be returned. /// ///The stream. /// The index of the message. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ////// is out of range. -or- ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (int index, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a body part as a stream. /// ////// Gets a body part as a stream. /// ////// //////The body part stream. /// The UID of the message. /// The desired body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (UniqueId uid, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a body part as a stream. /// ////// Asynchronously gets a body part as a stream. /// ////// //////The body part stream. /// The UID of the message. /// The desired body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (UniqueId uid, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a body part as a stream. /// ////// Gets a body part as a stream. /// ///The body part stream. /// The index of the message. /// The desired body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ////// is out of range. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (int index, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a body part as a stream. /// ////// Asynchronously gets a body part as a stream. /// ///The body part stream. /// The index of the message. /// The desired body part. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ////// is out of range. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (int index, BodyPart part, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a substream of the specified body part. /// ////// Gets a substream of the body part. If the starting offset is beyond /// the end of the body part, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the body part, a truncated stream /// will be returned. /// ///The stream. /// The UID of the message. /// The desired body part. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ///is . /// /// ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (UniqueId uid, BodyPart part, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a substream of the specified body part. /// ////// Asynchronously gets a substream of the body part. If the starting offset is beyond /// the end of the body part, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the body part, a truncated stream /// will be returned. /// ///The stream. /// The UID of the message. /// The desired body part. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ///is . /// /// ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (UniqueId uid, BodyPart part, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a substream of the specified body part. /// ////// Gets a substream of the body part. If the starting offset is beyond /// the end of the body part, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the body part, a truncated stream /// will be returned. /// ///The stream. /// The index of the message. /// The desired body part. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ////// is out of range. -or- ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (int index, BodyPart part, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a substream of the specified body part. /// ////// Asynchronously gets a substream of the body part. If the starting offset is beyond /// the end of the body part, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the body part, a truncated stream /// will be returned. /// ///The stream. /// The index of the message. /// The desired body part. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ////// is out of range. -or- ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (int index, BodyPart part, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a substream of the specified message. /// ////// ///Gets a substream of the specified message. ///For more information about how to construct the ///, /// see Section 6.4.5 of RFC3501. /// //////The stream. /// The UID of the message. /// The desired section of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (UniqueId uid, string section, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a substream of the specified message. /// ////// ///Asynchronously gets a substream of the specified message. ///For more information about how to construct the ///, /// see Section 6.4.5 of RFC3501. /// //////The stream. /// The UID of the message. /// The desired section of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (UniqueId uid, string section, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a substream of the specified message. /// ////// ///Gets a substream of the specified message. If the starting offset is beyond /// the end of the specified section of the message, an empty stream is returned. If /// the number of bytes desired extends beyond the end of the section, a truncated /// stream will be returned. ///For more information about how to construct the ///, /// see Section 6.4.5 of RFC3501. The stream. /// The UID of the message. /// The desired section of the message. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ///is . /// /// ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (UniqueId uid, string section, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a substream of the specified message. /// ////// ///Asynchronously gets a substream of the specified message. If the starting /// offset is beyond the end of the specified section of the message, an empty stream /// is returned. If the number of bytes desired extends beyond the end of the section, /// a truncated stream will be returned. ///For more information about how to construct the ///, /// see Section 6.4.5 of RFC3501. The stream. /// The UID of the message. /// The desired section of the message. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is invalid. /// /// ///is . /// /// ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (UniqueId uid, string section, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a substream of the specified message. /// ////// ///Gets a substream of the specified message. ///For more information about how to construct the ///, /// see Section 6.4.5 of RFC3501. The stream. /// The index of the message. /// The desired section of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ///is out of range. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (int index, string section, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a substream of the specified message. /// ////// ///Asynchronously gets a substream of the specified message. ///For more information about how to construct the ///, /// see Section 6.4.5 of RFC3501. The stream. /// The index of the message. /// The desired section of the message. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ///is out of range. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (int index, string section, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Get a substream of the specified message. /// ////// ///Gets a substream of the specified message. If the starting offset is beyond /// the end of the specified section of the message, an empty stream is returned. If /// the number of bytes desired extends beyond the end of the section, a truncated /// stream will be returned. ///For more information about how to construct the ///, /// see Section 6.4.5 of RFC3501. The stream. /// The index of the message. /// The desired section of the message. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ////// is out of range. -or- ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Stream GetStream (int index, string section, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); ////// Asynchronously get a substream of the specified message. /// ////// ///Asynchronously gets a substream of the specified message. If the starting /// offset is beyond the end of the specified section of the message, an empty stream /// is returned. If the number of bytes desired extends beyond the end of the section, /// a truncated stream will be returned. ///For more information about how to construct the ///, /// see Section 6.4.5 of RFC3501. The stream. /// The index of the message. /// The desired section of the message. /// The starting offset of the first desired byte. /// The number of bytes desired. /// The cancellation token. /// The progress reporting mechanism. ////// ///is . /// /// ////// is out of range. -or- ////// is negative. -or- ////// is negative. /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The ///did not return the requested message stream. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskGetStreamAsync (int index, string section, int offset, int count, CancellationToken cancellationToken = default, ITransferProgress? progress = null); /// /// Store message flags and keywords for a message. /// ////// Updates the message flags and keywords for a message. /// ////// The UID of the message. /// The message flags and keywords to store. /// The cancellation token. /// if the store operation was successful; otherwise, . /// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The ///specified an /// value but the folder does not support mod-sequences. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// bool Store (UniqueId uid, IStoreFlagsRequest request, CancellationToken cancellationToken = default); ////// Asynchronously store message flags and keywords for a message. /// ////// Asynchronously updates the message flags and keywords for a message. /// ////// The UID of the message. /// The message flags and keywords to store. /// The cancellation token. /// if the store operation was successful; otherwise, . /// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The ///specified an /// value but the folder does not support mod-sequences. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskStoreAsync (UniqueId uid, IStoreFlagsRequest request, CancellationToken cancellationToken = default); /// /// Store message flags and keywords for a set of messages. /// ////// Updates the message flags and keywords for a set of messages. /// ///The UIDs of the messages that were not updated. /// The message UIDs. /// The message flags and keywords to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The ///specified an /// value but the folder does not support mod-sequences. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListStore (IList uids, IStoreFlagsRequest request, CancellationToken cancellationToken = default); /// /// Asynchronously store message flags and keywords for a set of messages. /// ////// Asynchronously updates the message flags and keywords for a set of messages. /// ///The UIDs of the messages that were not updated. /// The message UIDs. /// The message flags and keywords to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The ///specified an /// value but the folder does not support mod-sequences. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> StoreAsync (IList uids, IStoreFlagsRequest request, CancellationToken cancellationToken = default); /// /// Store message flags and keywords for a message. /// ////// Updates the message flags and keywords for a message. /// ////// The index of the message. /// The message flags and keywords to store. /// The cancellation token. /// if the store operation was successful; otherwise, . /// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The ///specified an /// value but the folder does not support mod-sequences. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// bool Store (int index, IStoreFlagsRequest request, CancellationToken cancellationToken = default); ////// Asynchronously store message flags and keywords for a message. /// ////// Asynchronously updates the message flags and keywords for a message. /// ////// The index of the message. /// The message flags and keywords to store. /// The cancellation token. /// if the store operation was successful; otherwise, . /// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The ///specified an /// value but the folder does not support mod-sequences. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskStoreAsync (int index, IStoreFlagsRequest request, CancellationToken cancellationToken = default); /// /// Store message flags and keywords for a set of messages. /// ////// Updates the message flags and keywords for a set of messages. /// ///The indexes of the messages that were not updated. /// The message indexes. /// The message flags and keywords to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The ///specified an /// value but the folder does not support mod-sequences. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListStore (IList indexes, IStoreFlagsRequest request, CancellationToken cancellationToken = default); /// /// Asynchronously store message flags and keywords for a set of messages. /// ////// Asynchronously updates the message flags and keywords for a set of message. /// ///The indexes of the messages that were not updated. /// The message indexes. /// The message flags and keywords to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// The ///specified an /// value but the folder does not support mod-sequences. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> StoreAsync (IList indexes, IStoreFlagsRequest request, CancellationToken cancellationToken = default); /// /// Store GMail-style labels for a message. /// ////// Updates the GMail-style labels for a message. /// ////// The UID of the message. /// The labels to store. /// The cancellation token. /// if the store operation was successful; otherwise, . /// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// ///The folder does not support storing labels. ///-or- ///The ///specified an /// value but the folder does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// bool Store (UniqueId uid, IStoreLabelsRequest request, CancellationToken cancellationToken = default); ////// Asynchronously store GMail-style labels for a message. /// ////// Asynchronously updates the GMail-style labels for a message. /// ////// The UID of the message. /// The labels to store. /// The cancellation token. /// if the store operation was successful; otherwise, . /// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// ///The folder does not support storing labels. ///-or- ///The ///specified an /// value but the folder does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskStoreAsync (UniqueId uid, IStoreLabelsRequest request, CancellationToken cancellationToken = default); /// /// Store GMail-style labels for a set of messages. /// ////// Updates the GMail-style labels for a set of messages. /// ///The UIDs of the messages that were not updated. /// The message UIDs. /// The labels to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// ///The folder does not support storing labels. ///-or- ///The ///specified an /// value but the folder does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListStore (IList uids, IStoreLabelsRequest request, CancellationToken cancellationToken = default); /// /// Asynchronously store GMail-style labels for a set of messages. /// ////// Asynchronously updates the GMail-style labels for a set of messages. /// ///The UIDs of the messages that were not updated. /// The message UIDs. /// The labels to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// ///The folder does not support storing labels. ///-or- ///The ///specified an /// value but the folder does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> StoreAsync (IList uids, IStoreLabelsRequest request, CancellationToken cancellationToken = default); /// /// Store GMail-style labels for a message. /// ////// Updates the GMail-style labels for a message. /// ////// The index of the message. /// The labels to store. /// The cancellation token. /// if the store operation was successful; otherwise, . /// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// ///The folder does not support storing labels. ///-or- ///The ///specified an /// value but the folder does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// bool Store (int index, IStoreLabelsRequest request, CancellationToken cancellationToken = default); ////// Asynchronously store GMail-style labels for a message. /// ////// Asynchronously updates the GMail-style labels for a message. /// ////// The index of the message. /// The labels to store. /// The cancellation token. /// if the store operation was successful; otherwise, . /// ///is invalid. /// /// ///is . /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// ///The folder does not support storing labels. ///-or- ///The ///specified an /// value but the folder does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// TaskStoreAsync (int index, IStoreLabelsRequest request, CancellationToken cancellationToken = default); /// /// Store GMail-style labels for a set of messages. /// ////// Updates the GMail-style labels for a set of messages. /// ///The indexes of the messages that were not updated. /// The message indexes. /// The labels to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// ///The folder does not support storing labels. ///-or- ///The ///specified an /// value but the folder does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListStore (IList indexes, IStoreLabelsRequest request, CancellationToken cancellationToken = default); /// /// Asynchronously store GMail-style labels for a set of messages. /// ////// Asynchronously updates the GMail-style labels for a set of message. /// ///The indexes of the messages that were not updated. /// The message indexes. /// The labels to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open in read-write mode. /// ////// ///The folder does not support storing labels. ///-or- ///The ///specified an /// value but the folder does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> StoreAsync (IList indexes, IStoreLabelsRequest request, CancellationToken cancellationToken = default); /// /// Store the annotations for the specified message. /// ////// Stores the annotations for the specified message. /// /// The UID of the message. /// The annotations to store. /// The cancellation token. ////// ///is . /// /// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// The ///does not support annotations. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Store (UniqueId uid, IListannotations, CancellationToken cancellationToken = default); /// /// Asynchronously store the annotations for the specified message. /// ////// Asynchronously stores the annotations for the specified message. /// ///An asynchronous task context. /// The UID of the message. /// The annotations to store. /// The cancellation token. ////// ///is . /// /// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// The ///does not support annotations. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task StoreAsync (UniqueId uid, IListannotations, CancellationToken cancellationToken = default); /// /// Store the annotations for the specified messages. /// ////// Stores the annotations for the specified messages. /// /// The UIDs of the messages. /// The annotations to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// The ///does not support annotations. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Store (IListuids, IList annotations, CancellationToken cancellationToken = default); /// /// Asynchronously store the annotations for the specified messages. /// ////// Asynchronously stores the annotations for the specified messages. /// ///An asynchronous task context. /// The UIDs of the messages. /// The annotations to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// The ///does not support annotations. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task StoreAsync (IListuids, IList annotations, CancellationToken cancellationToken = default); /// /// Store the annotations for the specified messages only if their mod-sequence value is less than the specified value. /// ////// Stores the annotations for the specified messages only if their mod-sequence value is less than the specified value. /// ///The unique IDs of the messages that were not updated. /// The UIDs of the messages. /// The mod-sequence value. /// The annotations to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// ///The ///does not support annotations. -or- ///The ///does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListStore (IList uids, ulong modseq, IList annotations, CancellationToken cancellationToken = default); /// /// Asynchronously store the annotations for the specified messages only if their mod-sequence value is less than the specified value. /// ////// Asynchronously stores the annotations for the specified messages only if their mod-sequence value is less than the specified value. /// ///The unique IDs of the messages that were not updated. /// The UIDs of the messages. /// The mod-sequence value. /// The annotations to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// ///The ///does not support annotations. -or- ///The ///does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> StoreAsync (IList uids, ulong modseq, IList annotations, CancellationToken cancellationToken = default); /// /// Store the annotations for the specified message. /// ////// Stores the annotations for the specified message. /// /// The index of the message. /// The annotations to store. /// The cancellation token. ////// ///is . /// /// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// The ///does not support annotations. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Store (int index, IListannotations, CancellationToken cancellationToken = default); /// /// Asynchronously store the annotations for the specified message. /// ////// Asynchronously stores the annotations for the specified message. /// ///An asynchronous task context. /// The indexes of the message. /// The annotations to store. /// The cancellation token. ////// ///is . /// /// ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// The ///does not support annotations. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task StoreAsync (int index, IListannotations, CancellationToken cancellationToken = default); /// /// Store the annotations for the specified messages. /// ////// Stores the annotations for the specified messages. /// /// The indexes of the messages. /// The annotations to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// The ///does not support annotations. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// void Store (IListindexes, IList annotations, CancellationToken cancellationToken = default); /// /// Asynchronously store the annotations for the specified messages. /// ////// Asynchronously stores the annotations for the specified messages. /// ///An asynchronous task context. /// The indexes of the messages. /// The annotations to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// The ///does not support annotations. /// /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task StoreAsync (IListindexes, IList annotations, CancellationToken cancellationToken = default); /// /// Store the annotations for the specified messages only if their mod-sequence value is less than the specified value. /// ////// Stores the annotations for the specified messages only if their mod-sequence value is less than the specified value. /// ///The indexes of the messages that were not updated. /// The indexes of the messages. /// The mod-sequence value. /// The annotations to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// ///The ///does not support annotations. -or- ///The ///does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListStore (IList indexes, ulong modseq, IList annotations, CancellationToken cancellationToken = default); /// /// Asynchronously store the annotations for the specified messages only if their mod-sequence value is less than the specified value. /// ////// Asynchronously stores the annotations for the specified messages only if their mod-sequence value is less than the specified value.s /// ///The indexes of the messages that were not updated. /// The indexes of the messages. /// The mod-sequence value. /// The annotations to store. /// The cancellation token. ////// ////// is . -or- ////// is . /// One or more of the ///is invalid. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The ///is not currently open in read-write mode. /// /// Cannot store annotations without any properties defined. /// ////// ///The ///does not support annotations. -or- ///The ///does not support mod-sequences. /// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> StoreAsync (IList indexes, ulong modseq, IList annotations, CancellationToken cancellationToken = default); /// /// Search the folder for messages matching the specified query. /// ////// The returned array of unique identifiers can be used with methods such as /// ///. /// An array of matching UIDs. /// The search query. /// The cancellation token. ////// ///is . /// /// One or more search terms in the ///are not supported by the mail store. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListSearch (SearchQuery query, CancellationToken cancellationToken = default); /// /// Asynchronously search the folder for messages matching the specified query. /// ////// The returned array of unique identifiers can be used with methods such as /// ///. /// An array of matching UIDs. /// The search query. /// The cancellation token. ////// ///is . /// /// One or more search terms in the ///are not supported by the mail store. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// Task> SearchAsync (SearchQuery query, CancellationToken cancellationToken = default); /// /// Search the subset of UIDs in the folder for messages matching the specified query. /// ////// The returned array of unique identifiers can be used with methods such as /// ///. /// An array of matching UIDs. /// The subset of UIDs /// The search query. /// The cancellation token. ////// ////// is . -or- ////// is . /// ////// is empty. -or- ///One or more of the ///is invalid. /// One or more search terms in the ///are not supported by the mail store. /// /// The ///has been disposed. /// /// The ///is not connected. /// /// The ///is not authenticated. /// /// The folder is not currently open. /// ////// The operation was canceled via the cancellation token. /// ////// An I/O error occurred. /// ////// The server's response contained unexpected tokens. /// ////// The command failed. /// IListSearch (IList uids, SearchQuery query, CancellationToken cancellationToken = default); /// /// Asynchronously search the subset of UIDs in the folder for messages matching the specified query. /// ////// The returned array of unique identifiers can be used with methods such as ///