Example #1
0
	    /// <summary>
	    /// Constructs a message from a byte array.<br/>
	    /// <br/>
	    /// The headers are always parsed, but if <paramref name="parseBody"/> is <see langword="false"/>, the body is not parsed.
	    /// </summary>
	    /// <param name="rawMessageContent">The byte array which is the message contents to parse</param>
	    /// <param name="parseBody">
	    /// <see langword="true"/> if the body should be parsed,
	    /// <see langword="false"/> if only headers should be parsed out of the <paramref name="rawMessageContent"/> byte array
	    /// </param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message. 
        /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
	    public Message(byte[] rawMessageContent, bool parseBody, IParsingErrorHandler parsingErrorHandler = null)
		{
			RawMessage = rawMessageContent;

			// Find the headers and the body parts of the byte array
			MessageHeader headersTemp;
			byte[] body;
			HeaderExtractor.ExtractHeadersAndBody(rawMessageContent, out headersTemp, out body, parsingErrorHandler);

			// Set the Headers property
			Headers = headersTemp;

			// Should we also parse the body?
			if (parseBody)
			{
				// Parse the body into a MessagePart
				MessagePart = new MessagePart(body, Headers, parsingErrorHandler);
			}
		}
Example #2
0
        /// <summary>
        /// Constructs a message from a byte array.<br/>
        /// <br/>
        /// The headers are always parsed, but if <paramref name="parseBody"/> is <see langword="false"/>, the body is not parsed.
        /// </summary>
        /// <param name="rawMessageContent">The byte array which is the message contents to parse</param>
        /// <param name="parseBody">
        /// <see langword="true"/> if the body should be parsed,
        /// <see langword="false"/> if only headers should be parsed out of the <paramref name="rawMessageContent"/> byte array
        /// </param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message.
        /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
        public Message(byte[] rawMessageContent, bool parseBody, IParsingErrorHandler parsingErrorHandler = null)
        {
            RawMessage = rawMessageContent;

            // Find the headers and the body parts of the byte array
            MessageHeader headersTemp;

            byte[] body;
            HeaderExtractor.ExtractHeadersAndBody(rawMessageContent, out headersTemp, out body, parsingErrorHandler);

            // Set the Headers property
            Headers = headersTemp;

            // Should we also parse the body?
            if (parseBody)
            {
                // Parse the body into a MessagePart
                MessagePart = new MessagePart(body, Headers, parsingErrorHandler);
            }
        }
Example #3
0
        /// <summary>
        /// Used to construct the topmost message part
        /// </summary>
        /// <param name="rawBody">The body that needs to be parsed</param>
        /// <param name="headers">The headers that should be used from the message</param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message.
        /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
        /// <exception cref="ArgumentNullException">If <paramref name="rawBody"/> or <paramref name="headers"/> is <see langword="null"/></exception>
        internal MessagePart(byte[] rawBody, MessageHeader headers, IParsingErrorHandler parsingErrorHandler = null)
        {
            if (rawBody == null)
            {
                throw new ArgumentNullException("rawBody");
            }

            if (headers == null)
            {
                throw new ArgumentNullException("headers");
            }

            _parsingErrorHandler = parsingErrorHandler;

            ContentType             = headers.ContentType;
            ContentDescription      = headers.ContentDescription;
            ContentTransferEncoding = headers.ContentTransferEncoding;
            ContentId          = headers.ContentId;
            ContentDisposition = headers.ContentDisposition;

            FileName = FindFileName(ContentType, ContentDisposition, "(no name)");
            try
            {
                BodyEncoding = ParseBodyEncoding(ContentType.CharSet);
            }
            catch (FormatException ex)
            {
                BodyEncoding = Encoding.UTF8;
                if (_parsingErrorHandler != null)
                {
                    _parsingErrorHandler.HandleParseError(new ParseError(ex, ContentType.CharSet, string.Format("On body encoding. Encoding set to {0}", BodyEncoding.EncodingName)));
                }
                else
                {
                    throw;
                }
            }

            ParseBody(rawBody);
        }
