コード例 #1
0
ファイル: MultipartSigned.cs プロジェクト: gphummer/MimeKit
		static void PrepareEntityForSigning (MimeEntity entity)
		{
			if (entity is Multipart) {
				// Note: we do not want to modify multipart/signed parts
				if (entity is MultipartSigned)
					return;

				var multipart = (Multipart) entity;

				foreach (var subpart in multipart)
					PrepareEntityForSigning (subpart);
			} else if (entity is MessagePart) {
				var mpart = (MessagePart) entity;

				if (mpart.Message != null && mpart.Message.Body != null)
					PrepareEntityForSigning (mpart.Message.Body);
			} else {
				var part = (MimePart) entity;

				switch (part.ContentTransferEncoding) {
				case ContentEncoding.SevenBit:
					// need to make sure that "From "-lines are properly armored
					part.ContentTransferEncoding = part.GetBestEncoding (EncodingConstraint.SevenBit);
					break;
				case ContentEncoding.EightBit:
					part.ContentTransferEncoding = ContentEncoding.QuotedPrintable;
					break;
				case ContentEncoding.Binary:
					part.ContentTransferEncoding = ContentEncoding.Base64;
					break;
				}
			}
		}
コード例 #2
0
		static void PrepareEntityForEncrypting (MimeEntity entity)
		{
			if (entity is Multipart) {
				// Note: we do not want to modify multipart/signed parts
				if (entity is MultipartSigned)
					return;

				var multipart = (Multipart) entity;

				foreach (var subpart in multipart)
					PrepareEntityForEncrypting (subpart);
			} else if (entity is MessagePart) {
				var mpart = (MessagePart) entity;

				if (mpart.Message != null && mpart.Message.Body != null)
					PrepareEntityForEncrypting (mpart.Message.Body);
			} else {
				var part = (MimePart) entity;

				if (part.ContentTransferEncoding == ContentEncoding.Binary)
					part.ContentTransferEncoding = ContentEncoding.Base64;
				else if (part.ContentTransferEncoding != ContentEncoding.Base64)
					part.ContentTransferEncoding = ContentEncoding.QuotedPrintable;
			}
		}
コード例 #3
0
		/// <summary>
		/// Encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Encrypts the entity to the specified recipients using the default <see cref="SecureMimeContext"/>.
		/// </remarks>
		/// <returns>The encrypted entity.</returns>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Encrypt (CmsRecipientCollection recipients, MimeEntity entity)
		{
			if (recipients == null)
				throw new ArgumentNullException (nameof (recipients));

			if (entity == null)
				throw new ArgumentNullException (nameof (entity));

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return Encrypt (ctx, recipients, entity);
			}
		}
コード例 #4
0
ファイル: MultipartSigned.cs プロジェクト: gphummer/MimeKit
		/// <summary>
		/// Creates a new <see cref="MultipartSigned"/>.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs the entity using the supplied signer in order
		/// to generate a detached signature and then adds the entity along with
		/// the detached signature data to a new multipart/signed part.
		/// </remarks>
		/// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
		/// <param name="ctx">The S/MIME context to use for signing.</param>
		/// <param name="signer">The signer.</param>
		/// <param name="entity">The entity to sign.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static MultipartSigned Create (SecureMimeContext ctx, CmsSigner signer, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			PrepareEntityForSigning (entity);

			using (var memory = new MemoryBlockStream ()) {
				using (var filtered = new FilteredStream (memory)) {
					// Note: see rfc3156, section 3 - second note
					filtered.Add (new ArmoredFromFilter ());

					// Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156)
					filtered.Add (new TrailingWhitespaceFilter ());

					// Note: see rfc2015 or rfc3156, section 5.1
					filtered.Add (new Unix2DosFilter ());

					entity.WriteTo (filtered);
					filtered.Flush ();
				}

				memory.Position = 0;

				// Note: we need to parse the modified entity structure to preserve any modifications
				var parser = new MimeParser (memory, MimeFormat.Entity);
				var parsed = parser.ParseEntity ();
				memory.Position = 0;

				// sign the cleartext content
				var micalg = ctx.GetDigestAlgorithmName (signer.DigestAlgorithm);
				var signature = ctx.Sign (signer, memory);
				var signed = new MultipartSigned ();

				// set the protocol and micalg Content-Type parameters
				signed.ContentType.Parameters["protocol"] = ctx.SignatureProtocol;
				signed.ContentType.Parameters["micalg"] = micalg;

				// add the modified/parsed entity as our first part
				signed.Add (parsed);

				// add the detached signature as the second part
				signed.Add (signature);

				return signed;
			}
		}
コード例 #5
0
        /// <summary>
        /// Constructs specified entity and it's childentities bodystructure string.
        /// </summary>
        /// <param name="entity">Mime entity.</param>
        /// <param name="bodystructure">Specifies if to construct BODY or BODYSTRUCTURE.</param>
        /// <returns></returns>
        private static string ConstructParts(MimeEntity entity, bool bodystructure)
        {
            /* RFC 3501 7.4.2 BODYSTRUCTURE
             *                                            BODY A form of BODYSTRUCTURE without extension data.
             *
             *                  A parenthesized list that describes the [MIME-IMB] body
             *                  structure of a message.  This is computed by the server by
             *                  parsing the [MIME-IMB] header fields, defaulting various fields
             *                  as necessary.
             *
             *                  For example, a simple text message of 48 lines and 2279 octets
             *                  can have a body structure of: ("TEXT" "PLAIN" ("CHARSET"
             *                  "US-ASCII") NIL NIL "7BIT" 2279 48)
             *
             *                  Multiple parts are indicated by parenthesis nesting.  Instead
             *                  of a body type as the first element of the parenthesized list,
             *                  there is a sequence of one or more nested body structures.  The
             *                  second element of the parenthesized list is the multipart
             *                  subtype (mixed, digest, parallel, alternative, etc.).
             *
             *                  For example, a two part message consisting of a text and a
             *                  BASE64-encoded text attachment can have a body structure of:
             *                  (("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152
             *                  23)("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "cc.diff")
             *                  "<*****@*****.**>" "Compiler diff"
             *                  "BASE64" 4554 73) "MIXED")
             *
             *                  Extension data follows the multipart subtype.  Extension data
             *                  is never returned with the BODY fetch, but can be returned with
             *                  a BODYSTRUCTURE fetch.  Extension data, if present, MUST be in
             *                  the defined order.  The extension data of a multipart body part
             *                  are in the following order:
             *
             *                  body parameter parenthesized list
             *                          A parenthesized list of attribute/value pairs [e.g., ("foo"
             *                          "bar" "baz" "rag") where "bar" is the value of "foo", and
             *                          "rag" is the value of "baz"] as defined in [MIME-IMB].
             *
             *                  body disposition
             *                          A parenthesized list, consisting of a disposition type
             *                          string, followed by a parenthesized list of disposition
             *                          attribute/value pairs as defined in [DISPOSITION].
             *
             *                  body language
             *                          A string or parenthesized list giving the body language
             *                          value as defined in [LANGUAGE-TAGS].
             *
             *                  body location
             *                          A string list giving the body content URI as defined in [LOCATION].
             *
             *                  Any following extension data are not yet defined in this
             *                  version of the protocol.  Such extension data can consist of
             *                  zero or more NILs, strings, numbers, or potentially nested
             *                  parenthesized lists of such data.  Client implementations that
             *                  do a BODYSTRUCTURE fetch MUST be prepared to accept such
             *                  extension data.  Server implementations MUST NOT send such
             *                  extension data until it has been defined by a revision of this
             *                  protocol.
             *
             *                  The basic fields of a non-multipart body part are in the
             *                  following order:
             *
             *                  body type
             *                          A string giving the content media type name as defined in [MIME-IMB].
             *
             *                  body subtype
             *                           A string giving the content subtype name as defined in [MIME-IMB].
             *
             *                  body parameter parenthesized list
             *                          A parenthesized list of attribute/value pairs [e.g., ("foo"
             *                          "bar" "baz" "rag") where "bar" is the value of "foo" and
             *                          "rag" is the value of "baz"] as defined in [MIME-IMB].
             *
             *                  body id
             *                          A string giving the content id as defined in [MIME-IMB].
             *
             *                  body description
             *                          A string giving the content description as defined in [MIME-IMB].
             *
             *                  body encoding
             *                          A string giving the content transfer encoding as defined in	[MIME-IMB].
             *
             *                  body size
             *                          A number giving the size of the body in octets.  Note that
             *                          this size is the size in its transfer encoding and not the
             *                          resulting size after any decoding.
             *
             *                  A body type of type MESSAGE and subtype RFC822 contains,
             *                  immediately after the basic fields, the envelope structure,
             *                  body structure, and size in text lines of the encapsulated
             *                  message.
             *
             *                  A body type of type TEXT contains, immediately after the basic
             *                  fields, the size of the body in text lines.  Note that this
             *                  size is the size in its content transfer encoding and not the
             *                  resulting size after any decoding.
             *
             *                  Extension data follows the basic fields and the type-specific
             *                  fields listed above.  Extension data is never returned with the
             *                  BODY fetch, but can be returned with a BODYSTRUCTURE fetch.
             *                  Extension data, if present, MUST be in the defined order.
             *
             *                  The extension data of a non-multipart body part are in the
             *                  following order:
             *
             *                  body MD5
             *                          A string giving the body MD5 value as defined in [MD5].
             *
             *                  body disposition
             *                          A parenthesized list with the same content and function as
             *                          the body disposition for a multipart body part.
             *
             *                  body language
             *                          A string or parenthesized list giving the body language
             *                          value as defined in [LANGUAGE-TAGS].
             *
             *                  body location
             *                          A string list giving the body content URI as defined in [LOCATION].
             *
             *                  Any following extension data are not yet defined in this
             *                  version of the protocol, and would be as described above under
             *                  multipart extension data.
             *
             *
             *                  // We don't construct extention fields like rfc says:
             *                          Server implementations MUST NOT send such
             *                          extension data until it has been defined by a revision of this
             *                          protocol.
             *
             *
             *                  contentTypeMainMediaType - Example: 'TEXT'
             *                  contentTypeSubMediaType  - Example: 'PLAIN'
             *                  conentTypeParameters     - Example: '("CHARSET" "iso-8859-1" ...)'
             *                  contentID                - Content-ID: header field value.
             *                  contentDescription       - Content-Description: header field value.
             *                  contentEncoding          - Content-Transfer-Encoding: header field value.
             *                  contentSize              - mimeEntity ENCODED data size
             *                  [envelope]               - NOTE: included only if contentType = "message" !!!
             *                  [contentLines]           - number of ENCODED data lines. NOTE: included only if contentType = "text" !!!
             *
             *                  // Basic fields for multipart
             *                  (nestedMimeEntries) contentTypeSubMediaType
             *
             *                  // Basic fields for non-multipart
             *                  contentTypeMainMediaType contentTypeSubMediaType (conentTypeParameters) contentID contentDescription contentEncoding contentSize [envelope] [contentLine]
             *
             */

            StringBuilder retVal = new StringBuilder();

            // Multipart message
            if ((entity.ContentType & MediaType_enum.Multipart) != 0)
            {
                retVal.Append("(");

                // Construct child entities.
                foreach (MimeEntity childEntity in entity.ChildEntities)
                {
                    // Construct child entity. This can be multipart or non multipart.
                    retVal.Append(ConstructParts(childEntity, bodystructure));
                }

                // Add contentTypeSubMediaType
                string contentType = entity.ContentTypeString.Split(';')[0];
                if (contentType.Split('/').Length == 2)
                {
                    retVal.Append(" \"" + contentType.Split('/')[1].Replace(";", "") + "\"");
                }
                else
                {
                    retVal.Append(" NIL");
                }

                retVal.Append(")");
            }
            // Single part message
            else
            {
                retVal.Append("(");

                // NOTE: all header fields and parameters must in ENCODED form !!!

                // Add contentTypeMainMediaType
                if (entity.ContentTypeString != null)
                {
                    string contentType = entity.ContentTypeString.Split(';')[0];
                    if (contentType.Split('/').Length == 2)
                    {
                        retVal.Append("\"" + entity.ContentTypeString.Split('/')[0] + "\"");
                    }
                    else
                    {
                        retVal.Append("NIL");
                    }
                }
                else
                {
                    retVal.Append("NIL");
                }

                // contentTypeSubMediaType
                if (entity.ContentTypeString != null)
                {
                    string contentType = entity.ContentTypeString.Split(';')[0];
                    if (contentType.Split('/').Length == 2)
                    {
                        retVal.Append(" \"" + contentType.Split('/')[1].Replace(";", "") + "\"");
                    }
                    else
                    {
                        retVal.Append(" NIL");
                    }
                }
                else
                {
                    retVal.Append(" NIL");
                }

                // conentTypeParameters - Syntax: {("name" SP "value" *(SP "name" SP "value"))}
                if (entity.ContentTypeString != null)
                {
                    ParametizedHeaderField contentTypeParameters =
                        new ParametizedHeaderField(entity.Header.GetFirst("Content-Type:"));
                    if (contentTypeParameters.Parameters.Count > 0)
                    {
                        retVal.Append(" (");

                        bool first = true;
                        foreach (HeaderFieldParameter param in contentTypeParameters.Parameters)
                        {
                            // For first item, don't add SP
                            if (!first)
                            {
                                retVal.Append(" ");
                            }
                            else
                            {
                                // Clear first flag
                                first = false;
                            }

                            retVal.Append("\"" + param.Name + "\" \"" +
                                          MimeUtils.EncodeHeaderField(param.Value) + "\"");
                        }

                        retVal.Append(")");
                    }
                    else
                    {
                        retVal.Append(" NIL");
                    }
                }
                else
                {
                    retVal.Append(" NIL");
                }

                // contentID
                string contentID = entity.ContentID;
                if (contentID != null)
                {
                    retVal.Append(" \"" + MimeUtils.EncodeHeaderField(contentID) + "\"");
                }
                else
                {
                    retVal.Append(" NIL");
                }

                // contentDescription
                string contentDescription = entity.ContentDescription;
                if (contentDescription != null)
                {
                    retVal.Append(" \"" + MimeUtils.EncodeHeaderField(contentDescription) + "\"");
                }
                else
                {
                    retVal.Append(" NIL");
                }

                // contentEncoding
                HeaderField contentEncoding = entity.Header.GetFirst("Content-Transfer-Encoding:");
                if (contentEncoding != null)
                {
                    retVal.Append(" \"" + MimeUtils.EncodeHeaderField(contentEncoding.Value) + "\"");
                }
                else
                {
                    // If not specified, then must be 7bit.
                    retVal.Append(" \"7bit\"");
                }

                // contentSize
                if (entity.DataEncoded != null)
                {
                    retVal.Append(" " + entity.DataEncoded.Length);
                }
                else
                {
                    retVal.Append(" 0");
                }

                // envelope ---> FOR ContentType: message/rfc822 ONLY ###
                if ((entity.ContentType & MediaType_enum.Message_rfc822) != 0)
                {
                    retVal.Append(" " + IMAP_Envelope.ConstructEnvelope(entity));

                    // TODO: BODYSTRUCTURE,LINES
                }

                // contentLines ---> FOR ContentType: text/xxx ONLY ###
                if ((entity.ContentType & MediaType_enum.Text) != 0)
                {
                    if (entity.DataEncoded != null)
                    {
                        long             lineCount = 0;
                        StreamLineReader r         = new StreamLineReader(new MemoryStream(entity.DataEncoded));
                        byte[]           line      = r.ReadLine();
                        while (line != null)
                        {
                            lineCount++;

                            line = r.ReadLine();
                        }

                        retVal.Append(" " + lineCount);
                    }
                    else
                    {
                        retVal.Append(" 0");
                    }
                }

                retVal.Append(")");
            }

            return(retVal.ToString());
        }
