示例#1
0
		/// <summary>
		/// Parses a bodypart entry from the body structure and advances the
		/// read pointer.
		/// </summary>
		/// <param name="partNumber">The designated part specifier by which the body
		/// part is refered to by the server.</param>
		/// <param name="parenthesis">Set to true if the bodypart is enclosed
		/// in parenthesis.</param>
		/// <returns></returns>
		private Bodypart ParseBodypart(string partNumber, bool parenthesis = true) {
			Bodypart part = new Bodypart(partNumber);
			// Mandatory fields:
			//  "Type"² "Subtype"² ("Attribute" "Value")² "Id"² "Description"² "Encoding"² Size³
			//  ² String value, but can be NIL, ³ Integer value
			part.Type = ContentTypeMap.fromString(reader.ReadWord());
			part.Subtype = reader.ReadWord();
			part.Parameters = reader.ReadList();
			part.Id = reader.ReadWord();
			part.Description = reader.ReadWord();
			part.Encoding = ContentTransferEncodingMap.fromString(reader.ReadWord());
			part.Size = reader.ReadInteger();
			if (part.Type == ContentType.Text)
				part.Lines = reader.ReadInteger();
			try {
				ParseOptionalFields(part, parenthesis);
			} catch (EndOfStringException) {}
			return part;
		}
示例#2
0
		/// <summary>
		/// Creates an instance of the AlternateView class used by the MailMessage class
		/// to store alternate views of the mail message's content.
		/// </summary>
		/// <param name="part">The MIME body part to create the alternate view from.</param>
		/// <param name="bytes">An array of bytes composing the content of the
		/// alternate view</param>
		/// <returns>An initialized instance of the AlternateView class</returns>
		private static AlternateView CreateAlternateView(Bodypart part, byte[] bytes) {
			MemoryStream stream = new MemoryStream(bytes);
			string contentType = part.Type.ToString().ToLower() + "/" +
				part.Subtype.ToLower();
			AlternateView view = new AlternateView(stream,
				new System.Net.Mime.ContentType(contentType));
			try {
				view.ContentId = ParseMessageId(part.Id);
			} catch {}
			return view;
		}
示例#3
0
		/// <summary>
		/// Creates an instance of the Attachment class used by the MailMessage class
		/// to store mail message attachments.
		/// </summary>
		/// <param name="part">The MIME body part to create the attachment from.</param>
		/// <param name="bytes">An array of bytes composing the content of the
		/// attachment</param>
		/// <returns>An initialized instance of the Attachment class</returns>
		private static Attachment CreateAttachment(Bodypart part, byte[] bytes) {
			MemoryStream stream = new MemoryStream(bytes);
			string name = part.Disposition.Filename ?? Path.GetRandomFileName();
			Attachment attachment = new Attachment(stream, name);
			try {
				attachment.ContentId = ParseMessageId(part.Id);
			} catch {}
			string contentType = part.Type.ToString().ToLower() + "/" +
				part.Subtype.ToLower();
			attachment.ContentType = new System.Net.Mime.ContentType(contentType);
			return attachment;
		}
示例#4
0
		/// <summary>
		/// Adds a body part to an existing MailMessage instance.
		/// </summary>
		/// <param name="message">Extension method for the MailMessage class.</param>
		/// <param name="part">The body part to add to the MailMessage instance.</param>
		/// <param name="content">The content of the body part.</param>
		internal static void AddBodypart(this MailMessage message, Bodypart part, string content) {
			Encoding encoding = part.Parameters.ContainsKey("Charset") ?
				Util.GetEncoding(part.Parameters["Charset"]) : Encoding.ASCII;
			// decode content if it was encoded
			byte[] bytes;
			switch (part.Encoding) {
				case ContentTransferEncoding.QuotedPrintable:
					bytes = encoding.GetBytes(Util.QPDecode(content, encoding));
					break;
				case ContentTransferEncoding.Base64:
					bytes = Util.Base64Decode(content);
					break;
				default:
					bytes = Encoding.ASCII.GetBytes(content);
					break;
			}

			// If the MIME part contains text and the MailMessage's Body fields haven't been
			// initialized yet, put it there.
			if (message.Body == string.Empty && part.Type == ContentType.Text) {
				message.Body = encoding.GetString(bytes);
				message.BodyEncoding = encoding;
				message.IsBodyHtml = part.Subtype.ToLower() == "html";
				return;
			}

			if (part.Disposition.Type == ContentDispositionType.Attachment)
				message.Attachments.Add(CreateAttachment(part, bytes));
			else
				message.AlternateViews.Add(CreateAlternateView(part, bytes));
		}