Example #4
0
	    /// <summary>
	    /// Extract the header part and body part of a message.<br/>
	    /// The headers are then parsed to a strongly typed <see cref="MessageHeader"/> object.
	    /// </summary>
	    /// <param name="fullRawMessage">The full message in bytes where header and body needs to be extracted from</param>
	    /// <param name="headers">The extracted header parts of the message</param>
	    /// <param name="body">The body part of the message</param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing an header. 
        /// If it is not null, the handler handles the error on the specific header without stopping the message parsing process</param>
	    /// <exception cref="ArgumentNullException">If <paramref name="fullRawMessage"/> is <see langword="null"/></exception>
	    public static void ExtractHeadersAndBody(byte[] fullRawMessage, out MessageHeader headers, out byte[] body, IParsingErrorHandler parsingErrorHandler = null)
		{
			if(fullRawMessage == null)
				throw new ArgumentNullException("fullRawMessage");

			// Find the end location of the headers
			int endOfHeaderLocation = FindHeaderEndPosition(fullRawMessage);

			// The headers are always in ASCII - therefore we can convert the header part into a string
			// using US-ASCII encoding
			string headersString = Encoding.ASCII.GetString(fullRawMessage, 0, endOfHeaderLocation);

			// Now parse the headers to a NameValueCollection
			NameValueCollection headersUnparsedCollection = ExtractHeaders(headersString);

			// Use the NameValueCollection to parse it into a strongly-typed MessageHeader header
			headers = new MessageHeader(headersUnparsedCollection, parsingErrorHandler);

			// Since we know where the headers end, we also know where the body is
			// Copy the body part into the body parameter
			body = new byte[fullRawMessage.Length - endOfHeaderLocation];
			Array.Copy(fullRawMessage, endOfHeaderLocation, body, 0, body.Length);
		}
Example #5
0
	    /// <summary>
	    /// Used to construct the topmost message part
	    /// </summary>
	    /// <param name="rawBody">The body that needs to be parsed</param>
	    /// <param name="headers">The headers that should be used from the message</param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message. 
        /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
	    /// <exception cref="ArgumentNullException">If <paramref name="rawBody"/> or <paramref name="headers"/> is <see langword="null"/></exception>
	    internal MessagePart(byte[] rawBody, MessageHeader headers, IParsingErrorHandler parsingErrorHandler = null)
		{
		    if(rawBody == null)
				throw new ArgumentNullException("rawBody");
			
			if(headers == null)
				throw new ArgumentNullException("headers");

		    _parsingErrorHandler = parsingErrorHandler;

			ContentType = headers.ContentType;
			ContentDescription = headers.ContentDescription;
			ContentTransferEncoding = headers.ContentTransferEncoding;
			ContentId = headers.ContentId;
			ContentDisposition = headers.ContentDisposition;

			FileName = FindFileName(ContentType, ContentDisposition, "(no name)");
		    try
		    {
		        BodyEncoding = ParseBodyEncoding(ContentType.CharSet);
		    }
		    catch (FormatException ex)
		    {
		        BodyEncoding = Encoding.UTF8;
		        if (_parsingErrorHandler != null)
		        {
                    _parsingErrorHandler.HandleParseError(new ParseError(ex, ContentType.CharSet, string.Format("On body encoding. Encoding set to {0}", BodyEncoding.EncodingName)));
		        }
		        else
		        {
                    throw;
		        }
		    }

			ParseBody(rawBody);
		}