コード例 #6
0
		/// <summary>
		/// Cryptographically signs and encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs entity using the supplied signer and then
		/// encrypts the result to the specified recipients.
		/// </remarks>
		/// <returns>The signed and encrypted entity.</returns>
		/// <param name="signer">The signer.</param>
		/// <param name="digestAlgo">The digest algorithm to use for signing.</param>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="CertificateNotFoundException">
		/// <para>A signing certificate could not be found for <paramref name="signer"/>.</para>
		/// <para>-or-</para>
		/// <para>A certificate could not be found for one or more of the <paramref name="recipients"/>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime SignAndEncrypt (MailboxAddress signer, DigestAlgorithm digestAlgo, IEnumerable<MailboxAddress> recipients, MimeEntity entity)
		{
			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return SignAndEncrypt (ctx, signer, digestAlgo, recipients, entity);
			}
		}
コード例 #7
0
		/// <summary>
		/// Creates a new <see cref="MultipartEncrypted"/>.
		/// </summary>
		/// <remarks>
		/// Encrypts the entity to the specified recipients, encapsulating the result in a
		/// new multipart/encrypted part.
		/// </remarks>
		/// <returns>A new <see cref="MimeKit.Cryptography.MultipartEncrypted"/> instance containing
		/// the encrypted version of the specified entity.</returns>
		/// <param name="recipients">The recipients for the encrypted entity.</param>
		/// <param name="entity">The entity to sign and encrypt.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// One or more of the recipient keys cannot be used for encrypting.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// A default <see cref="OpenPgpContext"/> has not been registered.
		/// </exception>
		public static MultipartEncrypted Create (IEnumerable<PgpPublicKey> recipients, MimeEntity entity)
		{
			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (OpenPgpContext) CryptographyContext.Create ("application/pgp-encrypted")) {
				return Create (ctx, recipients, entity);
			}
		}
コード例 #8
0
		/// <summary>
		/// Compresses the specified entity.
		/// </summary>
		/// <remarks>
		/// <para>Compresses the specified entity using the default <see cref="SecureMimeContext"/>.</para>
		/// <para>It should be noted that this feature is not supported by most mail clients,
		/// even among those that support S/MIME.</para>
		/// </remarks>
		/// <returns>The compressed entity.</returns>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="entity"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Compress (MimeEntity entity)
		{
			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return Compress (ctx, entity);
			}
		}
コード例 #9
0
		/// <summary>
		/// Cryptographically signs the specified entity.
		/// </summary>
		/// <remarks>
		/// <para>Signs the entity using the supplied signer, digest algorithm and <see cref="SecureMimeContext"/>.</para>
		/// <para>For better interoperability with other mail clients, you should use
		/// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/>
		/// instead as the multipart/signed format is supported among a much larger
		/// subset of mail client software.</para>
		/// </remarks>
		/// <returns>The signed entity.</returns>
		/// <param name="ctx">The S/MIME context to use for signing.</param>
		/// <param name="signer">The signer.</param>
		/// <param name="digestAlgo">The digest algorithm to use for signing.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="CertificateNotFoundException">
		/// A signing certificate could not be found for <paramref name="signer"/>.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Sign (SecureMimeContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var memory = new MemoryBlockStream ()) {
				var options = FormatOptions.CloneDefault ();
				options.NewLineFormat = NewLineFormat.Dos;

				entity.WriteTo (options, memory);
				memory.Position = 0;

				return ctx.EncapsulatedSign (signer, digestAlgo, memory);
			}
		}
コード例 #10
0
        /// <summary>
        /// Construct secified mime entity ENVELOPE string.
        /// </summary>
        /// <param name="entity">Mime entity.</param>
        /// <returns></returns>
        public static string ConstructEnvelope(MimeEntity entity)
        {
            /* RFC 3501 7.4.2
             *                  ENVELOPE
             *                          A parenthesized list that describes the envelope structure of a
             *                          message.  This is computed by the server by parsing the
             *                          [RFC-2822] header into the component parts, defaulting various
             *                          fields as necessary.
             *
             *                          The fields of the envelope structure are in the following
             *                          order: date, subject, from, sender, reply-to, to, cc, bcc,
             *                          in-reply-to, and message-id.  The date, subject, in-reply-to,
             *                          and message-id fields are strings.  The from, sender, reply-to,
             *                          to, cc, and bcc fields are parenthesized lists of address
             *                          structures.
             *
             *                          An address structure is a parenthesized list that describes an
             *                          electronic mail address.  The fields of an address structure
             *                          are in the following order: personal name, [SMTP]
             *                          at-domain-list (source route), mailbox name, and host name.
             *
             *                          [RFC-2822] group syntax is indicated by a special form of
             *                          address structure in which the host name field is NIL.  If the
             *                          mailbox name field is also NIL, this is an end of group marker
             *                          (semi-colon in RFC 822 syntax).  If the mailbox name field is
             *                          non-NIL, this is a start of group marker, and the mailbox name
             *                          field holds the group name phrase.
             *
             *                          If the Date, Subject, In-Reply-To, and Message-ID header lines
             *                          are absent in the [RFC-2822] header, the corresponding member
             *                          of the envelope is NIL; if these header lines are present but
             *                          empty the corresponding member of the envelope is the empty
             *                          string.
             *
             *                                  Note: some servers may return a NIL envelope member in the
             *                                  "present but empty" case.  Clients SHOULD treat NIL and
             *                                  empty string as identical.
             *
             *                                  Note: [RFC-2822] requires that all messages have a valid
             *                                  Date header.  Therefore, the date member in the envelope can
             *                                  not be NIL or the empty string.
             *
             *                                  Note: [RFC-2822] requires that the In-Reply-To and
             *                                  Message-ID headers, if present, have non-empty content.
             *                                  Therefore, the in-reply-to and message-id members in the
             *                                  envelope can not be the empty string.
             *
             *                          If the From, To, cc, and bcc header lines are absent in the
             *                          [RFC-2822] header, or are present but empty, the corresponding
             *                          member of the envelope is NIL.
             *
             *                          If the Sender or Reply-To lines are absent in the [RFC-2822]
             *                          header, or are present but empty, the server sets the
             *                          corresponding member of the envelope to be the same value as
             *                          the from member (the client is not expected to know to do
             *                          this).
             *
             *                                  Note: [RFC-2822] requires that all messages have a valid
             *                                  From header.  Therefore, the from, sender, and reply-to
             *                                  members in the envelope can not be NIL.
             *
             *                          ENVELOPE ("date" "subject" from sender reply-to to cc bcc "in-reply-to" "messageID")
             */

            // NOTE: all header fields and parameters must in ENCODED form !!!

            StringBuilder retVal = new StringBuilder();

            retVal.Append("(");

            // date
            if (entity.Header.Contains("Date:"))
            {
                retVal.Append(TextUtils.QuoteString(MimeUtils.DateTimeToRfc2822(entity.Date)));
            }
            else
            {
                retVal.Append("NIL");
            }

            // subject
            if (entity.Subject != null)
            {
                retVal.Append(" " + TextUtils.QuoteString(MimeUtils.EncodeHeaderField(entity.Subject)));
            }
            else
            {
                retVal.Append(" NIL");
            }

            // from
            if (entity.From != null && entity.From.Count > 0)
            {
                retVal.Append(" " + ConstructAddresses(entity.From));
            }
            else
            {
                retVal.Append(" NIL");
            }

            // sender
            //	NOTE: There is confusing part, according rfc 2822 Sender: is MailboxAddress and not AddressList.
            if (entity.Sender != null)
            {
                retVal.Append(" (");

                retVal.Append(ConstructAddress(entity.Sender));

                retVal.Append(")");
            }
            else if (entity.From != null)
            {
                retVal.Append(" " + ConstructAddresses(entity.From));
            }
            else
            {
                retVal.Append(" NIL");
            }

            // reply-to
            if (entity.ReplyTo != null)
            {
                retVal.Append(" " + ConstructAddresses(entity.ReplyTo));
            }
            else if (entity.From != null)
            {
                retVal.Append(" " + ConstructAddresses(entity.From));
            }
            else
            {
                retVal.Append(" NIL");
            }

            // to
            if (entity.To != null && entity.To.Count > 0)
            {
                retVal.Append(" " + ConstructAddresses(entity.To));
            }
            else
            {
                retVal.Append(" NIL");
            }

            // cc
            if (entity.Cc != null && entity.Cc.Count > 0)
            {
                retVal.Append(" " + ConstructAddresses(entity.Cc));
            }
            else
            {
                retVal.Append(" NIL");
            }

            // bcc
            if (entity.Bcc != null && entity.Bcc.Count > 0)
            {
                retVal.Append(" " + ConstructAddresses(entity.Bcc));
            }
            else
            {
                retVal.Append(" NIL");
            }

            // in-reply-to
            if (entity.InReplyTo != null)
            {
                retVal.Append(" " + TextUtils.QuoteString(MimeUtils.EncodeHeaderField(entity.InReplyTo)));
            }
            else
            {
                retVal.Append(" NIL");
            }

            // message-id
            if (entity.MessageID != null)
            {
                retVal.Append(" " + TextUtils.QuoteString(MimeUtils.EncodeHeaderField(entity.MessageID)));
            }
            else
            {
                retVal.Append(" NIL");
            }

            retVal.Append(")");

            return(retVal.ToString());
        }
コード例 #11
0
ファイル: MultipartSigned.cs プロジェクト: vinodj/MimeKit
        static MultipartSigned Create(CryptographyContext ctx, DigestAlgorithm digestAlgo, MimeEntity entity, MimeEntity signature)
        {
            var micalg = ctx.GetDigestAlgorithmName(digestAlgo);
            var signed = new MultipartSigned();

            // set the protocol and micalg Content-Type parameters
            signed.ContentType.Parameters["protocol"] = ctx.SignatureProtocol;
            signed.ContentType.Parameters["micalg"]   = micalg;

            // add the modified/parsed entity as our first part
            signed.Add(entity);

            // add the detached signature as the second part
            signed.Add(signature);

            return(signed);
        }