示例#5
0
 /// <summary>
 ///   Glue method to create a bodypart from a MIMEPart instance.
 /// </summary>
 /// <param name="mimePart">
 ///   The MIMEPart instance to create the
 ///   bodypart instance from.
 /// </param>
 /// <returns>An initialized instance of the Bodypart class.</returns>
 private static Bodypart BodypartFromMIME(MIMEPart mimePart)
 {
   var contentType = ParseMIMEField(
     mimePart.header["Content-Type"]);
   var p = new Bodypart(null);
   var m = Regex.Match(contentType["value"], "(.+)/(.+)");
   if (m.Success)
   {
     p.Type = ContentTypeMap.fromString(m.Groups[1].Value);
     p.Subtype = m.Groups[2].Value;
   }
   p.Encoding = ContentTransferEncodingMap.fromString(
     mimePart.header["Content-Transfer-Encoding"]);
   p.Id = mimePart.header["Content-Id"];
   foreach (var k in contentType.AllKeys)
     p.Parameters.Add(k, contentType[k]);
   p.Size = mimePart.body.Length;
   if (mimePart.header["Content-Disposition"] != null)
   {
     var disposition = ParseMIMEField(
       mimePart.header["Content-Disposition"]);
     p.Disposition.Type = ContentDispositionTypeMap.fromString(
       disposition["value"]);
     p.Disposition.Filename = disposition["Filename"];
     foreach (var k in disposition.AllKeys)
       p.Disposition.Attributes.Add(k, disposition[k]);
   }
   return p;
 }
示例#6
0
    /// <summary>
    ///   Adds a body part to an existing MailMessage instance.
    /// </summary>
    /// <param name="message">Extension method for the MailMessage class.</param>
    /// <param name="part">The body part to add to the MailMessage instance.</param>
    /// <param name="content">The content of the body part.</param>
    internal static void AddBodypart(this MailMessage message, Bodypart part, string content)
    {
      var encoding = part.Parameters.ContainsKey("Charset")
        ? Util.GetEncoding(part.Parameters["Charset"])
        : Encoding.ASCII;
      // decode content if it was encoded
      byte[] bytes;
      try
      {
        switch (part.Encoding)
        {
          case ContentTransferEncoding.QuotedPrintable:
            bytes = encoding.GetBytes(Util.QPDecode(content, encoding));
            break;
          case ContentTransferEncoding.Base64:
            bytes = Util.Base64Decode(content);
            break;
          default:
            bytes = Encoding.ASCII.GetBytes(content);
            break;
        }
      }
      catch
      {
        // If it's not a valid Base64 or quoted-printable encoded string
        // just leave the data as is
        bytes = Encoding.ASCII.GetBytes(content);
      }

      // If the MailMessage's Body fields haven't been initialized yet, put it there.
      // Some weird (i.e. spam) mails like to omit content-types so don't check for
      // that here and just assume it's text.
      if (message.Body == string.Empty)
      {
        message.Body = encoding.GetString(bytes);
        message.BodyEncoding = encoding;
        message.IsBodyHtml = part.Subtype.ToLower() == "html";
        return;
      }

      if (part.Disposition.Type == ContentDispositionType.Attachment)
        message.Attachments.Add(CreateAttachment(part, bytes));
      else
        message.AlternateViews.Add(CreateAlternateView(part, bytes));
    }
示例#7
0
		/// <summary>
		/// Creates an instance of the Attachment class used by the MailMessage class to store mail
		/// message attachments.
		/// </summary>
		/// <param name="part">The MIME body part to create the attachment from.</param>
		/// <param name="bytes">An array of bytes composing the content of the attachment.</param>
		/// <returns>An initialized instance of the Attachment class.</returns>
		static Attachment CreateAttachment(Bodypart part, byte[] bytes) {
			MemoryStream stream = new MemoryStream(bytes);
			string name = part.Disposition.Filename;
			// Many MUAs put the file name in the name parameter of the content-type header instead of
			// the filename parameter of the content-disposition header.
			if (String.IsNullOrEmpty(name) && part.Parameters.ContainsKey("name"))
				name = part.Parameters["name"];
			if (String.IsNullOrEmpty(name))
				name = Path.GetRandomFileName();
			Attachment attachment = new Attachment(stream, name);
			try {
				attachment.ContentId = ParseMessageId(part.Id);
			} catch { }
			try {
				attachment.ContentType = new System.Net.Mime.ContentType(
					part.Type.ToString().ToLower() + "/" + part.Subtype.ToLower());
			} catch {
				attachment.ContentType = new System.Net.Mime.ContentType();
			}
			// Workaround: filename from Attachment constructor is ignored with Mono.
			attachment.Name = name;
			attachment.ContentDisposition.FileName = name;
			return attachment;
		}