Example #6
0
        /// <summary>
        /// Extract the header part and body part of a message.<br/>
        /// The headers are then parsed to a strongly typed <see cref="MessageHeader"/> object.
        /// </summary>
        /// <param name="fullRawMessage">The full message in bytes where header and body needs to be extracted from</param>
        /// <param name="headers">The extracted header parts of the message</param>
        /// <param name="body">The body part of the message</param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing an header.
        /// If it is not null, the handler handles the error on the specific header without stopping the message parsing process</param>
        /// <exception cref="ArgumentNullException">If <paramref name="fullRawMessage"/> is <see langword="null"/></exception>
        public static void ExtractHeadersAndBody(byte[] fullRawMessage, out MessageHeader headers, out byte[] body, IParsingErrorHandler parsingErrorHandler = null)
        {
            if (fullRawMessage == null)
            {
                throw new ArgumentNullException("fullRawMessage");
            }

            // Find the end location of the headers
            int endOfHeaderLocation = FindHeaderEndPosition(fullRawMessage);

            // The headers are always in ASCII - therefore we can convert the header part into a string
            // using US-ASCII encoding
            string headersString = Encoding.ASCII.GetString(fullRawMessage, 0, endOfHeaderLocation);

            // Now parse the headers to a NameValueCollection
            NameValueCollection headersUnparsedCollection = ExtractHeaders(headersString);

            // Use the NameValueCollection to parse it into a strongly-typed MessageHeader header
            headers = new MessageHeader(headersUnparsedCollection, parsingErrorHandler);

            // Since we know where the headers end, we also know where the body is
            // Copy the body part into the body parameter
            body = new byte[fullRawMessage.Length - endOfHeaderLocation];
            Array.Copy(fullRawMessage, endOfHeaderLocation, body, 0, body.Length);
        }
Example #7
0
 /// <summary>
 /// Convenience constructor for <see cref="Mime.Message(byte[], bool, IParsingErrorHandler)"/>.<br/>
 /// <br/>
 /// Creates a message from a byte array. The full message including its body is parsed.
 /// </summary>
 /// <param name="rawMessageContent">The byte array which is the message contents to parse</param>
 /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message.
 /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
 public Message(byte[] rawMessageContent, IParsingErrorHandler parsingErrorHandler = null)
     : this(rawMessageContent, true, parsingErrorHandler)
 {
 }
Example #8
0
	    /// <summary>
	    /// Parses a <see cref="NameValueCollection"/> to a MessageHeader
	    /// </summary>
	    /// <param name="headers">The collection that should be traversed and parsed</param>
	    /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing an header. 
	    /// If it is not null, the handler handles the error on the specific header without stopping the message parsing process</param>
	    /// <returns>A valid MessageHeader object</returns>
	    /// <exception cref="ArgumentNullException">If <paramref name="headers"/> is <see langword="null"/></exception>
	    internal MessageHeader(NameValueCollection headers, IParsingErrorHandler parsingErrorHandler = null)
		{
		    _parsingErrorHandler = parsingErrorHandler;
		    if (headers == null)
				throw new ArgumentNullException("headers");

			// Create empty lists as defaults. We do not like null values
			// List with an initial capacity set to zero will be replaced
			// when a corrosponding header is found
			To = new List<RfcMailAddress>(0);
			Cc = new List<RfcMailAddress>(0);
			Bcc = new List<RfcMailAddress>(0);
			Received = new List<Received>();
			Keywords = new List<string>();
			InReplyTo = new List<string>(0);
			References = new List<string>(0);
			DispositionNotificationTo = new List<RfcMailAddress>();
			UnknownHeaders = new NameValueCollection();

			// Default importancetype is Normal (assumed if not set)
			Importance = MailPriority.Normal;

			// 7BIT is the default ContentTransferEncoding (assumed if not set)
			ContentTransferEncoding = ContentTransferEncoding.SevenBit;

			// text/plain; charset=us-ascii is the default ContentType
			ContentType = new ContentType("text/plain; charset=us-ascii");

			// Now parse the actual headers
			ParseHeaders(headers);
		}