コード例 #12
0
        private static MimeEntity ToMimeMessageBody(MailDraft draft)
        {
            var linkedResources = new AttachmentCollection(true);
            var attachments     = new AttachmentCollection();

            string textBody;

            MailUtil.TryExtractTextFromHtml(draft.HtmlBody, out textBody);

            MultipartAlternative multipartAlternative = null;
            MimeEntity           body = null;

            if (!string.IsNullOrEmpty(textBody))
            {
                var textPart = new TextPart("plain")
                {
                    Text = textBody,
                    ContentTransferEncoding = ContentEncoding.QuotedPrintable
                };

                if (!string.IsNullOrEmpty(draft.HtmlBody))
                {
                    multipartAlternative = new MultipartAlternative {
                        textPart
                    };
                    body = multipartAlternative;
                }
                else
                {
                    body = textPart;
                }
            }

            if (!string.IsNullOrEmpty(draft.HtmlBody))
            {
                var htmlPart = new TextPart("html")
                {
                    Text = draft.HtmlBody,
                    ContentTransferEncoding = ContentEncoding.QuotedPrintable
                };

                MimeEntity tempPart;

                if (draft.AttachmentsEmbedded.Any())
                {
                    var multipartRelated = new MultipartRelated
                    {
                        Root = htmlPart
                    };

                    foreach (var emb in draft.AttachmentsEmbedded)
                    {
                        MimeEntity linkedResource;

                        if (!emb.data.Any())
                        {
                            var s3Key = MailStoragePathCombiner.GerStoredFilePath(emb);

                            var contentType =
                                ContentType.Parse(string.IsNullOrEmpty(emb.contentType)
                                    ? MimeMapping.GetMimeMapping(emb.fileName)
                                    : emb.contentType);

                            using (var stream = StorageManager
                                                .GetDataStoreForAttachments(emb.tenant)
                                                .GetReadStream(s3Key))
                            {
                                linkedResource = linkedResources.Add(emb.fileName, stream, contentType);
                            }
                        }
                        else
                        {
                            linkedResource = linkedResources.Add(emb.fileName, emb.data);
                        }

                        linkedResource.ContentId = emb.contentId;

                        multipartRelated.Add(linkedResource);
                    }

                    tempPart = multipartRelated;
                }
                else
                {
                    tempPart = htmlPart;
                }

                if (multipartAlternative != null)
                {
                    multipartAlternative.Add(tempPart);
                }
                else
                {
                    body = tempPart;
                }
            }

            if (!string.IsNullOrEmpty(draft.CalendarIcs))
            {
                var calendarPart = new TextPart("calendar")
                {
                    Text = draft.CalendarIcs,
                    ContentTransferEncoding = ContentEncoding.QuotedPrintable
                };

                calendarPart.ContentType.Parameters.Add("method", draft.CalendarMethod);

                if (multipartAlternative != null)
                {
                    multipartAlternative.Add(calendarPart);
                }
                else
                {
                    body = calendarPart;
                }
            }


            if (draft.Attachments.Any() || !string.IsNullOrEmpty(draft.CalendarIcs))
            {
                var multipart = new Multipart("mixed");

                if (body != null)
                {
                    multipart.Add(body);
                }

                foreach (var att in draft.Attachments)
                {
                    MimeEntity attachmentResource;

                    if (!att.data.Any())
                    {
                        var s3Key = MailStoragePathCombiner.GerStoredFilePath(att);

                        using (var stream = StorageManager
                                            .GetDataStoreForAttachments(att.tenant)
                                            .GetReadStream(s3Key))
                        {
                            attachmentResource = attachments.Add(att.fileName, stream);
                        }
                    }
                    else
                    {
                        attachmentResource = attachments.Add(att.fileName, att.data);
                    }

                    multipart.Add(attachmentResource);
                }

                if (!string.IsNullOrEmpty(draft.CalendarIcs))
                {
                    var filename = "calendar.ics";
                    switch (draft.CalendarMethod)
                    {
                    case "REQUEST":
                        filename = "invite.ics";
                        break;

                    case "REPLY":
                        filename = "reply.ics";
                        break;

                    case "CANCEL":
                        filename = "cancel.ics";
                        break;
                    }

                    var contentType = new ContentType("application", "ics");
                    contentType.Parameters.Add("method", draft.CalendarMethod);
                    contentType.Parameters.Add("name", filename);

                    var data = Encoding.UTF8.GetBytes(draft.CalendarIcs);

                    var calendarResource = attachments.Add(filename, data, contentType);
                    multipart.Add(calendarResource);
                }

                body = multipart;
            }

            if (body != null)
            {
                return(body);
            }

            return(new TextPart("plain")
            {
                Text = string.Empty
            });
        }
コード例 #13
0
ファイル: Message.cs プロジェクト: wlsoftware/smtp4dev
        private MessageEntitySummary HandleMimeEntity(MimeEntity entity)
        {
            var index = 0;

            return(MimeEntityVisitor.VisitWithResults <MessageEntitySummary>(entity, (e, p) =>
            {
                var fileName = PunyCodeReplacer.DecodePunycode(!string.IsNullOrEmpty(e.ContentDisposition?.FileName)
            ? e.ContentDisposition?.FileName
            : e.ContentType?.Name);

                var result = new MessageEntitySummary
                {
                    MessageId = Id,
                    Id = index.ToString(),
                    ContentId = e.ContentId,
                    Name = (fileName ?? e.ContentId ?? index.ToString()) + " - " + e.ContentType.MimeType,
                    Headers = e.Headers.Select(h => new Header {
                        Name = h.Field, Value = PunyCodeReplacer.DecodePunycode(h.Value)
                    }).ToList(),
                    ChildParts = new List <MessageEntitySummary>(),
                    Attachments = new List <AttachmentSummary>(),
                    Warnings = new List <MessageWarning>(),
                    Size = e.ToString().Length,
                    IsAttachment = (e.ContentDisposition?.Disposition != "inline" && !string.IsNullOrEmpty(fileName)) || e.ContentDisposition?.Disposition == "attachment",
                    MimeEntity = e
                };

                if (p != null)
                {
                    p.ChildParts.Add(result);

                    if (result.IsAttachment)
                    {
                        if (e.ContentDisposition?.Disposition != "attachment")
                        {
                            result.Warnings.Add(new MessageWarning {
                                Details = $"Attachment '{fileName}' should have \"Content-Disposition: attachment\" header."
                            });
                        }

                        if (string.IsNullOrEmpty(fileName))
                        {
                            result.Warnings.Add(new MessageWarning {
                                Details = $"Attachment with content ID '{e.ContentId}' should have filename specified in either 'Content-Type' or 'Content-Disposition' header."
                            });
                        }

                        p.Attachments.Add(new AttachmentSummary()
                        {
                            Id = result.Id,
                            ContentId = result.ContentId,
                            FileName = fileName,
                            Url = $"api/messages/{Id}/part/{result.Id}/content"
                        });
                    }
                }

                index++;
                return result;
            }));
        }
コード例 #14
0
 protected internal override void VisitMimeEntity(MimeEntity entity)
 {
     MimeEntity++;
     base.VisitMimeEntity(entity);
 }
コード例 #15
0
        public void TestArgumentExceptions()
        {
            var contentType = new ContentType("application", "octet-stream");
            var attachments = new AttachmentCollection();
            var items       = new MimeEntity[10];
            var data        = new byte[1024];

            using (var stream = new MemoryStream()) {
                Assert.Throws <ArgumentException> (() => attachments.Add(string.Empty));
                Assert.Throws <ArgumentNullException> (() => attachments.Add((string)null));
                Assert.Throws <ArgumentNullException> (() => attachments.Add((MimeEntity)null));
                Assert.Throws <ArgumentException> (() => attachments.Add(string.Empty, data));
                Assert.Throws <ArgumentNullException> (() => attachments.Add((string)null, data));
                Assert.Throws <ArgumentException> (() => attachments.Add(string.Empty, stream));
                Assert.Throws <ArgumentNullException> (() => attachments.Add((string)null, stream));
                Assert.Throws <ArgumentException> (() => attachments.Add(string.Empty, contentType));
                Assert.Throws <ArgumentNullException> (() => attachments.Add((string)null, contentType));
                Assert.Throws <ArgumentException> (() => attachments.Add(string.Empty, data, contentType));
                Assert.Throws <ArgumentNullException> (() => attachments.Add((string)null, data, contentType));
                Assert.Throws <ArgumentException> (() => attachments.Add(string.Empty, stream, contentType));
                Assert.Throws <ArgumentNullException> (() => attachments.Add((string)null, stream, contentType));

                Assert.Throws <ArgumentNullException> (() => attachments.Add("file.dat", (byte[])null));
                Assert.Throws <ArgumentNullException> (() => attachments.Add("file.dat", (Stream)null));
                Assert.Throws <ArgumentNullException> (() => attachments.Add("file.dat", (byte[])null, contentType));
                Assert.Throws <ArgumentNullException> (() => attachments.Add("file.dat", (Stream)null, contentType));

                Assert.Throws <ArgumentNullException> (() => attachments.Add("file.dat", (ContentType)null));
                Assert.Throws <ArgumentNullException> (() => attachments.Add("file.dat", data, null));
                Assert.Throws <ArgumentNullException> (() => attachments.Add("file.dat", stream, null));

                Assert.ThrowsAsync <ArgumentException> (async() => await attachments.AddAsync(string.Empty));
                Assert.ThrowsAsync <ArgumentNullException> (async() => await attachments.AddAsync((string)null));
                Assert.ThrowsAsync <ArgumentException> (async() => await attachments.AddAsync(string.Empty, stream));
                Assert.ThrowsAsync <ArgumentNullException> (async() => await attachments.AddAsync((string)null, stream));
                Assert.ThrowsAsync <ArgumentException> (async() => await attachments.AddAsync(string.Empty, contentType));
                Assert.ThrowsAsync <ArgumentNullException> (async() => await attachments.AddAsync((string)null, contentType));
                Assert.ThrowsAsync <ArgumentException> (async() => await attachments.AddAsync(string.Empty, stream, contentType));
                Assert.ThrowsAsync <ArgumentNullException> (async() => await attachments.AddAsync((string)null, stream, contentType));

                Assert.ThrowsAsync <ArgumentNullException> (async() => await attachments.AddAsync("file.dat", (Stream)null));
                Assert.ThrowsAsync <ArgumentNullException> (async() => await attachments.AddAsync("file.dat", (Stream)null, contentType));

                Assert.ThrowsAsync <ArgumentNullException> (async() => await attachments.AddAsync("file.dat", (ContentType)null));
                Assert.ThrowsAsync <ArgumentNullException> (async() => await attachments.AddAsync("file.dat", stream, null));

                Assert.Throws <ArgumentNullException> (() => attachments.Contains(null));

                Assert.Throws <ArgumentNullException> (() => attachments.CopyTo(null, 0));
                Assert.Throws <ArgumentOutOfRangeException> (() => attachments.CopyTo(items, -1));

                Assert.Throws <ArgumentNullException> (() => attachments.IndexOf(null));

                Assert.Throws <ArgumentNullException> (() => attachments.Remove(null));
                Assert.Throws <ArgumentOutOfRangeException> (() => attachments.RemoveAt(0));

                attachments.Add(new TextPart("plain"));
                Assert.Throws <ArgumentOutOfRangeException> (() => { var x = attachments[10]; });
                Assert.Throws <ArgumentOutOfRangeException> (() => attachments[10] = new TextPart("plain"));
                Assert.Throws <ArgumentNullException> (() => attachments[0]        = null);

                Assert.Throws <ArgumentOutOfRangeException> (() => attachments.Insert(-1, new TextPart("plain")));
                Assert.Throws <ArgumentNullException> (() => attachments.Insert(0, null));
            }
        }
コード例 #16
0
ファイル: EmailHelper.cs プロジェクト: mrkhangtran/TaTa
        public async Task SendEmailAsync(string recipientName, string recipientAddress, string subject, MimeEntity body)
        {
            var message = new MimeMessage();

            message.From.Add(new MailboxAddress("Tata", _smtpInfo.SmtpUsername));
            message.To.Add(new MailboxAddress(recipientName, recipientAddress));
            message.Subject = subject;
            message.Body    = body;

            using (var client = new SmtpClient())
            {
                client.ServerCertificateValidationCallback = (s, c, h, e) => true;

                await client.ConnectAsync(_smtpInfo.SmtpServer, _smtpInfo.SmtpPort, SecureSocketOptions.StartTls);

                client.AuthenticationMechanisms.Remove("XOAUTH2"); // Must be removed for Gmail SMTP
                client.Authenticate(_smtpInfo.SmtpUsername, _smtpInfo.SmtpPassword);
                await client.SendAsync(message);

                await client.DisconnectAsync(true);
            }
        }