示例#8
0
		/// <summary>
		/// Adds a body part to an existing MailMessage instance.
		/// </summary>
		/// <param name="message">Extension method for the MailMessage class.</param>
		/// <param name="part">The body part to add to the MailMessage instance.</param>
		/// <param name="content">The content of the body part.</param>
		internal static void AddBodypart(this MailMessage message, Bodypart part, string content) {
			Encoding encoding = part.Parameters.ContainsKey("Charset") ?
				Util.GetEncoding(part.Parameters["Charset"]) : Encoding.ASCII;
			// Decode the content if it is encoded.
			byte[] bytes;
			try {
				switch (part.Encoding) {
					case ContentTransferEncoding.QuotedPrintable:
						bytes = encoding.GetBytes(Util.QPDecode(content, encoding));
						break;
					case ContentTransferEncoding.Base64:
						bytes = Util.Base64Decode(content);
						break;
					default:
						bytes = Encoding.ASCII.GetBytes(content);
						break;
				}
			} catch {
				// If it's not a valid Base64 or quoted-printable encoded string just leave the data as is.
				bytes = Encoding.ASCII.GetBytes(content);
			}

			// If the part has a name it most likely is an attachment and it should go into the
			// Attachments collection.
			bool hasName = part.Parameters.ContainsKey("name");

			// If the MailMessage's Body fields haven't been initialized yet, put it there. Some weird
			// (i.e. spam) mails like to omit content-types so we don't check for that here and just
			// assume it's text.
			if (String.IsNullOrEmpty(message.Body) &&
				part.Disposition.Type != ContentDispositionType.Attachment) {
				message.Body = encoding.GetString(bytes);
				message.BodyEncoding = encoding;
				message.IsBodyHtml = part.Subtype.ToLower() == "html";
				return;
			}

			// Check for alternative view.
			string ContentType = ParseMIMEField(message.Headers["Content-Type"])["value"];
			bool preferAlternative = string.Compare(ContentType, "multipart/alternative", true) == 0;

			// Many attachments are missing the disposition-type. If it's not defined as alternative
			// and it has a name attribute, assume it is Attachment rather than an AlternateView.
			if (part.Disposition.Type == ContentDispositionType.Attachment ||
				(part.Disposition.Type == ContentDispositionType.Unknown &&
				preferAlternative == false && hasName))
				message.Attachments.Add(CreateAttachment(part, bytes));
			else
				message.AlternateViews.Add(CreateAlternateView(part, bytes));
		}
示例#9
0
        /// <summary>
        /// Adds a body part to an existing MailMessage instance.
        /// </summary>
        /// <param name="message">Extension method for the MailMessage class.</param>
        /// <param name="part">The body part to add to the MailMessage instance.</param>
        /// <param name="content">The content of the body part.</param>
        internal static void AddBodypart(this MailMessage message, Bodypart part, string content, bool getHtml = false)
        {
            Encoding encoding = part.Parameters.ContainsKey("Charset") ?
                                Util.GetEncoding(part.Parameters["Charset"]) : Encoding.ASCII;

            // Decode the content if it is encoded.
            byte[] bytes;
            try {
                switch (part.Encoding)
                {
                case ContentTransferEncoding.QuotedPrintable:
                    bytes = encoding.GetBytes(Util.QPDecode(content, encoding));
                    break;

                case ContentTransferEncoding.Base64:
                    bytes = Util.Base64Decode(content);
                    break;

                default:
                    bytes = Encoding.ASCII.GetBytes(content);
                    break;
                }
            } catch {
                // If it's not a valid Base64 or quoted-printable encoded string just leave the data as is.
                bytes = Encoding.ASCII.GetBytes(content);
            }

            // If the part has a name it most likely is an attachment and it should go into the
            // Attachments collection.
            bool hasName = part.Parameters.ContainsKey("name");

            // If the MailMessage's Body fields haven't been initialized yet, put it there. Some weird
            // (i.e. spam) mails like to omit content-types so we don't check for that here and just
            // assume it's text.
            if (part.Disposition.Type != ContentDispositionType.Attachment)
            {
                message.BodyEncoding = encoding;
                message.IsBodyHtml   = part.Subtype.ToLower() == "html";
                if (!string.IsNullOrEmpty(message.Body))
                {
                    if (getHtml && message.IsBodyHtml)
                    {
                        message.Body = encoding.GetString(bytes);
                    }
                    else
                    {
                        message.Body += (message.IsBodyHtml ? ("[[--html--]]") : "") + encoding.GetString(bytes);
                    }

                    return;
                }
                message.Body = encoding.GetString(bytes);
                return;
            }

            // Check for alternative view.
            string ContentType       = ParseMIMEField(message.Headers["Content-Type"])["value"];
            bool   preferAlternative = string.Compare(ContentType, "multipart/alternative", true) == 0;

            // Many attachments are missing the disposition-type. If it's not defined as alternative
            // and it has a name attribute, assume it is Attachment rather than an AlternateView.
            if (part.Disposition.Type == ContentDispositionType.Attachment ||
                (part.Disposition.Type == ContentDispositionType.Unknown &&
                 preferAlternative == false && hasName))
            {
                message.Attachments.Add(CreateAttachment(part, bytes));
            }
            else
            {
                message.AlternateViews.Add(CreateAlternateView(part, bytes));
            }
        }