Example #9
0
	    /// <summary>
	    /// Convenience constructor for <see cref="Mime.Message(byte[], bool, IParsingErrorHandler)"/>.<br/>
	    /// <br/>
	    /// Creates a message from a byte array. The full message including its body is parsed.
	    /// </summary>
	    /// <param name="rawMessageContent">The byte array which is the message contents to parse</param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message. 
        /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
	    public Message(byte[] rawMessageContent, IParsingErrorHandler parsingErrorHandler = null)
			: this(rawMessageContent, true, parsingErrorHandler)
		{
		}
Example #10
0
	    /// <summary>
	    /// Loads a <see cref="Message"/> from a <see cref="Stream"/> containing a raw email.
	    /// </summary>
	    /// <param name="messageStream">The <see cref="Stream"/> from which to load the raw <see cref="Message"/></param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message. 
        /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
	    /// <exception cref="ArgumentNullException">If <paramref name="messageStream"/> is <see langword="null"/></exception>
	    /// <exception>Other exceptions relevant to <see cref="Stream.Read"/> might be thrown as well</exception>
	    /// <returns>A <see cref="Message"/> with the content loaded from the <paramref name="messageStream"/></returns>
	    public static Message Load(Stream messageStream, IParsingErrorHandler parsingErrorHandler = null)
		{
			if (messageStream == null)
				throw new ArgumentNullException("messageStream");

			using (MemoryStream outStream = new MemoryStream())
			{
#if DOTNET4
				// TODO: Enable using native v4 framework methods when support is formally added.
				messageStream.CopyTo(outStream);
#else
				int bytesRead;
				byte[] buffer = new byte[4096];

				while ((bytesRead = messageStream.Read(buffer, 0, 4096)) > 0)
				{
					outStream.Write(buffer, 0, bytesRead);
				}
#endif
				byte[] content = outStream.ToArray();

				return new Message(content, parsingErrorHandler);
			}
		}
Example #11
0
	    /// <summary>
	    /// Loads a <see cref="Message"/> from a file containing a raw email.
	    /// </summary>
	    /// <param name="file">The File location to load the <see cref="Message"/> from. The file must exist.</param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message. 
        /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
	    /// <exception cref="ArgumentNullException">If <paramref name="file"/> is <see langword="null"/></exception>
	    /// <exception cref="FileNotFoundException">If <paramref name="file"/> does not exist</exception>
	    /// <exception>Other exceptions relevant to a <see cref="FileStream"/> might be thrown as well</exception>
	    /// <returns>A <see cref="Message"/> with the content loaded from the <paramref name="file"/></returns>
	    public static Message Load(FileInfo file, IParsingErrorHandler parsingErrorHandler = null)
		{
			if (file == null)
				throw new ArgumentNullException("file");

			if (!file.Exists)
				throw new FileNotFoundException("Cannot load message from non-existent file", file.FullName);

			using (FileStream stream = new FileStream(file.FullName, FileMode.Open))
			{
				return Load(stream, parsingErrorHandler);
			}
		}
Example #12
0
	    /// <summary>
	    /// Fetches a message from the server and parses it
	    /// </summary>
	    /// <param name="messageNumber">
	    /// Message number on server, which may not be marked as deleted.<br/>
	    /// Must be inside the range [1, messageCount]
	    /// </param>
        /// <param name="parsingErrorHandler">(Optional) It is notifified when an error occurs while parsing something in the message. 
        /// If it is not null, the handler handles the error on the specific element without stopping the message parsing process</param>
	    /// <returns>The message, containing the email message</returns>
	    /// <exception cref="PopServerException">If the server did not accept the command sent to fetch the message</exception>
	    public Message GetMessage(int messageNumber, IParsingErrorHandler parsingErrorHandler = null)
		{
			AssertDisposed();

			ValidateMessageNumber(messageNumber);

			if (State != ConnectionState.Transaction)
				throw new InvalidUseException("Cannot fetch a message, when the user has not been authenticated yet");

			byte[] messageContent = GetMessageAsBytes(messageNumber);

            return new Message(messageContent, parsingErrorHandler);
		}