コード例 #17
0
		/// <summary>
		/// Cryptographically signs the specified entity.
		/// </summary>
		/// <remarks>
		/// <para>Signs the entity using the supplied signer, digest algorithm and the default
		/// <see cref="SecureMimeContext"/>.</para>
		/// <para>For better interoperability with other mail clients, you should use
		/// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/>
		/// instead as the multipart/signed format is supported among a much larger
		/// subset of mail client software.</para>
		/// </remarks>
		/// <returns>The signed entity.</returns>
		/// <param name="signer">The signer.</param>
		/// <param name="digestAlgo">The digest algorithm to use for signing.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="CertificateNotFoundException">
		/// A signing certificate could not be found for <paramref name="signer"/>.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Sign (MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity)
		{
			if (signer == null)
				throw new ArgumentNullException (nameof (signer));

			if (entity == null)
				throw new ArgumentNullException (nameof (entity));

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return Sign (ctx, signer, digestAlgo, entity);
			}
		}
コード例 #18
0
ファイル: MultipartSigned.cs プロジェクト: vinodj/MimeKit
        /// <summary>
        /// Creates a new <see cref="MultipartSigned"/>.
        /// </summary>
        /// <remarks>
        /// Cryptographically signs the entity using the supplied signer and digest algorithm in
        /// order to generate a detached signature and then adds the entity along with the
        /// detached signature data to a new multipart/signed part.
        /// </remarks>
        /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
        /// <param name="ctx">The cryptography context to use for signing.</param>
        /// <param name="signer">The signer.</param>
        /// <param name="digestAlgo">The digest algorithm to use for signing.</param>
        /// <param name="entity">The entity to sign.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// The <paramref name="digestAlgo"/> was out of range.
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// The <paramref name="digestAlgo"/> is not supported.
        /// </exception>
        /// <exception cref="CertificateNotFoundException">
        /// A signing certificate could not be found for <paramref name="signer"/>.
        /// </exception>
        /// <exception cref="PrivateKeyNotFoundException">
        /// The private key could not be found for <paramref name="signer"/>.
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static MultipartSigned Create(CryptographyContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }

            if (signer == null)
            {
                throw new ArgumentNullException(nameof(signer));
            }

            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            using (var memory = new MemoryBlockStream()) {
                var prepared = Prepare(entity, memory);

                memory.Position = 0;

                // sign the cleartext content
                var signature = ctx.Sign(signer, digestAlgo, memory);

                return(Create(ctx, digestAlgo, prepared, signature));
            }
        }
コード例 #19
0
		/// <summary>
		/// Verifies the signed-data and returns the unencapsulated <see cref="MimeKit.MimeEntity"/>.
		/// </summary>
		/// <remarks>
		/// Verifies the signed-data and returns the unencapsulated <see cref="MimeKit.MimeEntity"/>.
		/// </remarks>
		/// <returns>The list of digital signatures.</returns>
		/// <param name="entity">The unencapsulated entity.</param>
		/// <exception cref="System.InvalidOperationException">
		/// The "smime-type" parameter on the Content-Type header is not "signed-data".
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public DigitalSignatureCollection Verify (out MimeEntity entity)
		{
			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return Verify (ctx, out entity);
			}
		}
コード例 #20
0
ファイル: MultipartSigned.cs プロジェクト: vinodj/MimeKit
        /// <summary>
        /// Creates a new <see cref="MultipartSigned"/>.
        /// </summary>
        /// <remarks>
        /// Cryptographically signs the entity using the supplied signer in order
        /// to generate a detached signature and then adds the entity along with
        /// the detached signature data to a new multipart/signed part.
        /// </remarks>
        /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
        /// <param name="ctx">The S/MIME context to use for signing.</param>
        /// <param name="signer">The signer.</param>
        /// <param name="entity">The entity to sign.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static MultipartSigned Create(SecureMimeContext ctx, CmsSigner signer, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }

            if (signer == null)
            {
                throw new ArgumentNullException(nameof(signer));
            }

            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            using (var memory = new MemoryBlockStream()) {
                var prepared = Prepare(entity, memory);

                memory.Position = 0;

                // sign the cleartext content
                var signature = ctx.Sign(signer, memory);

                return(Create(ctx, signer.DigestAlgorithm, prepared, signature));
            }
        }
コード例 #21
0
		/// <summary>
		/// Encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Encrypts the entity to the specified recipients using the default <see cref="SecureMimeContext"/>.
		/// </remarks>
		/// <returns>The encrypted entity.</returns>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// Valid certificates could not be found for one or more of the <paramref name="recipients"/>.
		/// </exception>
		/// <exception cref="CertificateNotFoundException">
		/// A certificate could not be found for one or more of the <paramref name="recipients"/>.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Encrypt (IEnumerable<MailboxAddress> recipients, MimeEntity entity)
		{
			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return Encrypt (ctx, recipients, entity);
			}
		}
コード例 #22
0
        /// <summary>
        /// Creates simple mime message with attachments.
        /// </summary>
        /// <param name="from">Header field From: value.</param>
        /// <param name="to">Header field To: value.</param>
        /// <param name="subject">Header field Subject: value.</param>
        /// <param name="bodyText">Body text of message. NOTE: Pass null is body text isn't wanted.</param>
        /// <param name="bodyHtml">Body HTML text of message. NOTE: Pass null is body HTML text isn't wanted.</param>
        /// <param name="attachmentFileNames">Attachment file names. Pass null if no attachments. NOTE: File name must contain full path to file, for example: c:\test.pdf.</param>
        /// <returns></returns>
        public static Mime CreateSimple(AddressList from, AddressList to, string subject, string bodyText, string bodyHtml, string[] attachmentFileNames)
        {
            Mime m = new Mime();

            MimeEntity mainEntity = m.MainEntity;

            mainEntity.From    = from;
            mainEntity.To      = to;
            mainEntity.Subject = subject;

            // There are no atachments
            if (attachmentFileNames == null || attachmentFileNames.Length == 0)
            {
                // If bodyText and bodyHtml both specified
                if (bodyText != null && bodyHtml != null)
                {
                    mainEntity.ContentType = MediaType_enum.Multipart_alternative;

                    MimeEntity textEntity = mainEntity.ChildEntities.Add();
                    textEntity.ContentType             = MediaType_enum.Text_plain;
                    textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textEntity.DataText = bodyText;

                    MimeEntity textHtmlEntity = mainEntity.ChildEntities.Add();
                    textHtmlEntity.ContentType             = MediaType_enum.Text_html;
                    textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textHtmlEntity.DataText = bodyHtml;
                }
                // There is only body text
                else if (bodyText != null)
                {
                    MimeEntity textEntity = mainEntity;
                    textEntity.ContentType             = MediaType_enum.Text_plain;
                    textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textEntity.DataText = bodyText;
                }
                // There is only body html text
                else if (bodyHtml != null)
                {
                    MimeEntity textHtmlEntity = mainEntity;
                    textHtmlEntity.ContentType             = MediaType_enum.Text_html;
                    textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textHtmlEntity.DataText = bodyHtml;
                }
            }
            // There are attachments
            else
            {
                mainEntity.ContentType = MediaType_enum.Multipart_mixed;

                // If bodyText and bodyHtml both specified
                if (bodyText != null && bodyHtml != null)
                {
                    MimeEntity multiPartAlternativeEntity = mainEntity.ChildEntities.Add();
                    multiPartAlternativeEntity.ContentType = MediaType_enum.Multipart_alternative;

                    MimeEntity textEntity = multiPartAlternativeEntity.ChildEntities.Add();
                    textEntity.ContentType             = MediaType_enum.Text_plain;
                    textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textEntity.DataText = bodyText;

                    MimeEntity textHtmlEntity = multiPartAlternativeEntity.ChildEntities.Add();
                    textHtmlEntity.ContentType             = MediaType_enum.Text_html;
                    textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textHtmlEntity.DataText = bodyHtml;
                }
                // There is only body text
                else if (bodyText != null)
                {
                    MimeEntity textEntity = mainEntity.ChildEntities.Add();
                    textEntity.ContentType             = MediaType_enum.Text_plain;
                    textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textEntity.DataText = bodyText;
                }
                // There is only body html text
                else if (bodyHtml != null)
                {
                    MimeEntity textHtmlEntity = mainEntity.ChildEntities.Add();
                    textHtmlEntity.ContentType             = MediaType_enum.Text_html;
                    textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textHtmlEntity.DataText = bodyHtml;
                }

                foreach (string fileName in attachmentFileNames)
                {
                    MimeEntity attachmentEntity = mainEntity.ChildEntities.Add();
                    attachmentEntity.ContentType                 = MediaType_enum.Application_octet_stream;
                    attachmentEntity.ContentDisposition          = ContentDisposition_enum.Attachment;
                    attachmentEntity.ContentTransferEncoding     = ContentTransferEncoding_enum.Base64;
                    attachmentEntity.ContentDisposition_FileName = Core.GetFileNameFromPath(fileName);
                    attachmentEntity.DataFromFile(fileName);
                }
            }

            return(m);
        }
コード例 #23
0
		/// <summary>
		/// Cryptographically signs and encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs entity using the supplied signer and then
		/// encrypts the result to the specified recipients.
		/// </remarks>
		/// <returns>The signed and encrypted entity.</returns>
		/// <param name="signer">The signer.</param>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime SignAndEncrypt (CmsSigner signer, CmsRecipientCollection recipients, MimeEntity entity)
		{
			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return SignAndEncrypt (ctx, signer, recipients, entity);
			}
		}
コード例 #24
0
ファイル: MainWindow.xaml.cs プロジェクト: seif/papercut-web
        /// <summary>
        ///     The messages list_ selection changed.
        /// </summary>
        /// <param name="sender">
        ///     The sender.
        /// </param>
        /// <param name="e">
        ///     The e.
        /// </param>
        private void messagesList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var setTitle = new Action <string>(
                t =>
            {
                this.Subject.Content = t;
                this.Subject.ToolTip = t;
            });

            // If there are no selected items, then disable the Delete button, clear the boxes, and return
            if (e.AddedItems.Count == 0)
            {
                this.deleteButton.IsEnabled   = false;
                this.forwardButton.IsEnabled  = false;
                this.rawView.Text             = string.Empty;
                this.bodyView.Text            = string.Empty;
                this.htmlViewTab.Visibility   = Visibility.Hidden;
                this.tabControl.SelectedIndex = this.defaultTab.IsVisible ? 0 : 1;

                // Clear fields
                this.FromEdit.Text = string.Empty;
                this.ToEdit.Text   = string.Empty;
                this.CCEdit.Text   = string.Empty;
                this.BccEdit.Text  = string.Empty;
                this.DateEdit.Text = string.Empty;

                var subject = string.Empty;
                this.SubjectEdit.Text = subject;

                this.defaultBodyView.Text = string.Empty;

                this.defaultHtmlView.Content = null;
                this.defaultHtmlView.NavigationService.RemoveBackEntry();
                //this.defaultHtmlView.Refresh();

                setTitle("Papercut");

                return;
            }

            var mailFile = ((MessageEntry)e.AddedItems[0]).File;

            try
            {
                this.tabControl.IsEnabled     = false;
                this.SpinAnimation.Visibility = Visibility.Visible;
                setTitle("Loading...");

                if (this._currentMessageCancellationTokenSource != null)
                {
                    this._currentMessageCancellationTokenSource.Cancel();
                }

                this._currentMessageCancellationTokenSource = new CancellationTokenSource();

                Task.Factory.StartNew(() => { })
                .ContinueWith(
                    task => File.ReadAllLines(mailFile, Encoding.ASCII),
                    this._currentMessageCancellationTokenSource.Token,
                    TaskContinuationOptions.NotOnCanceled,
                    TaskScheduler.Default)
                .ContinueWith(
                    task =>
                {
                    // Load the MIME body
                    var mimeReader = new MimeReader(task.Result);
                    MimeEntity me  = mimeReader.CreateMimeEntity();

                    return(Tuple.Create(task.Result, me.ToMailMessageEx()));
                },
                    this._currentMessageCancellationTokenSource.Token,
                    TaskContinuationOptions.NotOnCanceled,
                    TaskScheduler.Default).ContinueWith(
                    task =>
                {
                    var resultTuple   = task.Result;
                    var mailMessageEx = resultTuple.Item2;

                    // set the raw view...
                    this.rawView.Text = string.Join("\n", resultTuple.Item1);

                    this.bodyView.Text          = mailMessageEx.Body;
                    this.bodyViewTab.Visibility = Visibility.Visible;

                    this.defaultBodyView.Text = mailMessageEx.Body;

                    this.FromEdit.Text = mailMessageEx.From.IfNotNull(s => s.ToString()) ?? string.Empty;
                    this.ToEdit.Text   = mailMessageEx.To.IfNotNull(s => s.ToString()) ?? string.Empty;
                    this.CCEdit.Text   = mailMessageEx.CC.IfNotNull(s => s.ToString()) ?? string.Empty;
                    this.BccEdit.Text  = mailMessageEx.Bcc.IfNotNull(s => s.ToString()) ?? string.Empty;
                    this.DateEdit.Text = mailMessageEx.DeliveryDate.IfNotNull(s => s.ToString()) ?? string.Empty;

                    var subject           = mailMessageEx.Subject.IfNotNull(s => s.ToString()) ?? string.Empty;
                    this.SubjectEdit.Text = subject;

                    setTitle(subject);

                    // If it is HTML, render it to the HTML view
                    if (mailMessageEx.IsBodyHtml)
                    {
                        if (task.IsCanceled)
                        {
                            return;
                        }

                        this.SetBrowserDocument(mailMessageEx);
                        this.htmlViewTab.Visibility = Visibility.Visible;

                        this.defaultHtmlView.Visibility = Visibility.Visible;
                        this.defaultBodyView.Visibility = Visibility.Collapsed;
                    }
                    else
                    {
                        this.htmlViewTab.Visibility = Visibility.Hidden;
                        if (this.defaultTab.IsVisible)
                        {
                            this.tabControl.SelectedIndex = 0;
                        }
                        else if (Equals(this.tabControl.SelectedItem, this.htmlViewTab))
                        {
                            this.tabControl.SelectedIndex = 2;
                        }

                        this.defaultHtmlView.Visibility = Visibility.Collapsed;
                        this.defaultBodyView.Visibility = Visibility.Visible;
                    }

                    this.SpinAnimation.Visibility = Visibility.Collapsed;
                    this.tabControl.IsEnabled     = true;

                    // Enable the delete and forward button
                    this.deleteButton.IsEnabled  = true;
                    this.forwardButton.IsEnabled = true;
                },
                    this._currentMessageCancellationTokenSource.Token,
                    TaskContinuationOptions.NotOnCanceled,
                    TaskScheduler.FromCurrentSynchronizationContext());
            }
            catch (Exception ex)
            {
                Logger.WriteWarning(string.Format(@"Unable to Load Message ""{0}"": {1}", mailFile, ex));

                setTitle("Papercut");
                this.tabControl.SelectedIndex = 1;
                this.bodyViewTab.Visibility   = Visibility.Hidden;
                this.htmlViewTab.Visibility   = Visibility.Hidden;
            }
        }
