예제 #1
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)
        {
            NameValueCollection contentType = ParseMIMEField(
                mimePart.header["Content-Type"]);
            Bodypart p = new Bodypart(null);
            Match    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 (string k in contentType.AllKeys)
            {
                p.Parameters.Add(k, contentType[k]);
            }
            p.Size = mimePart.body.Length;
            if (mimePart.header["Content-Disposition"] != null)
            {
                NameValueCollection disposition = ParseMIMEField(
                    mimePart.header["Content-Disposition"]);
                p.Disposition.Type = ContentDispositionTypeMap.fromString(
                    disposition["value"]);
                p.Disposition.Filename = disposition["Filename"];
                foreach (string k in disposition.AllKeys)
                {
                    p.Disposition.Attributes.Add(k, disposition[k]);
                }
            }
            return(p);
        }
예제 #2
0
        /// <summary>
        /// Reads the message body of a MIME multipart message.
        /// </summary>
        /// <param name="boundary">The boundary string which separates
        /// the different parts which make up the multipart-message</param>
        /// <param name="nested">True if recursive call</param>
        /// <returns>A list of the MIME parts composing the multipart
        /// message</returns>
        /// <remarks>Each MIME part consists of its own set of header
        /// fields and a body.</remarks>
        private MIMEPart[] ReadMultipartBody(string boundary, bool nested = false)
        {
            List <MIMEPart> parts      = new List <MIMEPart>();
            string          s_boundary = "--" + boundary,
                            e_boundary = "--" + boundary + "--";
            /* skip everything up to the first boundary */
            string response = GetResponse();

            while (!response.StartsWith(s_boundary))
            {
                response = GetResponse();
            }
            /* read MIME parts enclosed in boundary strings */
            while (response.StartsWith(s_boundary))
            {
                MIMEPart part = new MIMEPart();
                /* read content-header of part */
                part.header = ReadMailHeader();
                /* account for nested multipart content */
                NameValueCollection contentType = ParseMIMEField(
                    part.header["Content-Type"]);
                if (contentType["Boundary"] != null)
                {
                    parts.AddRange(ReadMultipartBody(contentType["boundary"], true));
                }
                /* read content-body of part */
                while (!(response = GetResponse()).StartsWith(s_boundary))
                {
                    part.body = part.body + response + "\r\n";
                }

                /* add MIME part to the list unless body is null which means the body was
                 *              nested multipart content */
                if (part.body != null)
                {
                    parts.Add(part);
                }
                /* if the boundary is actually the end boundary, we're done */
                if (response.StartsWith(e_boundary))
                {
                    break;
                }
            }
            if (nested == false)
            {
                /* FETCH closing bracket may be last character of response */
                if (!response.EndsWith(")"))
                {
                    /* next read should return closing bracket from FETCH command then */
                    if ((response = GetResponse()) != ")")
                    {
                        throw new BadServerResponseException(response);
                    }
                }
            }
            return(parts.ToArray());
        }
예제 #3
0
        /// <summary>
        /// Parses the body of a multipart MIME mail message.
        /// </summary>
        /// <param name="reader">An instance of the StringReader class initialized
        /// with a string containing the body of the mail message.</param>
        /// <param name="boundary">The boundary value as is present as part of
        /// the Content-Type header field in multipart mail messages.</param>
        /// <returns>An array of initialized MIMEPart instances representing
        /// the various parts of the MIME mail message.</returns>
        private static MIMEPart[] ParseMIMEParts(StringReader reader, string boundary)
        {
            List <MIMEPart> list = new List <MIMEPart>();
            string          start = "--" + boundary, end = "--" + boundary + "--", line;

            // Skip everything up to the first boundary
            while ((line = reader.ReadLine()) != null)
            {
                if (line.StartsWith(start))
                {
                    break;
                }
            }
            // Read MIME parts delimited by boundary strings
            while (line != null && line.StartsWith(start))
            {
                MIMEPart p = new MIMEPart();
                // Read the part header
                StringBuilder header = new StringBuilder();
                while (!String.IsNullOrEmpty(line = reader.ReadLine()))
                {
                    header.AppendLine(line);
                }
                p.header = ParseMailHeader(header.ToString());
                // Account for nested multipart content
                NameValueCollection contentType = ParseMIMEField(p.header["Content-Type"]);
                if (contentType["Boundary"] != null)
                {
                    list.AddRange(ParseMIMEParts(reader, contentType["boundary"]));
                }
                // Read the part body
                StringBuilder body = new StringBuilder();
                while ((line = reader.ReadLine()) != null)
                {
                    if (line.StartsWith(start))
                    {
                        break;
                    }
                    body.AppendLine(line);
                }
                p.body = body.ToString();
                // Add the MIME part to the list unless body is null which means the
                // body contained nested multipart content
                if (!String.IsNullOrEmpty(p.body))
                {
                    list.Add(p);
                }
                // If the boundary is actually the end boundary, we're done
                if (line == null || line.StartsWith(end))
                {
                    break;
                }
            }
            return(list.ToArray());
        }