示例#10
0
		/// <summary>
		/// Parses the mandatory extra fields that are present if the bodypart is
		/// of type message/rfc822 (see RFC 3501, p. 75).
		/// </summary>
		/// <param name="part">The bodypart instance the parsed fields will be
		/// added to.</param>
		private void ParseMessage822Fields(Bodypart part) {
			// We just skip over most of this extra information as it is useless
			// to us.
			// Mandatory fields:
			//	"Envelope" "Bodystructure" "Lines"
			SkipParenthesizedExpression();
			SkipParenthesizedExpression();
			part.Lines = reader.ReadInteger();
		}
示例#11
0
		/// <summary>
		/// Parses the optional fields of a bodypart entry from the body structure
		/// and advances the read pointer.
		/// </summary>
		/// <param name="part">The bodypart instance the parsed fields will be
		/// added to.</param>
		/// <param name="parenthesis">Set to true if the bodypart entry is enclosed
		/// in parenthesis.</param>
		private void ParseOptionalFields(Bodypart part, bool parenthesis = true) {
			// Optional fields:
			//  "Md5"² ("Disposition" ("Attribute" "Value"))² "Language"² "Location"²
			if (parenthesis && reader.Peek(true) == ')') {
				reader.Read();
				return;
			}
			part.Md5 = reader.ReadWord();
			if (parenthesis && reader.Peek(true) == ')') {
				reader.Read();
				return;
			}
			part.Disposition = reader.ReadDisposition();
			if (parenthesis && reader.Peek(true) == ')') {
				reader.Read();
				return;
			}
			part.Language = reader.ReadWord();
			if (parenthesis && reader.Peek(true) == ')') {
				reader.Read();
				return;
			}
			part.Location = reader.ReadWord();
			if (parenthesis)
				reader.SkipUntil(')');
		}
示例#12
0
		/// <summary>
		/// Adds a body part to an existing MailMessage instance.
		/// </summary>
		/// <param name="message">Extension method for the MailMessage class.</param>
		/// <param name="part">The body part to add to the MailMessage instance.</param>
		/// <param name="content">The content of the body part.</param>
		internal static void AddBodypart(this MailMessage message, Bodypart part, string content) {
			Encoding encoding = part.Parameters.ContainsKey("Charset") ?
				Util.GetEncoding(part.Parameters["Charset"]) : Encoding.ASCII;
			// Decode the content if it is encoded.
			byte[] bytes;
			try {
				switch (part.Encoding) {
					case ContentTransferEncoding.QuotedPrintable:
						bytes = encoding.GetBytes(Util.QPDecode(content, encoding));
						break;
					case ContentTransferEncoding.Base64:
						bytes = Util.Base64Decode(content);
						break;
					default:
						bytes = Encoding.ASCII.GetBytes(content);
						break;
				}
			} catch {
				// If it's not a valid Base64 or quoted-printable encoded string
				// just leave the data as is
				bytes = Encoding.ASCII.GetBytes(content);
			}

			// Always a attachment if we have name? Because Inline != AlternateView ?
			bool haveName = part.Parameters.ContainsKey("name");

			// If the MailMessage's Body fields haven't been initialized yet, put it there.
			// Some weird (i.e. spam) mails like to omit content-types so we don't check for
			// that here and just assume it's text.
			if (String.IsNullOrEmpty(message.Body) &&
				part.Disposition.Type != ContentDispositionType.Attachment) {
				message.Body = encoding.GetString(bytes);
				message.BodyEncoding = encoding;
				message.IsBodyHtml = part.Subtype.ToLower() == "html";
				return;
			}
			string ContentType = ParseMIMEField(message.Headers["Content-Type"])["value"];
			bool preferAlternative = string.Compare(ContentType, "multipart/alternative", true) == 0;
			// handle "multipart/mixed" ?

			// Many attachments are missing Type, If we have a filename and not multipart/alternative then use attachment.
			if (part.Disposition.Type == ContentDispositionType.Attachment ||
				(part.Disposition.Type == ContentDispositionType.Unknown &&
				!preferAlternative && haveName))
				message.Attachments.Add(CreateAttachment(part, bytes));
			else
				message.AlternateViews.Add(CreateAlternateView(part, bytes));
		}