コード例 #25
0
		/// <summary>
		/// Creates a new <see cref="MultipartEncrypted"/>.
		/// </summary>
		/// <remarks>
		/// Signs the entity using the supplied signer and digest algorithm and then encrypts to
		/// the specified recipients, encapsulating the result in a new multipart/encrypted part.
		/// </remarks>
		/// <returns>A new <see cref="MimeKit.Cryptography.MultipartEncrypted"/> instance containing
		/// the signed and encrypted version of the specified entity.</returns>
		/// <param name="ctx">The OpenPGP cryptography context to use for singing and encrypting.</param>
		/// <param name="signer">The signer to use to sign the entity.</param>
		/// <param name="digestAlgo">The digest algorithm to use for signing.</param>
		/// <param name="recipients">The recipients for the encrypted entity.</param>
		/// <param name="entity">The entity to sign and encrypt.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="signer"/> cannot be used for signing.</para>
		/// <para>-or-</para>
		/// <para>One or more of the recipient keys cannot be used for encrypting.</para>
		/// <para>-or-</para>
		/// <para>No recipients were specified.</para>
		/// </exception>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// The <paramref name="digestAlgo"/> was out of range.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// The <paramref name="digestAlgo"/> is not supported.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The user chose to cancel the password prompt.
		/// </exception>
		/// <exception cref="System.UnauthorizedAccessException">
		/// 3 bad attempts were made to unlock the secret key.
		/// </exception>
		public static MultipartEncrypted Create (OpenPgpContext ctx, PgpSecretKey signer, DigestAlgorithm digestAlgo, IEnumerable<PgpPublicKey> recipients, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var memory = new MemoryStream ()) {
				var options = FormatOptions.Default.Clone ();
				options.NewLineFormat = NewLineFormat.Dos;

				PrepareEntityForEncrypting (entity);
				entity.WriteTo (options, memory);
				memory.Position = 0;

				var encrypted = new MultipartEncrypted ();
				encrypted.ContentType.Parameters["protocol"] = ctx.EncryptionProtocol;

				// add the protocol version part
				encrypted.Add (new ApplicationPgpEncrypted ());

				// add the encrypted entity as the second part
				encrypted.Add (ctx.SignAndEncrypt (signer, digestAlgo, recipients, memory));

				return encrypted;
			}
		}
コード例 #26
0
        public BounceDetectResult(
            MimeMessage message,
            MimeEntity deliveryNotification,
            MessageDeliveryStatus deliveryStatus,
            MimeEntity undeliveredMessagePart
            )
        {
            var headers = new Dictionary <string, string[]>(StringComparer.OrdinalIgnoreCase);

            if (deliveryStatus != null)
            {
                foreach (var header in deliveryStatus.StatusGroups.SelectMany(g => g).Where(h => Matchers.ContainsKey(h.Field)))
                {
                    var m = Matchers[header.Field].Match(header.Value);

                    if (!m.Success)
                    {
                        continue;
                    }

                    var matched = m.Groups.Cast <Group>().Skip(1).Select(c => c.Value).ToArray();

                    if (matched.Length > 0)
                    {
                        headers[header.Field] = matched;
                    }
                }
            }

            if (headers.ContainsKey("Status"))
            {
                var status = headers["Status"];
                _primaryStatus   = ParseBounceStatus(status[0], PrimaryStatusCodes);
                _secundaryStatus = ParseBounceStatus(status[1], SecundaryStatusCodes);
                _combinedStatus  = ParseBounceStatus(string.Join("", status.Skip(1)), CombinedStatusCodes);
            }

            if (headers.ContainsKey("Remote-Mta"))
            {
                _remoteMta = headers["Remote-Mta"][1];
            }

            if (headers.ContainsKey("Reporting-Mta"))
            {
                _reportingMta = headers["Reporting-Mta"][1];
            }

            if (headers.ContainsKey("Final-Recipient"))
            {
                _finalRecipient = headers["Final-Recipient"][1];
            }

            if (headers.ContainsKey("Diagnostic-Code"))
            {
                _diagnosticCodes = headers["Diagnostic-Code"].Skip(1).ToArray();
            }

            if (headers.ContainsKey("Action"))
            {
                _action = headers["Action"][0];
            }

            _deliveryNotificationPart = deliveryNotification;
            _deliveryStatus           = deliveryStatus;
            _undeliveredMessagePart   = undeliveredMessagePart;

            // get the original message id.
            if (_undeliveredMessagePart != null)
            {
                var undeliveredMessage = ((MessagePart)_undeliveredMessagePart).Message;
                _undeliveredMessageId = undeliveredMessage.MessageId;
            }
            // try harder. Exchange has In-Reply-To right on the root message. its the undelivered message id.
            else
            {
                _undeliveredMessageId = message.Headers["In-Reply-To"];
            }
        }
コード例 #27
0
ファイル: IMAP_BODY.cs プロジェクト: Inzaghi2012/teamlab.v7.5
        /// <summary>
        /// Constructs specified entity and it's childentities bodystructure string.
        /// </summary>
        /// <param name="entity">Mime entity.</param>
        /// <param name="bodystructure">Specifies if to construct BODY or BODYSTRUCTURE.</param>
        /// <returns></returns>
        private static string ConstructParts(MimeEntity entity, bool bodystructure)
        {
            /* RFC 3501 7.4.2 BODYSTRUCTURE
							  BODY A form of BODYSTRUCTURE without extension data.
			  
				A parenthesized list that describes the [MIME-IMB] body
				structure of a message.  This is computed by the server by
				parsing the [MIME-IMB] header fields, defaulting various fields
				as necessary.

				For example, a simple text message of 48 lines and 2279 octets
				can have a body structure of: ("TEXT" "PLAIN" ("CHARSET"
				"US-ASCII") NIL NIL "7BIT" 2279 48)

				Multiple parts are indicated by parenthesis nesting.  Instead
				of a body type as the first element of the parenthesized list,
				there is a sequence of one or more nested body structures.  The
				second element of the parenthesized list is the multipart
				subtype (mixed, digest, parallel, alternative, etc.).
					
				For example, a two part message consisting of a text and a
				BASE64-encoded text attachment can have a body structure of:
				(("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152
				23)("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "cc.diff")
				"<*****@*****.**>" "Compiler diff"
				"BASE64" 4554 73) "MIXED")

				Extension data follows the multipart subtype.  Extension data
				is never returned with the BODY fetch, but can be returned with
				a BODYSTRUCTURE fetch.  Extension data, if present, MUST be in
				the defined order.  The extension data of a multipart body part
				are in the following order:

				body parameter parenthesized list
					A parenthesized list of attribute/value pairs [e.g., ("foo"
					"bar" "baz" "rag") where "bar" is the value of "foo", and
					"rag" is the value of "baz"] as defined in [MIME-IMB].

				body disposition
					A parenthesized list, consisting of a disposition type
					string, followed by a parenthesized list of disposition
					attribute/value pairs as defined in [DISPOSITION].

				body language
					A string or parenthesized list giving the body language
					value as defined in [LANGUAGE-TAGS].

				body location
					A string list giving the body content URI as defined in [LOCATION].

				Any following extension data are not yet defined in this
				version of the protocol.  Such extension data can consist of
				zero or more NILs, strings, numbers, or potentially nested
				parenthesized lists of such data.  Client implementations that
				do a BODYSTRUCTURE fetch MUST be prepared to accept such
				extension data.  Server implementations MUST NOT send such
				extension data until it has been defined by a revision of this
				protocol.

				The basic fields of a non-multipart body part are in the
				following order:

				body type
					A string giving the content media type name as defined in [MIME-IMB].
				
				body subtype
					 A string giving the content subtype name as defined in [MIME-IMB].

				body parameter parenthesized list
					A parenthesized list of attribute/value pairs [e.g., ("foo"
					"bar" "baz" "rag") where "bar" is the value of "foo" and
					"rag" is the value of "baz"] as defined in [MIME-IMB].

				body id
					A string giving the content id as defined in [MIME-IMB].

				body description
					A string giving the content description as defined in [MIME-IMB].

				body encoding
					A string giving the content transfer encoding as defined in	[MIME-IMB].

				body size
					A number giving the size of the body in octets.  Note that
					this size is the size in its transfer encoding and not the
					resulting size after any decoding.

				A body type of type MESSAGE and subtype RFC822 contains,
				immediately after the basic fields, the envelope structure,
				body structure, and size in text lines of the encapsulated
				message.

				A body type of type TEXT contains, immediately after the basic
				fields, the size of the body in text lines.  Note that this
				size is the size in its content transfer encoding and not the
				resulting size after any decoding.

				Extension data follows the basic fields and the type-specific
				fields listed above.  Extension data is never returned with the
				BODY fetch, but can be returned with a BODYSTRUCTURE fetch.
				Extension data, if present, MUST be in the defined order.

				The extension data of a non-multipart body part are in the
				following order:

				body MD5
					A string giving the body MD5 value as defined in [MD5].
					
				body disposition
					A parenthesized list with the same content and function as
					the body disposition for a multipart body part.

				body language
					A string or parenthesized list giving the body language
					value as defined in [LANGUAGE-TAGS].

				body location
					A string list giving the body content URI as defined in [LOCATION].

				Any following extension data are not yet defined in this
				version of the protocol, and would be as described above under
				multipart extension data.
			
			
				// We don't construct extention fields like rfc says:
					Server implementations MUST NOT send such
					extension data until it has been defined by a revision of this
					protocol.
			
										
				contentTypeMainMediaType - Example: 'TEXT'
				contentTypeSubMediaType  - Example: 'PLAIN'
				conentTypeParameters     - Example: '("CHARSET" "iso-8859-1" ...)'
				contentID                - Content-ID: header field value.
				contentDescription       - Content-Description: header field value.
				contentEncoding          - Content-Transfer-Encoding: header field value.
				contentSize              - mimeEntity ENCODED data size
				[envelope]               - NOTE: included only if contentType = "message" !!!
				[contentLines]           - number of ENCODED data lines. NOTE: included only if contentType = "text" !!!
									   			
				// Basic fields for multipart
				(nestedMimeEntries) contentTypeSubMediaType
												
				// Basic fields for non-multipart
				contentTypeMainMediaType contentTypeSubMediaType (conentTypeParameters) contentID contentDescription contentEncoding contentSize [envelope] [contentLine]

			*/

            StringBuilder retVal = new StringBuilder();
            // Multipart message
            if ((entity.ContentType & MediaType_enum.Multipart) != 0)
            {
                retVal.Append("(");

                // Construct child entities.
                foreach (MimeEntity childEntity in entity.ChildEntities)
                {
                    // Construct child entity. This can be multipart or non multipart.
                    retVal.Append(ConstructParts(childEntity, bodystructure));
                }

                // Add contentTypeSubMediaType
                string contentType = entity.ContentTypeString.Split(';')[0];
                if (contentType.Split('/').Length == 2)
                {
                    retVal.Append(" \"" + contentType.Split('/')[1].Replace(";", "") + "\"");
                }
                else
                {
                    retVal.Append(" NIL");
                }

                retVal.Append(")");
            }
                // Single part message
            else
            {
                retVal.Append("(");

                // NOTE: all header fields and parameters must in ENCODED form !!!

                // Add contentTypeMainMediaType
                if (entity.ContentTypeString != null)
                {
                    string contentType = entity.ContentTypeString.Split(';')[0];
                    if (contentType.Split('/').Length == 2)
                    {
                        retVal.Append("\"" + entity.ContentTypeString.Split('/')[0] + "\"");
                    }
                    else
                    {
                        retVal.Append("NIL");
                    }
                }
                else
                {
                    retVal.Append("NIL");
                }

                // contentTypeSubMediaType
                if (entity.ContentTypeString != null)
                {
                    string contentType = entity.ContentTypeString.Split(';')[0];
                    if (contentType.Split('/').Length == 2)
                    {
                        retVal.Append(" \"" + contentType.Split('/')[1].Replace(";", "") + "\"");
                    }
                    else
                    {
                        retVal.Append(" NIL");
                    }
                }
                else
                {
                    retVal.Append(" NIL");
                }

                // conentTypeParameters - Syntax: {("name" SP "value" *(SP "name" SP "value"))}
                if (entity.ContentTypeString != null)
                {
                    ParametizedHeaderField contentTypeParameters =
                        new ParametizedHeaderField(entity.Header.GetFirst("Content-Type:"));
                    if (contentTypeParameters.Parameters.Count > 0)
                    {
                        retVal.Append(" (");

                        bool first = true;
                        foreach (HeaderFieldParameter param in contentTypeParameters.Parameters)
                        {
                            // For first item, don't add SP
                            if (!first)
                            {
                                retVal.Append(" ");
                            }
                            else
                            {
                                // Clear first flag
                                first = false;
                            }

                            retVal.Append("\"" + param.Name + "\" \"" +
                                          MimeUtils.EncodeHeaderField(param.Value) + "\"");
                        }

                        retVal.Append(")");
                    }
                    else
                    {
                        retVal.Append(" NIL");
                    }
                }
                else
                {
                    retVal.Append(" NIL");
                }

                // contentID
                string contentID = entity.ContentID;
                if (contentID != null)
                {
                    retVal.Append(" \"" + MimeUtils.EncodeHeaderField(contentID) + "\"");
                }
                else
                {
                    retVal.Append(" NIL");
                }

                // contentDescription
                string contentDescription = entity.ContentDescription;
                if (contentDescription != null)
                {
                    retVal.Append(" \"" + MimeUtils.EncodeHeaderField(contentDescription) + "\"");
                }
                else
                {
                    retVal.Append(" NIL");
                }

                // contentEncoding
                HeaderField contentEncoding = entity.Header.GetFirst("Content-Transfer-Encoding:");
                if (contentEncoding != null)
                {
                    retVal.Append(" \"" + MimeUtils.EncodeHeaderField(contentEncoding.Value) + "\"");
                }
                else
                {
                    // If not specified, then must be 7bit.
                    retVal.Append(" \"7bit\"");
                }

                // contentSize
                if (entity.DataEncoded != null)
                {
                    retVal.Append(" " + entity.DataEncoded.Length);
                }
                else
                {
                    retVal.Append(" 0");
                }

                // envelope ---> FOR ContentType: message/rfc822 ONLY ###
                if ((entity.ContentType & MediaType_enum.Message_rfc822) != 0)
                {
                    retVal.Append(" " + IMAP_Envelope.ConstructEnvelope(entity));

                    // TODO: BODYSTRUCTURE,LINES
                }

                // contentLines ---> FOR ContentType: text/xxx ONLY ###
                if ((entity.ContentType & MediaType_enum.Text) != 0)
                {
                    if (entity.DataEncoded != null)
                    {
                        long lineCount = 0;
                        StreamLineReader r = new StreamLineReader(new MemoryStream(entity.DataEncoded));
                        byte[] line = r.ReadLine();
                        while (line != null)
                        {
                            lineCount++;

                            line = r.ReadLine();
                        }

                        retVal.Append(" " + lineCount);
                    }
                    else
                    {
                        retVal.Append(" 0");
                    }
                }

                retVal.Append(")");
            }

            return retVal.ToString();
        }