예제 #4
0
        /// <summary>
        /// Adds the parts of a MIME multi-part message to an instance of the
        /// MailMessage class. MIME parts are either added to the AlternateViews
        /// or to the Attachments collections depending on their type.
        /// </summary>
        /// <param name="m">The MailMessage instance to operate on</param>
        /// <param name="parts">An array of MIME parts</param>
        private void AddMIMEPartsToMessage(MailMessage m, MIMEPart[] parts)
        {
            bool setBodyFields = false;

            for (int i = 0; i < parts.Length; i++)
            {
                MIMEPart            p           = parts[i];
                NameValueCollection contentType = ParseMIMEField(
                    p.header["Content-Type"]);
                string transferEnc = p.header["Content-Transfer-Encoding"] ??
                                     "none";
                Encoding encoding = Util.GetEncoding(contentType["Charset"]);
                byte[]   bytes    = encoding.GetBytes(p.body);
                /* decode content if it was encoded */
                switch (transferEnc.ToLower())
                {
                case "quoted-printable":
                    bytes = encoding.GetBytes(Util.QPDecode(p.body, encoding));
                    break;

                case "base64":
                    bytes = Util.Base64Decode(p.body);
                    break;
                }

                /* Put the first MIME part that contains text into the Body fields of the
                 * MailMessage instance */
                if (setBodyFields == false && contentType["value"].ToLower().Contains("text"))
                {
                    m.Body         = encoding.GetString(bytes);
                    m.BodyEncoding = encoding;
                    m.IsBodyHtml   = contentType["value"].ToLower()
                                     .Contains("text/html");
                    setBodyFields = true;
                    continue;
                }
                NameValueCollection disposition = ParseMIMEField(
                    p.header["Content-Disposition"] ?? "");
                if (disposition["value"].ToLower() == "attachment")
                {
                    m.Attachments.Add(CreateAttachment(p.header, bytes,
                                                       disposition["filename"] ?? ("attachment" + i.ToString())));
                }
                else
                {
                    m.AlternateViews.Add(CreateAlternateView(p.header, 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>
 ///   Parses the body of a multipart MIME mail message.
 /// </summary>
 /// <param name="reader">
 ///   An instance of the StringReader class initialized
 ///   with a string containing the body of the mail message.
 /// </param>
 /// <param name="boundary">
 ///   The boundary value as is present as part of
 ///   the Content-Type header field in multipart mail messages.
 /// </param>
 /// <returns>
 ///   An array of initialized MIMEPart instances representing
 ///   the various parts of the MIME mail message.
 /// </returns>
 private static MIMEPart[] ParseMIMEParts(StringReader reader, string boundary)
 {
   var list = new List<MIMEPart>();
   string start = "--" + boundary, end = "--" + boundary + "--", line;
   // Skip everything up to the first boundary
   while ((line = reader.ReadLine()) != null)
   {
     if (line.StartsWith(start))
       break;
   }
   // Read MIME parts delimited by boundary strings
   while (line != null && line.StartsWith(start))
   {
     var p = new MIMEPart();
     // Read the part header
     var header = new StringBuilder();
     while (!string.IsNullOrEmpty(line = reader.ReadLine()))
       header.AppendLine(line);
     p.header = ParseMailHeader(header.ToString());
     // Account for nested multipart content
     var contentType = ParseMIMEField(p.header["Content-Type"]);
     if (contentType["Boundary"] != null)
       list.AddRange(ParseMIMEParts(reader, contentType["boundary"]));
     // Read the part body
     var body = new StringBuilder();
     while ((line = reader.ReadLine()) != null)
     {
       if (line.StartsWith(start))
         break;
       body.AppendLine(line);
     }
     p.body = body.ToString();
     // Add the MIME part to the list unless body is null which means the
     // body contained nested multipart content
     if (!string.IsNullOrEmpty(p.body))
       list.Add(p);
     // If the boundary is actually the end boundary, we're done
     if (line == null || line.StartsWith(end))
       break;
   }
   return list.ToArray();
 }
예제 #7
0
		/// <summary>
		/// Parses the body of a multipart MIME mail message.
		/// </summary>
		/// <param name="reader">An instance of the StringReader class initialized with a string
		/// containing the body of the mail message.</param>
		/// <param name="boundary">The boundary value as is present as part of the Content-Type header
		/// field in multipart mail messages.</param>
		/// <returns>An array of initialized MIMEPart instances representing the various parts of the
		/// MIME mail message.</returns>
		static MIMEPart[] ParseMIMEParts(StringReader reader, string boundary) {
			List<MIMEPart> list = new List<MIMEPart>();
			string start = "--" + boundary, end = "--" + boundary + "--", line;
			// Skip everything up to the first boundary.
			while ((line = reader.ReadLine()) != null) {
				if (line.StartsWith(start))
					break;
			}
			// Read the MIME parts which are delimited by boundary strings.
			while (line != null && line.StartsWith(start)) {
				MIMEPart p = new MIMEPart();
				// Read the part header.
				StringBuilder header = new StringBuilder();
				while (!String.IsNullOrEmpty(line = reader.ReadLine()))
					header.AppendLine(line);
				p.header = ParseMailHeader(header.ToString());
				// Account for nested multipart content.
				NameValueCollection contentType = ParseMIMEField(p.header["Content-Type"]);
				if (contentType["Boundary"] != null)
					list.AddRange(ParseMIMEParts(reader, contentType["boundary"]));
				// Read the part body.
				StringBuilder body = new StringBuilder();
				while ((line = reader.ReadLine()) != null) {
					if (line.StartsWith(start))
						break;
					body.AppendLine(line);
				}
				p.body = body.ToString();
				// Add the MIME part to the list unless body is null or empty which means the body
				// contained nested multipart content.
				if(p.body != null && p.body.Trim() != String.Empty)
					list.Add(p);
				// If this boundary is the end boundary, we're done.
				if (line == null || line.StartsWith(end))
					break;
			}
			return list.ToArray();
		}
예제 #8
0
		/// <summary>
		/// Adds the parts of a MIME multi-part message to an instance of the
		/// MailMessage class. MIME parts are either added to the AlternateViews
		/// or to the Attachments collections depending on their type.
		/// </summary>
		/// <param name="m">The MailMessage instance to operate on</param>
		/// <param name="parts">An array of MIME parts</param>
		private void AddMIMEPartsToMessage(MailMessage m, MIMEPart[] parts) {
			bool setBodyFields = false;
			for (int i = 0; i < parts.Length; i++) {
				MIMEPart p = parts[i];
				NameValueCollection contentType = ParseMIMEField(
					p.header["Content-Type"]);
				string transferEnc = p.header["Content-Transfer-Encoding"] ??
					"none";
				Encoding encoding = Util.GetEncoding(contentType["Charset"]);
				byte[] bytes = encoding.GetBytes(p.body);
				/* decode content if it was encoded */
				switch (transferEnc.ToLower()) {
					case "quoted-printable":
						bytes = encoding.GetBytes(Util.QPDecode(p.body, encoding));
						break;
					case "base64":
						bytes = Util.Base64Decode(p.body);
						break;
				}
				/* Put the first MIME part that contains text into the Body fields of the
				 * MailMessage instance */
				if (setBodyFields == false && contentType["value"].ToLower().Contains("text")) {
						m.Body = encoding.GetString(bytes);
						m.BodyEncoding = encoding;
						m.IsBodyHtml = contentType["value"].ToLower()
							.Contains("text/html");
						setBodyFields = true;
						continue;
				}
				NameValueCollection disposition = ParseMIMEField(
					p.header["Content-Disposition"] ?? "");
				if (disposition["value"].ToLower() == "attachment") {
					m.Attachments.Add(CreateAttachment(p.header, bytes,
						disposition["filename"] ?? ("attachment" + i.ToString())));
				} else {
					m.AlternateViews.Add(CreateAlternateView(p.header, bytes));
				}
			}
		}
예제 #9
0
		/// <summary>
		/// Creates a new instance of the MailMessage class and initializes it using
		/// the specified header and body information.
		/// </summary>
		/// <param name="header">A collection of mail and MIME headers</param>
		/// <param name="body">The mail body. May be null in case the message
		/// is a MIME multi-part message in which case the MailMessage's body will
		/// be set to the body of the first MIME part.</param>
		/// <param name="parts">An array of MIME parts making up the message. If the
		/// message is not a MIME multi-part message, this can be set to null.
		/// </param>
		/// <returns>An initialized instance of the MailMessage class</returns>
		private MailMessage CreateMailmessage(NameValueCollection header, string body,
			MIMEPart[] parts) {
			MailMessage m = new MailMessage();
			NameValueCollection contentType = ParseMIMEField(
				header["Content-Type"]);
			/* NameValueCollection throws an exception if adding an empty string as
			 * value which can happen, if reading a mail message with an empty subject
			 * for instance
			 */
			foreach (string key in header) {
				string value = header.GetValues(key)[0];
				if (value != String.Empty)
					m.Headers.Add(key, value);
			}
			if (parts != null) {
				/* This takes care of setting the Body, BodyEncoding and IsBodyHtml fields also */
				AddMIMEPartsToMessage(m, parts);
			} else {
				/* charset attribute should be part of content-type */
				m.BodyEncoding = Util.GetEncoding(contentType["charset"]);
				m.Body = body;
				m.IsBodyHtml = contentType["value"].Contains("text/html");
			}
			Match ma = Regex.Match(header["Subject"], @"=\?([A-Za-z0-9\-]+)");
			if (ma.Success) {
				/* encoded-word subject */
				m.SubjectEncoding = Util.GetEncoding(
					ma.Groups[1].Value);
				m.Subject = Util.DecodeWords(header["Subject"]);
			} else {
				m.SubjectEncoding = Encoding.ASCII;
				m.Subject = header["Subject"];
			}
			m.Priority = header["Priority"] != null ?
				PriorityMapping[header["Priority"]] : MailPriority.Normal;			
			SetAddressFields(m, header);
			return m;
		}
예제 #10
0
		/// <summary>
		/// Reads the message body of a MIME multipart message.
		/// </summary>
		/// <param name="boundary">The boundary string which separates
		/// the different parts which make up the multipart-message</param>
		/// <param name="nested">True if recursive call</param>
		/// <returns>A list of the MIME parts composing the multipart
		/// message</returns>
		/// <remarks>Each MIME part consists of its own set of header
		/// fields and a body.</remarks>
		private MIMEPart[] ReadMultipartBody(string boundary, bool nested = false) {
			List<MIMEPart> parts = new List<MIMEPart>();
			string s_boundary = "--" + boundary,
				e_boundary = "--" + boundary + "--";
			/* skip everything up to the first boundary */
			string response = GetResponse();
			while (!response.StartsWith(s_boundary))
				response = GetResponse();
			/* read MIME parts enclosed in boundary strings */
			while (response.StartsWith(s_boundary)) {
				MIMEPart part = new MIMEPart();
				/* read content-header of part */
				part.header = ReadMailHeader();
				/* account for nested multipart content */
				NameValueCollection contentType = ParseMIMEField(
					part.header["Content-Type"]);
				if (contentType["Boundary"] != null)
					parts.AddRange(ReadMultipartBody(contentType["boundary"], true));
				/* read content-body of part */
				while (!(response = GetResponse()).StartsWith(s_boundary))
					part.body = part.body + response + "\r\n";
				/* add MIME part to the list unless body is null which means the body was
						nested multipart content */
				if(part.body != null)
					parts.Add(part);
				/* if the boundary is actually the end boundary, we're done */
				if (response.StartsWith(e_boundary))
					break;
			}
			if (nested == false) {
				/* FETCH closing bracket may be last character of response */
				if (!response.EndsWith(")")) {
					/* next read should return closing bracket from FETCH command then */
					if ((response = GetResponse()) != ")")
						throw new BadServerResponseException(response);
				}
			}
			return parts.ToArray();
		}