コード例 #28
0
 /// <summary>
 /// Returns requested header fields lines.
 /// Note: Header terminator blank line is included.
 /// </summary>
 /// <param name="fieldsStr">Header fields to get.</param>
 /// <param name="entity">Entity which header field lines to get.</param>
 /// <returns></returns>
 public static byte[] ParseHeaderFields(string fieldsStr, MimeEntity entity)
 {
     return ParseHeaderFields(fieldsStr, Encoding.Default.GetBytes(entity.HeaderString));
 }
コード例 #29
0
 /// <summary>
 /// Creates a new <see cref="MultipartSigned"/>.
 /// </summary>
 /// <remarks>
 /// Cryptographically signs the entity using the supplied signer and digest algorithm in
 /// order to generate a detached signature and then adds the entity along with the
 /// detached signature data to a new multipart/signed part.
 /// </remarks>
 /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
 /// <param name="signer">The signer.</param>
 /// <param name="digestAlgo">The digest algorithm to use for signing.</param>
 /// <param name="entity">The entity to sign.</param>
 /// <exception cref="System.ArgumentNullException">
 /// <para><paramref name="signer"/> is <c>null</c>.</para>
 /// <para>-or-</para>
 /// <para><paramref name="entity"/> is <c>null</c>.</para>
 /// </exception>
 /// <exception cref="System.ArgumentException">
 /// <paramref name="signer"/> cannot be used for signing.
 /// </exception>
 /// <exception cref="System.ArgumentOutOfRangeException">
 /// The <paramref name="digestAlgo"/> was out of range.
 /// </exception>
 /// <exception cref="System.NotSupportedException">
 /// <para>A cryptography context suitable for signing could not be found.</para>
 /// <para>-or-</para>
 /// <para>The <paramref name="digestAlgo"/> is not supported.</para>
 /// </exception>
 /// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">
 /// An error occurred in the OpenPGP subsystem.
 /// </exception>
 public static MultipartSigned Create(PgpSecretKey signer, DigestAlgorithm digestAlgo, MimeEntity entity)
 {
     using (var ctx = (OpenPgpContext)CryptographyContext.Create("application/pgp-signature")) {
         return(Create(ctx, signer, digestAlgo, entity));
     }
 }
コード例 #30
0
 public Attachment(string label, MimeEntity attachment)
 {
     InitializeComponent();
     attachmentLabel.Text = label;
     Attach = attachment;
 }
コード例 #31
0
 /// <summary>
 /// Gets specified mime entity header.
 /// Note: Header terminator blank line is included.
 /// </summary>
 /// <param name="entity">Mime entity.</param>
 /// <returns></returns>
 public static byte[] GetMimeEntityHeader(MimeEntity entity)
 {
     return Encoding.ASCII.GetBytes(entity.HeaderString + "\r\n");
 }
コード例 #32
0
        /// <summary>
        /// Creates a new <see cref="MultipartSigned"/>.
        /// </summary>
        /// <remarks>
        /// Cryptographically signs the entity using the supplied signer in order
        /// to generate a detached signature and then adds the entity along with
        /// the detached signature data to a new multipart/signed part.
        /// </remarks>
        /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
        /// <param name="ctx">The S/MIME context to use for signing.</param>
        /// <param name="signer">The signer.</param>
        /// <param name="entity">The entity to sign.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static MultipartSigned Create(SecureMimeContext ctx, CmsSigner signer, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }

            if (signer == null)
            {
                throw new ArgumentNullException(nameof(signer));
            }

            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            entity.Prepare(EncodingConstraint.SevenBit, 78);

            using (var memory = new MemoryBlockStream()) {
                using (var filtered = new FilteredStream(memory)) {
                    // Note: see rfc3156, section 3 - second note
                    filtered.Add(new ArmoredFromFilter());

                    // Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156)
                    filtered.Add(new TrailingWhitespaceFilter());

                    // Note: see rfc2015 or rfc3156, section 5.1
                    filtered.Add(new Unix2DosFilter());

                    entity.WriteTo(filtered);
                    filtered.Flush();
                }

                memory.Position = 0;

                // Note: we need to parse the modified entity structure to preserve any modifications
                var parser = new MimeParser(memory, MimeFormat.Entity);
                var parsed = parser.ParseEntity();
                memory.Position = 0;

                // sign the cleartext content
                var micalg    = ctx.GetDigestAlgorithmName(signer.DigestAlgorithm);
                var signature = ctx.Sign(signer, memory);
                var signed    = new MultipartSigned();

                // set the protocol and micalg Content-Type parameters
                signed.ContentType.Parameters["protocol"] = ctx.SignatureProtocol;
                signed.ContentType.Parameters["micalg"]   = micalg;

                // add the modified/parsed entity as our first part
                signed.Add(parsed);

                // add the detached signature as the second part
                signed.Add(signature);

                return(signed);
            }
        }
コード例 #33
0
		/// <summary>
		/// Encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Encrypts the entity to the specified recipients using the supplied <see cref="SecureMimeContext"/>.
		/// </remarks>
		/// <returns>The encrypted entity.</returns>
		/// <param name="ctx">The S/MIME context to use for encrypting.</param>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Encrypt (SecureMimeContext ctx, CmsRecipientCollection recipients, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException (nameof (ctx));

			if (recipients == null)
				throw new ArgumentNullException (nameof (recipients));

			if (entity == null)
				throw new ArgumentNullException (nameof (entity));

			using (var memory = new MemoryBlockStream ()) {
				var options = FormatOptions.CloneDefault ();
				options.NewLineFormat = NewLineFormat.Dos;

				entity.WriteTo (options, memory);
				memory.Position = 0;

				return ctx.Encrypt (recipients, memory);
			}
		}
コード例 #34
0
 /// <summary>
 /// Creates a new <see cref="MultipartSigned"/>.
 /// </summary>
 /// <remarks>
 /// Cryptographically signs the entity using the supplied signer in order
 /// to generate a detached signature and then adds the entity along with
 /// the detached signature data to a new multipart/signed part.
 /// </remarks>
 /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
 /// <param name="signer">The signer.</param>
 /// <param name="entity">The entity to sign.</param>
 /// <exception cref="System.ArgumentNullException">
 /// <para><paramref name="signer"/> is <c>null</c>.</para>
 /// <para>-or-</para>
 /// <para><paramref name="entity"/> is <c>null</c>.</para>
 /// </exception>
 /// <exception cref="System.NotSupportedException">
 /// A cryptography context suitable for signing could not be found.
 /// </exception>
 /// <exception cref="Org.BouncyCastle.Cms.CmsException">
 /// An error occurred in the cryptographic message syntax subsystem.
 /// </exception>
 public static MultipartSigned Create(CmsSigner signer, MimeEntity entity)
 {
     using (var ctx = (SecureMimeContext)CryptographyContext.Create("application/pkcs7-signature")) {
         return(Create(ctx, signer, entity));
     }
 }
コード例 #35
0
		/// <summary>
		/// Cryptographically signs the specified entity.
		/// </summary>
		/// <remarks>
		/// <para>Signs the entity using the supplied signer and <see cref="SecureMimeContext"/>.</para>
		/// <para>For better interoperability with other mail clients, you should use
		/// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/>
		/// instead as the multipart/signed format is supported among a much larger
		/// subset of mail client software.</para>
		/// </remarks>
		/// <returns>The signed entity.</returns>
		/// <param name="ctx">The S/MIME context to use for signing.</param>
		/// <param name="signer">The signer.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Sign (SecureMimeContext ctx, CmsSigner signer, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException (nameof (ctx));

			if (signer == null)
				throw new ArgumentNullException (nameof (signer));

			if (entity == null)
				throw new ArgumentNullException (nameof (entity));

			using (var memory = new MemoryBlockStream ()) {
				var options = FormatOptions.CloneDefault ();
				options.NewLineFormat = NewLineFormat.Dos;

				entity.WriteTo (options, memory);
				memory.Position = 0;

				return ctx.EncapsulatedSign (signer, memory);
			}
		}
コード例 #36
0
        void Render(MimeEntity entity)
        {
            var related = entity as MultipartRelated;

            if (related != null)
            {
                RenderMultipartRelated(related);
                return;
            }

            var multipart = entity as Multipart;
            var text      = entity as TextPart;

            // check if the entity is a multipart
            if (multipart != null)
            {
                if (multipart.ContentType.IsMimeType("multipart", "alternative"))
                {
                    // A multipart/alternative is just a collection of alternate views.
                    // The last part is the format that most closely matches what the
                    // user saw in his or her email client's WYSIWYG editor.
                    TextPart preferred = null;

                    for (int i = multipart.Count; i > 0; i--)
                    {
                        related = multipart[i - 1] as MultipartRelated;

                        if (related != null)
                        {
                            var root = related.Root;

                            if (root != null && root.ContentType.IsMimeType("text", "html"))
                            {
                                RenderMultipartRelated(related);
                                return;
                            }

                            continue;
                        }

                        text = multipart[i - 1] as TextPart;

                        if (text == null)
                        {
                            continue;
                        }

                        if (text.IsHtml)
                        {
                            // we prefer html over plain text
                            preferred = text;
                            break;
                        }

                        if (preferred == null)
                        {
                            // we'll take what we can get
                            preferred = text;
                        }
                    }

                    if (preferred != null)
                    {
                        RenderText(preferred);
                    }
                }
                else if (multipart.Count > 0)
                {
                    // At this point we know we're not dealing with a multipart/related or a
                    // multipart/alternative, so we can safely treat this as a multipart/mixed
                    // even if it's not.

                    // The main message body is usually the first part of a multipart/mixed. I
                    // suppose that it might be better to render the first text/* part instead
                    // (in case it's not the first part), but that's rare and probably also
                    // indicates that the text is meant to be displayed between the other parts
                    // (probably images or video?) in some sort of pseudo-multimedia "document"
                    // layout. Modern clients don't do this, they use HTML or RTF instead.
                    Render(multipart[0]);
                }
            }
            else if (text != null)
            {
                // render the text part
                RenderText(text);
            }
            else
            {
                // message/rfc822 part
            }
        }
コード例 #37
0
		/// <summary>
		/// Verifies the signed-data and returns the unencapsulated <see cref="MimeKit.MimeEntity"/>.
		/// </summary>
		/// <remarks>
		/// Verifies the signed-data and returns the unencapsulated <see cref="MimeKit.MimeEntity"/>.
		/// </remarks>
		/// <returns>The list of digital signatures.</returns>
		/// <param name="ctx">The S/MIME context to use for verifying the signature.</param>
		/// <param name="entity">The unencapsulated entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="ctx"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.InvalidOperationException">
		/// The "smime-type" parameter on the Content-Type header is not "signed-data".
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public DigitalSignatureCollection Verify (SecureMimeContext ctx, out MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (SecureMimeType != SecureMimeType.SignedData)
				throw new InvalidOperationException ();

			using (var memory = new MemoryBlockStream ()) {
				ContentObject.DecodeTo (memory);
				memory.Position = 0;

				return ctx.Verify (memory, out entity);
			}
		}
コード例 #38
0
        public void TextConstructiorShouldCreateTextPlain()
        {
            MimeEntity e = new MimeEntity("Hello, world");

            Assert.True(e.HasMediaType("text/plain"));
        }
コード例 #39
0
		/// <summary>
		/// Compresses the specified entity.
		/// </summary>
		/// <remarks>
		/// <para>Compresses the specified entity using the specified <see cref="SecureMimeContext"/>.</para>
		/// <para>It should be noted that this feature is not supported by most mail clients,
		/// even among those that support S/MIME.</para>
		/// </remarks>
		/// <returns>The compressed entity.</returns>
		/// <param name="ctx">The S/MIME context to use for compressing.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Compress (SecureMimeContext ctx, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var memory = new MemoryBlockStream ()) {
				var options = FormatOptions.CloneDefault ();
				options.NewLineFormat = NewLineFormat.Dos;

				entity.WriteTo (options, memory);
				memory.Position = 0;

				return ctx.Compress (memory);
			}
		}
コード例 #40
0
        public void TextPlainShouldNotBeMultipart()
        {
            MimeEntity e = new MimeEntity("Hello, world");

            Assert.False(e.IsMultiPart);
        }
コード例 #41
0
		/// <summary>
		/// Encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Encrypts the entity to the specified recipients using the supplied <see cref="SecureMimeContext"/>.
		/// </remarks>
		/// <returns>The encrypted entity.</returns>
		/// <param name="ctx">The S/MIME context to use for encrypting.</param>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// Valid certificates could not be found for one or more of the <paramref name="recipients"/>.
		/// </exception>
		/// <exception cref="CertificateNotFoundException">
		/// A certificate could not be found for one or more of the <paramref name="recipients"/>.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Encrypt (SecureMimeContext ctx, IEnumerable<MailboxAddress> recipients, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var memory = new MemoryBlockStream ()) {
				var options = FormatOptions.CloneDefault ();
				options.NewLineFormat = NewLineFormat.Dos;

				entity.WriteTo (options, memory);
				memory.Position = 0;

				return (ApplicationPkcs7Mime) ctx.Encrypt (recipients, memory);
			}
		}
コード例 #42
0
        public void BodyTextShouldBeAccessible()
        {
            MimeEntity e = new MimeEntity("Hello, world");

            Assert.Equal("Hello, world", e.Body.Text);
        }
コード例 #43
0
		/// <summary>
		/// Cryptographically signs the specified entity.
		/// </summary>
		/// <remarks>
		/// <para>Signs the entity using the supplied signer.</para>
		/// <para>For better interoperability with other mail clients, you should use
		/// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/>
		/// instead as the multipart/signed format is supported among a much larger
		/// subset of mail client software.</para>
		/// </remarks>
		/// <returns>The signed entity.</returns>
		/// <param name="signer">The signer.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime Sign (CmsSigner signer, MimeEntity entity)
		{
			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-mime")) {
				return Sign (ctx, signer, entity);
			}
		}
コード例 #44
0
        public void BodySourceTextShouldBeAccessible()
        {
            MimeEntity e = new MimeEntity("Hello, world");

            Assert.Equal("Hello, world", e.Body.SourceText.ToString());
        }
コード例 #45
0
		/// <summary>
		/// Cryptographically signs and encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs entity using the supplied signer and then
		/// encrypts the result to the specified recipients.
		/// </remarks>
		/// <returns>The signed and encrypted entity.</returns>
		/// <param name="ctx">The S/MIME context to use for signing and encrypting.</param>
		/// <param name="signer">The signer.</param>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime SignAndEncrypt (SecureMimeContext ctx, CmsSigner signer, CmsRecipientCollection recipients, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			return Encrypt (ctx, recipients, MultipartSigned.Create (ctx, signer, entity));
		}
コード例 #46
0
        public void EntityShouldHaveParsedContentType(string mediaType)
        {
            MimeEntity e = new MimeEntity("Hello, world", mediaType);

            Assert.Equal(mediaType, e.ParsedContentType.MediaType);
        }
コード例 #47
0
		/// <summary>
		/// Cryptographically signs and encrypts the specified entity.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs entity using the supplied signer and then
		/// encrypts the result to the specified recipients.
		/// </remarks>
		/// <returns>The signed and encrypted entity.</returns>
		/// <param name="ctx">The S/MIME context to use for signing and encrypting.</param>
		/// <param name="signer">The signer.</param>
		/// <param name="digestAlgo">The digest algorithm to use for signing.</param>
		/// <param name="recipients">The recipients.</param>
		/// <param name="entity">The entity.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="CertificateNotFoundException">
		/// <para>A signing certificate could not be found for <paramref name="signer"/>.</para>
		/// <para>-or-</para>
		/// <para>A certificate could not be found for one or more of the <paramref name="recipients"/>.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static ApplicationPkcs7Mime SignAndEncrypt (SecureMimeContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, IEnumerable<MailboxAddress> recipients, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			return Encrypt (ctx, recipients, MultipartSigned.Create (ctx, signer, digestAlgo, entity));
		}
コード例 #48
0
 /// <summary>
 /// Verify the digital signatures of the specified signed data and extract the original content.
 /// </summary>
 /// <remarks>
 /// Verifies the digital signatures of the specified signed data and extracts the original content.
 /// </remarks>
 /// <returns>The list of digital signatures.</returns>
 /// <param name="signedData">The signed data.</param>
 /// <param name="entity">The extracted MIME entity.</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <exception cref="System.ArgumentNullException">
 /// <paramref name="signedData"/> is <c>null</c>.
 /// </exception>
 /// <exception cref="System.FormatException">
 /// The extracted content could not be parsed as a MIME entity.
 /// </exception>
 /// <exception cref="System.OperationCanceledException">
 /// The operation was cancelled via the cancellation token.
 /// </exception>
 public abstract DigitalSignatureCollection Verify(Stream signedData, out MimeEntity entity, CancellationToken cancellationToken = default(CancellationToken));
コード例 #49
0
		/// <summary>
		/// Creates a new <see cref="MultipartEncrypted"/>.
		/// </summary>
		/// <remarks>
		/// Signs the entity using the supplied signer and digest algorithm and then encrypts to
		/// the specified recipients, encapsulating the result in a new multipart/encrypted part.
		/// </remarks>
		/// <returns>A new <see cref="MimeKit.Cryptography.MultipartEncrypted"/> instance containing
		/// the signed and encrypted version of the specified entity.</returns>
		/// <param name="signer">The signer to use to sign the entity.</param>
		/// <param name="digestAlgo">The digest algorithm to use for signing.</param>
		/// <param name="recipients">The recipients for the encrypted entity.</param>
		/// <param name="entity">The entity to sign and encrypt.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// A default <see cref="OpenPgpContext"/> has not been registered.
		/// </exception>
		/// <exception cref="PrivateKeyNotFoundException">
		/// The private key for <paramref name="signer"/> could not be found.
		/// </exception>
		/// <exception cref="PublicKeyNotFoundException">
		/// A public key for one or more of the <paramref name="recipients"/> could not be found.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The user chose to cancel the password prompt.
		/// </exception>
		/// <exception cref="System.UnauthorizedAccessException">
		/// 3 bad attempts were made to unlock the secret key.
		/// </exception>
		public static MultipartEncrypted Create (MailboxAddress signer, DigestAlgorithm digestAlgo, IEnumerable<MailboxAddress> recipients, MimeEntity entity)
		{
			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var ctx = (OpenPgpContext) CryptographyContext.Create ("application/pgp-encrypted")) {
				return Create (ctx, signer, digestAlgo, recipients, entity);
			}
		}
コード例 #50
0
 public MimeKitContent(MimeEntity entity = null)
 {
     MimeEntity = entity;
 }
コード例 #51
0
		/// <summary>
		/// Creates a new <see cref="MultipartEncrypted"/>.
		/// </summary>
		/// <remarks>
		/// Encrypts the entity to the specified recipients, encapsulating the result in a
		/// new multipart/encrypted part.
		/// </remarks>
		/// <returns>A new <see cref="MimeKit.Cryptography.MultipartEncrypted"/> instance containing
		/// the encrypted version of the specified entity.</returns>
		/// <param name="ctx">The OpenPGP cryptography context to use for encrypting.</param>
		/// <param name="recipients">The recipients for the encrypted entity.</param>
		/// <param name="entity">The entity to sign and encrypt.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// One or more of the recipient keys cannot be used for encrypting.
		/// </exception>
		public static MultipartEncrypted Create (OpenPgpContext ctx, IEnumerable<PgpPublicKey> recipients, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException ("ctx");

			if (recipients == null)
				throw new ArgumentNullException ("recipients");

			if (entity == null)
				throw new ArgumentNullException ("entity");

			using (var memory = new MemoryStream ()) {
				using (var filtered = new FilteredStream (memory)) {
					filtered.Add (new Unix2DosFilter ());

					PrepareEntityForEncrypting (entity);
					entity.WriteTo (filtered);
					filtered.Flush ();
				}

				memory.Position = 0;

				var encrypted = new MultipartEncrypted ();
				encrypted.ContentType.Parameters["protocol"] = ctx.EncryptionProtocol;

				// add the protocol version part
				encrypted.Add (new ApplicationPgpEncrypted ());

				// add the encrypted entity as the second part
				encrypted.Add (ctx.Encrypt (recipients, memory));

				return encrypted;
			}
		}
コード例 #52
0
 public static IPostbode SetMimeKitContent(this IPostbode postbode, MimeEntity content)
 {
     postbode.SetContent(new MimeKitContent(content));
     return(postbode);
 }
コード例 #53
0
        /// <summary>
        /// 一个修改后的版本,CreateFromMailMessage()方法在 https://github.com/jstedfast/MimeKit/blob/master/MimeKit/MimeMessage.cs
        /// </summary>
        /// <param name="mail"></param>
        /// <returns></returns>
        public static MimeMessage ToMimeMessage(this MailMessage mail)
        {
            if (mail == null)
            {
                throw new ArgumentNullException(nameof(mail));
            }

            var headers = new List <Header>();

            foreach (var field in mail.Headers.AllKeys)
            {
                foreach (var value in mail.Headers.GetValues(field))
                {
                    headers.Add(new Header(field, value));
                }
            }

            var        message = new MimeMessage(headers.ToArray());
            MimeEntity body    = null;

            // Note: If the user has already sent their MailMessage via System.Net.Mail.SmtpClient,
            // then the following MailMessage properties will have been merged into the Headers, so
            // check to make sure our MimeMessage properties are empty before adding them.
            if (mail.Sender != null)
            {
                message.Sender = mail.Sender.ToMailboxAddress();
            }

            if (mail.From != null)
            {
                message.Headers.Replace(HeaderId.From, string.Empty);
                message.From.Add(mail.From.ToMailboxAddress());
            }

            if (mail.ReplyToList.Count > 0)
            {
                message.Headers.Replace(HeaderId.ReplyTo, string.Empty);
                message.ReplyTo.AddRange(mail.ReplyToList.ToInternetAddressList());
            }

            if (mail.To.Count > 0)
            {
                message.Headers.Replace(HeaderId.To, string.Empty);
                message.To.AddRange(mail.To.ToInternetAddressList());
            }

            if (mail.CC.Count > 0)
            {
                message.Headers.Replace(HeaderId.Cc, string.Empty);
                message.Cc.AddRange(mail.CC.ToInternetAddressList());
            }

            if (mail.Bcc.Count > 0)
            {
                message.Headers.Replace(HeaderId.Bcc, string.Empty);
                message.Bcc.AddRange(mail.Bcc.ToInternetAddressList());
            }

            if (mail.SubjectEncoding != null)
            {
                message.Headers.Replace(HeaderId.Subject, mail.SubjectEncoding, mail.Subject ?? string.Empty);
            }
            else
            {
                message.Subject = mail.Subject ?? string.Empty;
            }

            switch (mail.Priority)
            {
            case MailPriority.Normal:
                message.Headers.RemoveAll(HeaderId.XMSMailPriority);
                message.Headers.RemoveAll(HeaderId.Importance);
                message.Headers.RemoveAll(HeaderId.XPriority);
                message.Headers.RemoveAll(HeaderId.Priority);
                break;

            case MailPriority.High:
                message.Headers.Replace(HeaderId.Priority, "urgent");
                message.Headers.Replace(HeaderId.Importance, "high");
                message.Headers.Replace(HeaderId.XPriority, "2 (High)");
                break;

            case MailPriority.Low:
                message.Headers.Replace(HeaderId.Priority, "non-urgent");
                message.Headers.Replace(HeaderId.Importance, "low");
                message.Headers.Replace(HeaderId.XPriority, "4 (Low)");
                break;
            }

            if (!string.IsNullOrEmpty(mail.Body))
            {
                var text = new TextPart(mail.IsBodyHtml ? "html" : "plain");
                text.SetText(mail.BodyEncoding ?? Encoding.UTF8, mail.Body);
                body = text;
            }

            if (mail.AlternateViews.Count > 0)
            {
                var alternative = new MultipartAlternative();

                if (body != null)
                {
                    alternative.Add(body);
                }

                foreach (var view in mail.AlternateViews)
                {
                    var part = GetMimePart(view);

                    if (view.BaseUri != null)
                    {
                        part.ContentLocation = view.BaseUri;
                    }

                    if (view.LinkedResources.Count > 0)
                    {
                        var type    = part.ContentType.MediaType + "/" + part.ContentType.MediaSubtype;
                        var related = new MultipartRelated();

                        related.ContentType.Parameters.Add("type", type);

                        if (view.BaseUri != null)
                        {
                            related.ContentLocation = view.BaseUri;
                        }

                        related.Add(part);

                        foreach (var resource in view.LinkedResources)
                        {
                            part = GetMimePart(resource);

                            if (resource.ContentLink != null)
                            {
                                part.ContentLocation = resource.ContentLink;
                            }

                            related.Add(part);
                        }

                        alternative.Add(related);
                    }
                    else
                    {
                        alternative.Add(part);
                    }
                }

                body = alternative;
            }

            if (body == null)
            {
                body = new TextPart(mail.IsBodyHtml ? "html" : "plain");
            }

            if (mail.Attachments.Count > 0)
            {
                var mixed = new Multipart("mixed");

                if (body != null)
                {
                    mixed.Add(body);
                }

                foreach (var attachment in mail.Attachments)
                {
                    mixed.Add(GetMimePart(attachment));
                }

                body = mixed;
            }

            message.Body = body;

            return(message);
        }
コード例 #54
0
 /// <summary>
 /// Returns header fields lines except requested.
 /// Note: Header terminator blank line is included.
 /// </summary>
 /// <param name="fieldsStr">Header fields to skip.</param>
 /// <param name="entity">Entity which header field lines to get.</param>
 /// <returns></returns>
 public static byte[] ParseHeaderFieldsNot(string fieldsStr, MimeEntity entity)
 {
     return(ParseHeaderFieldsNot(fieldsStr, Encoding.Default.GetBytes(entity.HeaderString)));
 }
コード例 #55
0
ファイル: MultipartSigned.cs プロジェクト: gphummer/MimeKit
		/// <summary>
		/// Creates a new <see cref="MultipartSigned"/>.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs the entity using the supplied signer and digest algorithm in
		/// order to generate a detached signature and then adds the entity along with the
		/// detached signature data to a new multipart/signed part.
		/// </remarks>
		/// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
		/// <param name="signer">The signer.</param>
		/// <param name="digestAlgo">The digest algorithm to use for signing.</param>
		/// <param name="entity">The entity to sign.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <paramref name="signer"/> cannot be used for signing.
		/// </exception>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// The <paramref name="digestAlgo"/> was out of range.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>A cryptography context suitable for signing could not be found.</para>
		/// <para>-or-</para>
		/// <para>The <paramref name="digestAlgo"/> is not supported.</para>
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">
		/// An error occurred in the OpenPGP subsystem.
		/// </exception>
		public static MultipartSigned Create (PgpSecretKey signer, DigestAlgorithm digestAlgo, MimeEntity entity)
		{
			using (var ctx = (OpenPgpContext) CryptographyContext.Create ("application/pgp-signature")) {
				return Create (ctx, signer, digestAlgo, entity);
			}
		}
コード例 #56
0
 /// <summary>
 /// Gets specified mime entity header.
 /// Note: Header terminator blank line is included.
 /// </summary>
 /// <param name="entity">Mime entity.</param>
 /// <returns></returns>
 public static byte[] GetMimeEntityHeader(MimeEntity entity)
 {
     return(Encoding.ASCII.GetBytes(entity.HeaderString + "\r\n"));
 }
コード例 #57
0
ファイル: MultipartSigned.cs プロジェクト: gphummer/MimeKit
		/// <summary>
		/// Creates a new <see cref="MultipartSigned"/>.
		/// </summary>
		/// <remarks>
		/// Cryptographically signs the entity using the supplied signer in order
		/// to generate a detached signature and then adds the entity along with
		/// the detached signature data to a new multipart/signed part.
		/// </remarks>
		/// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
		/// <param name="signer">The signer.</param>
		/// <param name="entity">The entity to sign.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// A cryptography context suitable for signing could not be found.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Cms.CmsException">
		/// An error occurred in the cryptographic message syntax subsystem.
		/// </exception>
		public static MultipartSigned Create (CmsSigner signer, MimeEntity entity)
		{
			using (var ctx = (SecureMimeContext) CryptographyContext.Create ("application/pkcs7-signature")) {
				return Create (ctx, signer, entity);
			}
		}
コード例 #58
0
		/// <summary>
		/// Create a multipart/encrypted MIME part by signing and encrypting the specified entity.
		/// </summary>
		/// <remarks>
		/// Signs the entity using the supplied signer and digest algorithm and then encrypts to
		/// the specified recipients, encapsulating the result in a new multipart/encrypted part.
		/// </remarks>
		/// <returns>A new <see cref="MultipartEncrypted"/> instance containing
		/// the signed and encrypted version of the specified entity.</returns>
		/// <param name="ctx">The OpenPGP cryptography context to use for signing and encrypting.</param>
		/// <param name="signer">The signer to use to sign the entity.</param>
		/// <param name="digestAlgo">The digest algorithm to use for signing.</param>
		/// <param name="recipients">The recipients for the encrypted entity.</param>
		/// <param name="entity">The entity to sign and encrypt.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="ctx"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="recipients"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="entity"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="PrivateKeyNotFoundException">
		/// The private key for <paramref name="signer"/> could not be found.
		/// </exception>
		/// <exception cref="PublicKeyNotFoundException">
		/// A public key for one or more of the <paramref name="recipients"/> could not be found.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The user chose to cancel the password prompt.
		/// </exception>
		/// <exception cref="System.UnauthorizedAccessException">
		/// 3 bad attempts were made to unlock the secret key.
		/// </exception>
		public static MultipartEncrypted SignAndEncrypt (OpenPgpContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, IEnumerable<MailboxAddress> recipients, MimeEntity entity)
		{
			if (ctx == null)
				throw new ArgumentNullException (nameof (ctx));

			if (signer == null)
				throw new ArgumentNullException (nameof (signer));

			if (recipients == null)
				throw new ArgumentNullException (nameof (recipients));

			if (entity == null)
				throw new ArgumentNullException (nameof (entity));

			using (var memory = new MemoryBlockStream ()) {
				var options = FormatOptions.CloneDefault ();
				options.NewLineFormat = NewLineFormat.Dos;

				entity.WriteTo (options, memory);
				memory.Position = 0;

				var encrypted = new MultipartEncrypted ();
				encrypted.ContentType.Parameters["protocol"] = ctx.EncryptionProtocol;

				// add the protocol version part
				encrypted.Add (new ApplicationPgpEncrypted ());

				// add the encrypted entity as the second part
				encrypted.Add (ctx.SignAndEncrypt (signer, digestAlgo, recipients, memory));

				return encrypted;
			}
		}
コード例 #59
0
        /// <summary>
        /// Verify the digital signatures of the specified signedData and extract the original content.
        /// </summary>
        /// <returns>The list of digital signatures.</returns>
        /// <param name="signedData">The signed data.</param>
        /// <param name="entity">The unencapsulated entity.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="signedData"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public DigitalSignatureCollection Verify(Stream signedData, out MimeEntity entity)
        {
            if (signedData == null)
                throw new ArgumentNullException ("signedData");

            var parser = new CmsSignedDataParser (signedData);
            var signed = parser.GetSignedContent ();

            entity = MimeEntity.Load (signed.ContentStream);

            return GetDigitalSignatures (parser);
        }
コード例 #60
0
        /*
         * Actual implementation of creation of MimeEntity, recursively runs through given node, and creates a MimeEntity accordingly.
         */
        MimeEntity Create(Node entityNode)
        {
            // Sanity check.
            if (string.IsNullOrEmpty(entityNode.Value as string))
            {
                throw new LambdaException(
                          string.Format("No media subtype provided for '{0}' to MIME builder", entityNode.Name),
                          entityNode,
                          _context);
            }

            // Setting up a return value.
            MimeEntity retVal = null;

            // Figuring out which type to create.
            switch (entityNode.Name)
            {
            case "multipart":
                retVal = CreateMultipart(entityNode);
                break;

            case "text":
            case "image":
            case "application":
            case "audio":
            case "video":
            case "message":
            case "example":
            case "model":
                retVal = CreateLeafPart(entityNode);
                break;

            default:
                throw new LambdaException(
                          string.Format("Unknown media type '{0}' for MIME builder", entityNode.Name),
                          entityNode,
                          _context);
            }

            // Figuring out if entity should be encrypted and/or signed.
            bool shouldSign    = entityNode ["sign"] != null;
            bool shouldEncrypt = entityNode ["encrypt"] != null;

            // Signing and/or encrypting entity, if we should.
            if (shouldSign && !shouldEncrypt)
            {
                // Only signing entity.
                retVal = SignEntity(entityNode, retVal);
            }
            else if (shouldEncrypt && !shouldSign)
            {
                // Only encrypting entity.
                retVal = EncryptEntity(entityNode, retVal);
            }
            else if (shouldEncrypt && shouldSign)
            {
                // Signing and encrypting entity.
                retVal = SignAndEncryptEntity(entityNode, retVal);
            }

            // Returning entity to caller.
            return(retVal);
        }