public static void ConstructParts(StructureBuilder builder, MIME_Entity entity, bool includeExtensions) { var wordEncoder = new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.B, Encoding.UTF8); wordEncoder.Split = false; if (entity.Body is MIME_b_Multipart) { // Recursive build for multipart builder.StartBracket(); foreach (MIME_Entity child in ((MIME_b_Multipart)entity.Body).BodyParts) { ConstructParts(builder, child, includeExtensions); } if (entity.ContentType != null && entity.ContentType.SubType != null) { builder.SpaceNQuoted(entity.ContentType.SubType.ToUpperInvariant()); } else { builder.AppendQuoted("PLAIN"); } if (includeExtensions) { // conentTypeParameters - Syntax: {("name" SP "value" *(SP "name" SP "value"))} ConstructTypeParameters(builder, entity, wordEncoder); // body disposition Syntax: {(disposition-type [ SP ("name" SP "value" *(SP "name" SP "value"))])} ConstructBodyDisposition(builder, entity, wordEncoder); // body language builder.AppendNil(); // body location builder.AppendNil(); } builder.Append(")"); } else { ConstructSinglePart(builder, entity, wordEncoder, includeExtensions); } }
/// <summary> /// Parses header field from the specified value. /// </summary> /// <param name="value">Header field value. Header field name must be included. For example: 'Sender: [email protected]'.</param> /// <returns>Returns parsed header field.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception> /// <exception cref="ParseException">Is raised when header field parsing errors.</exception> public static Mail_h_Mailbox Parse(string value) { if (value == null) { throw new ArgumentNullException("value"); } string[] name_value = value.Split(new[] { ':' }, 2); if (name_value.Length != 2) { throw new ParseException("Invalid header field value '" + value + "'."); } MIME_Reader r = new MIME_Reader(name_value[1]); string word = r.QuotedReadToDelimiter(new[] { ',', '<', ':' }); // Invalid value. if (word == null) { throw new ParseException("Invalid header field value '" + value + "'."); } // name-addr else if (r.Peek(true) == '<') { Mail_h_Mailbox h = new Mail_h_Mailbox(name_value[0], new Mail_t_Mailbox( word != null ? MIME_Encoding_EncodedWord.DecodeS( TextUtils.UnQuoteString(word)) : null, r.ReadParenthesized())); h.m_ParseValue = value; return(h); } // addr-spec else { Mail_h_Mailbox h = new Mail_h_Mailbox(name_value[0], new Mail_t_Mailbox(null, word)); h.m_ParseValue = value; return(h); } }
/// <summary> /// Returns address as string value. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <returns>Returns address as string value.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder) { if (string.IsNullOrEmpty(m_DisplayName)) { return("<" + m_Address + ">"); } else { if (wordEncoder != null && MIME_Encoding_EncodedWord.MustEncode(m_DisplayName)) { return(wordEncoder.Encode(m_DisplayName) + " " + "<" + m_Address + ">"); } else { return(TextUtils.QuoteString(m_DisplayName) + " " + "<" + m_Address + ">"); } } }
/// <summary> /// Constructs ENVELOPE address structure. /// </summary> /// <param name="address">Mailbox address.</param> /// <param name="wordEncoder">Unicode words encoder.</param> /// <returns></returns> private static string ConstructAddress(Mail_t_Mailbox address, MIME_Encoding_EncodedWord wordEncoder) { /* 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. */ // NOTE: all header fields and parameters must in ENCODED form !!! StringBuilder retVal = new StringBuilder(); retVal.Append("("); // personal name if (address.DisplayName != null) { retVal.Append(TextUtils.QuoteString(wordEncoder.Encode(RemoveCrlf(address.DisplayName)))); } else { retVal.Append("NIL"); } // source route, always NIL (not used nowdays) retVal.Append(" NIL"); // mailbox name retVal.Append(" " + TextUtils.QuoteString(wordEncoder.Encode(RemoveCrlf(address.LocalPart)))); // host name if (address.Domain != null) { retVal.Append(" " + TextUtils.QuoteString(wordEncoder.Encode(RemoveCrlf(address.Domain)))); } else { retVal.Append(" NIL"); } retVal.Append(")"); return(retVal.ToString()); }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset) { if (IsModified) { StringBuilder retVal = new StringBuilder(); retVal.Append("Received: "); retVal.Append("FROM " + m_From); if (m_pFrom_TcpInfo != null) { retVal.Append(" (" + m_pFrom_TcpInfo + ")"); } retVal.Append(" BY " + m_By); if (m_pBy_TcpInfo != null) { retVal.Append(" (" + m_pBy_TcpInfo + ")"); } if (!string.IsNullOrEmpty(m_Via)) { retVal.Append(" VIA " + m_Via); } if (!string.IsNullOrEmpty(m_With)) { retVal.Append(" WITH " + m_With); } if (!string.IsNullOrEmpty(m_ID)) { retVal.Append(" ID " + m_ID); } if (!string.IsNullOrEmpty(m_For)) { retVal.Append(" FOR " + m_For); } retVal.Append("; " + MIME_Utils.DateTimeToRfc2822(m_Time)); retVal.Append("\r\n"); return(retVal.ToString()); } else { return(m_ParseValue); } }
/// <summary> /// Parses mailbox from mailbox address string. /// </summary> /// <param name="mailbox">Mailbox string. Format: ["diplay-name"<SP>]<local-part@domain>.</param> /// <returns></returns> public static MailboxAddress Parse(string mailbox) { mailbox = mailbox.Trim(); /* We must parse following situations: * "Ivar Lumi" <*****@*****.**> * "Ivar Lumi" [email protected] * <*****@*****.**> * [email protected] * Ivar Lumi <*****@*****.**> */ string name = ""; string emailAddress = mailbox; // Email address is between <> and remaining left part is display name if (mailbox.IndexOf("<") > -1 && mailbox.IndexOf(">") > -1) { name = MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(mailbox.Substring(0, mailbox.LastIndexOf("<")))); emailAddress = mailbox.Substring(mailbox.LastIndexOf("<") + 1, mailbox.Length - mailbox.LastIndexOf("<") - 2).Trim(); } else { // There is name included, parse it if (mailbox.StartsWith("\"")) { int startIndex = mailbox.IndexOf("\""); if (startIndex > -1 && mailbox.LastIndexOf("\"") > startIndex) { name = MIME_Encoding_EncodedWord.DecodeS(mailbox.Substring(startIndex + 1, mailbox.LastIndexOf("\"") - startIndex - 1).Trim()); } emailAddress = mailbox.Substring(mailbox.LastIndexOf("\"") + 1).Trim(); } // Right part must be email address emailAddress = emailAddress.Replace("<", "").Replace(">", "").Trim(); } return(new MailboxAddress(name, emailAddress)); }
public static string EncodeField(string input, bool IsAddress = false) { if (ShouldEncode(input)) { var wordEncoder = new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8); if (IsAddress) { int index = input.IndexOf("<"); int endindex = input.LastIndexOf(">"); if (index > 0 && endindex > index) { var word = input.Substring(0, index); var encoded = wordEncoder.Encode(word); return(encoded + input.Substring(index)); } } return(wordEncoder.Encode(input)); } return(input); }
/// <summary> /// Returns address as string value. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <returns>Returns address as string value.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder) { if (string.IsNullOrEmpty(m_DisplayName)) { return(m_Address); } else { if (wordEncoder != null && MIME_Encoding_EncodedWord.MustEncode(m_DisplayName)) { return(wordEncoder.Encode(m_DisplayName) + " " + "<" + m_Address + ">"); } else if (System.Text.RegularExpressions.Regex.IsMatch(m_DisplayName, @"[""(),:;<>@\[\\\]]")) { return(TextUtils.QuoteString(m_DisplayName) + " " + "<" + m_Address + ">"); } else { return(m_DisplayName + " " + "<" + m_Address + ">"); } } }
/// <summary> /// Parses <b>mailbox-list</b> from specified string value. /// </summary> /// <param name="value">The <b>mailbox-list</b> string value.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception> /// <exception cref="ParseException">Is raised when <b>value</b> is not valid <b>mailbox-list</b> value.</exception> public static Mail_t_MailboxList Parse(string value) { if (value == null) { throw new ArgumentNullException("value"); } MIME_Reader r = new MIME_Reader(value); Mail_t_MailboxList retVal = new Mail_t_MailboxList(); while (true) { string word = r.QuotedReadToDelimiter(new char[] { ',', '<' }); // We processed all data. if (string.IsNullOrEmpty(word) && r.Available == 0) { break; } // name-addr else if (r.Peek(true) == '<') { retVal.Add(new Mail_t_Mailbox(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word.Trim())) : null, r.ReadParenthesized())); } // addr-spec else { retVal.Add(new Mail_t_Mailbox(null, word)); } // We have more addresses. if (r.Peek(true) == ',') { r.Char(false); } } return(retVal); }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <param name="reEncode">If true always specified encoding is used. If false and header field value not modified, original encoding is kept.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset, bool reEncode) { if (reEncode || this.IsModified) { StringBuilder retVal = new StringBuilder(); retVal.Append(this.Name + ": "); for (int i = 0; i < m_pAddresses.Count; i++) { if (i > 0) { retVal.Append("\t"); } // Don't add ',' for last item. if (i == (m_pAddresses.Count - 1)) { retVal.Append(m_pAddresses[i].ToString(wordEncoder) + "\r\n"); } else { retVal.Append(m_pAddresses[i].ToString(wordEncoder) + ",\r\n"); } } // No items, we need to add ending CRLF. if (m_pAddresses.Count == 0) { retVal.Append("\r\n"); } return(retVal.ToString()); } else { return(m_ParseValue); } }
/// <summary> /// Parses IMAP FETCH BODYSTRUCTURE single part entity from reader. /// </summary> /// <param name="r">Fetch reader.</param> /// <returns>Returns parsed bodystructure entity.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>r</b> is null reference.</exception> public static IMAP_t_Fetch_r_i_BodyStructure_e_SinglePart Parse(StringReader r) { if (r == null) { throw new ArgumentNullException("r"); } IMAP_t_Fetch_r_i_BodyStructure_e_SinglePart retVal = new IMAP_t_Fetch_r_i_BodyStructure_e_SinglePart(); /* RFC 3501 7.4.2. * * Normal single part entity fields. * body type * body subtype * body parameter parenthesized list * body id * body description * body encoding * body size - Encoded bytes count. * --- extention fields * * Message/xxx type entity fields. * body type * body subtype * body parameter parenthesized list * body id * body description * body encoding * body size - Encoded bytes count. * --- message special fields * envelope structure * body structure * body encoded text lines count * --- extention fields * * Text/xxx type entity fields. * body type * body subtype * body parameter parenthesized list * body id * body description * body encoding * body size - Encoded bytes count. * --- text special fields * body encoded text lines count * --- extention fields * * Extention fields. * body MD5 * body disposition * body language * body location */ // body type // body subtype // body parameter parenthesized list string type = IMAP_Utils.ReadString(r); string subtype = IMAP_Utils.ReadString(r); if (!string.IsNullOrEmpty(type) && !string.IsNullOrEmpty(subtype)) { retVal.m_pContentType = new MIME_h_ContentType(type + "/" + subtype); } r.ReadToFirstChar(); // Parse Content-Type parameters if (r.StartsWith("(")) { StringReader pramsReader = new StringReader(r.ReadParenthesized()); if (retVal.m_pContentType != null) { while (pramsReader.Available > 0) { string name = IMAP_Utils.ReadString(pramsReader); if (string.IsNullOrEmpty(name)) { break; } string value = IMAP_Utils.ReadString(pramsReader); if (value == null) { value = ""; } retVal.m_pContentType.Parameters[name] = MIME_Encoding_EncodedWord.DecodeTextS(value); } } } // NIL else { IMAP_Utils.ReadString(r); } // body id - nstring retVal.m_ContentID = IMAP_Utils.ReadString(r); // body description - nstring retVal.m_ContentDescription = IMAP_Utils.ReadString(r); // body encoding - string retVal.m_ContentTransferEncoding = IMAP_Utils.ReadString(r); // body size - Encoded bytes count. string size = IMAP_Utils.ReadString(r); if (string.IsNullOrEmpty(size)) { retVal.m_ContentSize = -1; } else { retVal.m_ContentSize = Convert.ToInt64(size); } if (string.Equals("text", type, StringComparison.InvariantCultureIgnoreCase)) { // body encoded text lines count string linesCount = IMAP_Utils.ReadString(r); if (string.IsNullOrEmpty(size)) { retVal.m_LinesCount = -1; } else { retVal.m_LinesCount = Convert.ToInt32(linesCount); } } if (string.Equals("message", type, StringComparison.InvariantCultureIgnoreCase)) { // envelope structure r.ReadToFirstChar(); // Read ENVELOPE if (r.StartsWith("(")) { string prams = r.ReadParenthesized(); } // NIL else { IMAP_Utils.ReadString(r); } // body structure r.ReadToFirstChar(); // Read BODYSTRUCTURE if (r.StartsWith("(")) { string prams = r.ReadParenthesized(); } // NIL else { IMAP_Utils.ReadString(r); } // body encoded text lines count string linesCount = IMAP_Utils.ReadString(r); if (string.IsNullOrEmpty(size)) { retVal.m_LinesCount = -1; } else { retVal.m_LinesCount = Convert.ToInt32(linesCount); } } // body MD5 - nstring retVal.m_Md5 = IMAP_Utils.ReadString(r); // body disposition - "(" string SP body-fld-param ")" / nil // body-fld-param = "(" string SP string *(SP string SP string) ")" / nil if (r.StartsWith("(")) { string disposition = IMAP_Utils.ReadString(r); if (!string.IsNullOrEmpty(disposition)) { retVal.m_pContentDisposition = new MIME_h_ContentDisposition(disposition); } r.ReadToFirstChar(); // Parse Content-Dispostion parameters. if (r.StartsWith("(")) { StringReader pramsReader = new StringReader(r.ReadParenthesized()); if (retVal.m_pContentDisposition != null) { while (pramsReader.Available > 0) { string name = IMAP_Utils.ReadString(pramsReader); if (string.IsNullOrEmpty(name)) { break; } string value = IMAP_Utils.ReadString(pramsReader); if (value == null) { value = ""; } retVal.m_pContentDisposition.Parameters[name] = MIME_Encoding_EncodedWord.DecodeTextS(value); } } } // NIL else { IMAP_Utils.ReadString(r); } } // NIL else { IMAP_Utils.ReadString(r); } // body language - nstring / "(" string *(SP string) ")" r.ReadToFirstChar(); if (r.StartsWith("(")) { retVal.m_Language = r.ReadParenthesized(); } else { retVal.m_Language = IMAP_Utils.ReadString(r); } // body location - nstring retVal.m_Location = IMAP_Utils.ReadString(r); return(retVal); }
/// <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(MIME_Entity 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] * */ MIME_Encoding_EncodedWord wordEncoder = new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.B, Encoding.UTF8); wordEncoder.Split = false; StringBuilder retVal = new StringBuilder(); // Multipart message if (entity.Body is MIME_b_Multipart) { retVal.Append("("); // Construct child entities. foreach (MIME_Entity childEntity in ((MIME_b_Multipart)entity.Body).BodyParts) { // Construct child entity. This can be multipart or non multipart. retVal.Append(ConstructParts(childEntity, bodystructure)); } // Add contentTypeSubMediaType if (entity.ContentType != null && entity.ContentType.SubType != null) { retVal.Append(" \"" + entity.ContentType.SubType + "\""); } 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.ContentType != null && entity.ContentType.Type != null) { retVal.Append("\"" + entity.ContentType.Type + "\""); } else { retVal.Append("NIL"); } // Add contentTypeSubMediaType if (entity.ContentType != null && entity.ContentType.SubType != null) { retVal.Append(" \"" + entity.ContentType.SubType + "\""); } else { retVal.Append(" NIL"); } // conentTypeParameters - Syntax: {("name" SP "value" *(SP "name" SP "value"))} if (entity.ContentType != null) { if (entity.ContentType.Parameters.Count > 0) { retVal.Append(" ("); bool first = true; foreach (MIME_h_Parameter parameter in entity.ContentType.Parameters) { // For the first item, don't add SP. if (first) { first = false; } else { retVal.Append(" "); } retVal.Append("\"" + parameter.Name + "\" \"" + wordEncoder.Encode(parameter.Value) + "\""); } retVal.Append(")"); } else { retVal.Append(" NIL"); } } else { retVal.Append(" NIL"); } // contentID string contentID = entity.ContentID; if (contentID != null) { retVal.Append(" \"" + wordEncoder.Encode(contentID) + "\""); } else { retVal.Append(" NIL"); } // contentDescription string contentDescription = entity.ContentDescription; if (contentDescription != null) { retVal.Append(" \"" + wordEncoder.Encode(contentDescription) + "\""); } else { retVal.Append(" NIL"); } // contentEncoding if (entity.ContentTransferEncoding != null) { retVal.Append(" \"" + wordEncoder.Encode(entity.ContentTransferEncoding) + "\""); } else { // If not specified, then must be 7bit. retVal.Append(" \"7bit\""); } // contentSize if (entity.Body is MIME_b_SinglepartBase) { retVal.Append(" " + ((MIME_b_SinglepartBase)entity.Body).EncodedData.Length.ToString()); } else { retVal.Append(" 0"); } // envelope ---> FOR ContentType: message/rfc822 ONLY ### if (entity.Body is MIME_b_MessageRfc822) { retVal.Append(" " + IMAP_Envelope.ConstructEnvelope(((MIME_b_MessageRfc822)entity.Body).Message)); // TODO: BODYSTRUCTURE,LINES } // contentLines ---> FOR ContentType: text/xxx ONLY ### if (entity.Body is MIME_b_Text) { long lineCount = 0; StreamLineReader r = new StreamLineReader(new MemoryStream(((MIME_b_SinglepartBase)entity.Body).EncodedData)); byte[] line = r.ReadLine(); while (line != null) { lineCount++; line = r.ReadLine(); } retVal.Append(" " + lineCount.ToString()); } retVal.Append(")"); } return(retVal.ToString()); }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset) { return "TODO:"; }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset) { if (m_ParseValue != null) { return m_ParseValue; } else { return m_Name + ": " + m_pAddress.ToString(wordEncoder) + "\r\n"; } }
/// <summary> /// Returns address as string value. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <returns>Returns address as string value.</returns> public abstract string ToString(MIME_Encoding_EncodedWord wordEncoder);
/// <summary> /// Construct secified mime entity ENVELOPE string. /// </summary> /// <param name="entity">Mail message.</param> /// <returns></returns> public static string ConstructEnvelope(Mail_Message 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 !!! MIME_Encoding_EncodedWord wordEncoder = new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.B, Encoding.UTF8); wordEncoder.Split = false; StringBuilder retVal = new StringBuilder(); retVal.Append("ENVELOPE ("); // date try{ if (entity.Date != DateTime.MinValue) { retVal.Append(TextUtils.QuoteString(MIME_Utils.DateTimeToRfc2822(entity.Date))); } else { retVal.Append("NIL"); } } catch { retVal.Append("NIL"); } // subject if (entity.Subject != null) { //retVal.Append(" " + TextUtils.QuoteString(wordEncoder.Encode(entity.Subject))); string val = wordEncoder.Encode(entity.Subject); retVal.Append(" {" + val.Length + "}\r\n" + val); } else { retVal.Append(" NIL"); } // from if (entity.From != null && entity.From.Count > 0) { retVal.Append(" " + ConstructAddresses(entity.From.ToArray(), wordEncoder)); } 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, wordEncoder)); retVal.Append(")"); } else { retVal.Append(" NIL"); } // reply-to if (entity.ReplyTo != null) { retVal.Append(" " + ConstructAddresses(entity.ReplyTo.Mailboxes, wordEncoder)); } else { retVal.Append(" NIL"); } // to if (entity.To != null && entity.To.Count > 0) { retVal.Append(" " + ConstructAddresses(entity.To.Mailboxes, wordEncoder)); } else { retVal.Append(" NIL"); } // cc if (entity.Cc != null && entity.Cc.Count > 0) { retVal.Append(" " + ConstructAddresses(entity.Cc.Mailboxes, wordEncoder)); } else { retVal.Append(" NIL"); } // bcc if (entity.Bcc != null && entity.Bcc.Count > 0) { retVal.Append(" " + ConstructAddresses(entity.Bcc.Mailboxes, wordEncoder)); } else { retVal.Append(" NIL"); } // in-reply-to if (entity.InReplyTo != null) { retVal.Append(" " + TextUtils.QuoteString(wordEncoder.Encode(entity.InReplyTo))); } else { retVal.Append(" NIL"); } // message-id if (entity.MessageID != null) { retVal.Append(" " + TextUtils.QuoteString(wordEncoder.Encode(entity.MessageID))); } else { retVal.Append(" NIL"); } retVal.Append(")"); return(retVal.ToString()); }
/// <summary> /// Parses ENVELOPE from IMAP envelope string. /// </summary> /// <param name="envelopeString">Envelope string.</param> public void Parse(string envelopeString) { if (envelopeString.StartsWith("(")) { envelopeString = envelopeString.Substring(1); } if (envelopeString.EndsWith(")")) { envelopeString = envelopeString.Substring(0, envelopeString.Length - 1); } string word = ""; StringReader r = new StringReader(envelopeString); #region Date // Date word = r.ReadWord(); if (word == null) { throw new Exception("Invalid IMAP ENVELOPE structure !"); } if (word.ToUpper() == "NIL") { m_Date = DateTime.MinValue; } else { try { m_Date = MimeUtils.ParseDate(word); } catch { // Failed to parse date, return minimum. m_Date = DateTime.MinValue; } } #endregion #region Subject // Subject word = r.ReadWord(); if (word == null) { throw new Exception("Invalid IMAP ENVELOPE structure !"); } if (word.ToUpper() == "NIL") { m_Subject = null; } else { m_Subject = MIME_Encoding_EncodedWord.DecodeS(word); } #endregion #region From // From m_From = ParseAddresses(r); #endregion #region Sender // Sender // NOTE: There is confusing part, according rfc 2822 Sender: is MailboxAddress and not AddressList. MailboxAddress[] sender = ParseAddresses(r); if (sender != null && sender.Length > 0) { m_Sender = sender[0]; } else { m_Sender = null; } #endregion #region ReplyTo // ReplyTo m_ReplyTo = ParseAddresses(r); #endregion #region To // To m_To = ParseAddresses(r); #endregion #region Cc // Cc m_Cc = ParseAddresses(r); #endregion #region Bcc // Bcc m_Bcc = ParseAddresses(r); #endregion #region InReplyTo // InReplyTo r.ReadToFirstChar(); word = r.ReadWord(); if (word == null) { throw new Exception("Invalid IMAP ENVELOPE structure !"); } if (word.ToUpper() == "NIL") { m_InReplyTo = null; } else { m_InReplyTo = word; } #endregion #region MessageID // MessageID r.ReadToFirstChar(); word = r.ReadWord(); if (word == null) { throw new Exception("Invalid IMAP ENVELOPE structure !"); } if (word.ToUpper() == "NIL") { m_MessageID = null; } else { m_MessageID = word; } #endregion }
public static Mail_t_AddressList ParseAddressList(string value) { MIME_Reader r = new MIME_Reader(value); /* RFC 5322 3.4. * address = mailbox / group * * mailbox = name-addr / addr-spec * * name-addr = [display-name] angle-addr * * angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr * * group = display-name ":" [group-list] ";" [CFWS] * * display-name = phrase * * mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list * * address-list = (address *("," address)) / obs-addr-list * * group-list = mailbox-list / CFWS / obs-group-list */ Mail_t_AddressList retVal = new Mail_t_AddressList(); while (true) { string word = r.QuotedReadToDelimiter(new[] { ',', '<', ':' }); // We processed all data. if (word == null && r.Available == 0) { if (retVal.Count == 0) { if (CheckEmail(value)) { retVal.Add(new Mail_t_Mailbox(null, value)); } } break; } // skip old group address format else if (r.Peek(true) == ':') { // Consume ':' r.Char(true); } // name-addr else if (r.Peek(true) == '<') { string address = r.ReadParenthesized(); if (CheckEmail(address)) { retVal.Add( new Mail_t_Mailbox( word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word)) : null, address)); } } // addr-spec else { if (CheckEmail(word)) { retVal.Add(new Mail_t_Mailbox(null, word)); } } // We have more addresses. if (r.Peek(true) == ',') { r.Char(false); } } return(retVal); }
internal void Parse(string text) { StringReader stringReader = new StringReader(text); stringReader.ReadToFirstChar(); if (stringReader.StartsWith("(")) { while (stringReader.StartsWith("(")) { IMAP_BODY_Entity iMAP_BODY_Entity = new IMAP_BODY_Entity(); iMAP_BODY_Entity.Parse(stringReader.ReadParenthesized()); iMAP_BODY_Entity.m_pParentEntity = this; this.m_pChildEntities.Add(iMAP_BODY_Entity); stringReader.ReadToFirstChar(); } string str = stringReader.ReadWord(); this.m_pContentType = new MIME_h_ContentType("multipart/" + str); return; } string text2 = stringReader.ReadWord(); string text3 = stringReader.ReadWord(); if (text2.ToUpper() != "NIL" && text3.ToUpper() != "NIL") { this.m_pContentType = new MIME_h_ContentType(text2 + "/" + text3); } stringReader.ReadToFirstChar(); if (stringReader.StartsWith("(")) { string source = stringReader.ReadParenthesized(); StringReader stringReader2 = new StringReader(source); while (stringReader2.Available > 0L) { string name = stringReader2.ReadWord(); string value = MIME_Encoding_EncodedWord.DecodeS(stringReader2.ReadWord()); this.m_pContentType.Parameters[name] = value; } } else { stringReader.ReadWord(); } string text4 = stringReader.ReadWord(); if (text4.ToUpper() != "NIL") { this.m_ContentID = text4; } string text5 = stringReader.ReadWord(); if (text5.ToUpper() != "NIL") { this.m_ContentDescription = text5; } string text6 = stringReader.ReadWord(); if (text6.ToUpper() != "NIL") { this.m_ContentEncoding = text6; } string text7 = stringReader.ReadWord(); if (text7.ToUpper() != "NIL") { this.m_ContentSize = Convert.ToInt32(text7); } if (string.Equals(this.ContentType.TypeWithSubype, MIME_MediaTypes.Message.rfc822, StringComparison.InvariantCultureIgnoreCase)) { stringReader.ReadToFirstChar(); if (stringReader.StartsWith("(")) { stringReader.ReadParenthesized(); } else { stringReader.ReadWord(); } } if (text2.ToLower() == "text") { string text8 = stringReader.ReadWord(); if (text8.ToUpper() != "NIL") { this.m_ContentLines = Convert.ToInt32(text8); } } }
public static void ConstructEnvelope(StructureBuilder builder, Mail_Message entity) { // date, subject, from, sender, reply-to, to, cc, bcc, in-reply-to, and message-id var wordEncoder = new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.B, Encoding.UTF8); wordEncoder.Split = false; builder.Append("ENVELOPE").SpaceNBracket(); // date try { if (entity.Date != DateTime.MinValue) { builder.Append(TextUtils.QuoteString(MIME_Utils.DateTimeToRfc2822(entity.Date))); } else { builder.Append("NIL"); } } catch { builder.Append("NIL"); } // subject if (entity.Subject != null) { builder.Append(" " + TextUtils.QuoteString(wordEncoder.Encode(entity.Subject))); //string val = wordEncoder.Encode(entity.Subject); //builder.Append(" {").Append(val.Length).Append("}\r\n").Append(val); } else { builder.AppendNil(); } // from if (entity.From != null && entity.From.Count > 0) { builder.Append(" "); ConstructAddresses(builder, entity.From.ToArray(), wordEncoder); } else { builder.AppendNil(); } // sender // NOTE: There is confusing part, according rfc 2822 Sender: is MailboxAddress and not AddressList. if (entity.Sender != null) { builder.SpaceNBracket(); ConstructAddress(builder, entity.Sender, wordEncoder); builder.EndBracket(); } else { builder.AppendNil(); } // reply-to if (entity.ReplyTo != null) { builder.Append(" "); ConstructAddresses(builder, entity.ReplyTo.Mailboxes, wordEncoder); } else { builder.Append(" NIL"); } // to if (entity.To != null && entity.To.Count > 0) { builder.Append(" "); ConstructAddresses(builder, entity.To.Mailboxes, wordEncoder); } else { builder.Append(" NIL"); } // cc if (entity.Cc != null && entity.Cc.Count > 0) { builder.Append(" "); ConstructAddresses(builder, entity.Cc.Mailboxes, wordEncoder); } else { builder.AppendNil(); } // bcc if (entity.Bcc != null && entity.Bcc.Count > 0) { builder.Append(" "); ConstructAddresses(builder, entity.Bcc.Mailboxes, wordEncoder); } else { builder.AppendNil(); } // in-reply-to if (entity.InReplyTo != null) { builder.Append(" ").Append(TextUtils.QuoteString(wordEncoder.Encode(entity.InReplyTo))); } else { builder.AppendNil(); } // message-id if (entity.MessageID != null) { builder.Append(" ").Append(TextUtils.QuoteString(wordEncoder.Encode(entity.MessageID))); } else { builder.AppendNil(); } builder.EndBracket(); }
public static void ConstructAddress(StructureBuilder builder, Mail_t_Mailbox address, MIME_Encoding_EncodedWord wordEncoder) { /* 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. */ // NOTE: all header fields and parameters must in ENCODED form !!! builder.StartBracket(); // personal name if (address.DisplayName != null) { builder.Append(TextUtils.QuoteString(wordEncoder.Encode(RemoveCrlf(address.DisplayName)))); } else { builder.Append("NIL"); } // source route, always NIL (not used nowdays) builder.AppendNil(); // mailbox name builder.Append(" ").Append(TextUtils.QuoteString(wordEncoder.Encode(RemoveCrlf(address.LocalPart)))); // host name if (address.Domain != null) { builder.Append(" ").Append(TextUtils.QuoteString(wordEncoder.Encode(RemoveCrlf(address.Domain)))); } else { builder.AppendNil(); } builder.EndBracket(); }
public static void ConstructAddresses(StructureBuilder builder, Mail_t_Mailbox[] mailboxes, MIME_Encoding_EncodedWord wordEncoder) { builder.StartBracket(); foreach (Mail_t_Mailbox address in mailboxes) { ConstructAddress(builder, address, wordEncoder); } builder.EndBracket(); }
/// <summary> /// Returns address as string value. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <returns>Returns address as string value.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder) { StringBuilder retVal = new StringBuilder(); if (string.IsNullOrEmpty(m_DisplayName)) { retVal.Append(":"); } else { if (MIME_Encoding_EncodedWord.MustEncode(m_DisplayName)) { retVal.Append(wordEncoder.Encode(m_DisplayName) + ":"); } else { retVal.Append(TextUtils.QuoteString(m_DisplayName) + ":"); } } for (int i = 0; i < m_pList.Count; i++) { retVal.Append(m_pList[i].ToString(wordEncoder)); if (i < (m_pList.Count - 1)) { retVal.Append(","); } } retVal.Append(";"); return retVal.ToString(); }
/// <summary> /// Parses IMAP FETCH BODYSTRUCTURE multipart entity from reader. /// </summary> /// <param name="r">Fetch reader.</param> /// <returns>Returns parsed bodystructure entity.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>r</b> is null reference.</exception> public static IMAP_t_Fetch_r_i_BodyStructure_e_Multipart Parse(StringReader r) { if (r == null) { throw new ArgumentNullException("r"); } IMAP_t_Fetch_r_i_BodyStructure_e_Multipart retVal = new IMAP_t_Fetch_r_i_BodyStructure_e_Multipart(); /* RFC 3501 7.4.2. * * Normal fields. * 1*(body-parts) - parenthesized list of body parts * subtype * --- extention fields * * Extention fields. * body parameter parenthesized list * body disposition * body language * body location */ #region Normal fields // Read child entities. while (r.Available > 0) { r.ReadToFirstChar(); if (r.StartsWith("(")) { StringReader bodyPartReader = new StringReader(r.ReadParenthesized()); bodyPartReader.ReadToFirstChar(); IMAP_t_Fetch_r_i_BodyStructure_e part = null; // multipart if (bodyPartReader.StartsWith("(")) { part = IMAP_t_Fetch_r_i_BodyStructure_e_Multipart.Parse(bodyPartReader); } // single-part else { part = IMAP_t_Fetch_r_i_BodyStructure_e_SinglePart.Parse(bodyPartReader); } part.SetParent(retVal); retVal.m_pBodyParts.Add(part); } else { break; } } // subtype string subtype = IMAP_Utils.ReadString(r); if (!string.IsNullOrEmpty(subtype)) { retVal.m_pContentType = new MIME_h_ContentType("multipart/" + subtype); } #endregion #region Extention field // body parameter parenthesized list r.ReadToFirstChar(); if (r.StartsWith("(")) { StringReader pramsReader = new StringReader(r.ReadParenthesized()); if (retVal.m_pContentType != null) { while (pramsReader.Available > 0) { string name = IMAP_Utils.ReadString(pramsReader); if (string.IsNullOrEmpty(name)) { break; } string value = IMAP_Utils.ReadString(pramsReader); if (value == null) { value = ""; } retVal.m_pContentType.Parameters[name] = MIME_Encoding_EncodedWord.DecodeTextS(value); } } } // NIL else { IMAP_Utils.ReadString(r); } // body disposition - "(" string SP body-fld-param ")" / nil // body-fld-param = "(" string SP string *(SP string SP string) ")" / nil if (r.StartsWith("(")) { string disposition = IMAP_Utils.ReadString(r); if (!string.IsNullOrEmpty(disposition)) { retVal.m_pContentDisposition = new MIME_h_ContentDisposition(disposition); } r.ReadToFirstChar(); // Parse Content-Dispostion parameters. if (r.StartsWith("(")) { StringReader pramsReader = new StringReader(r.ReadParenthesized()); if (retVal.m_pContentDisposition != null) { while (pramsReader.Available > 0) { string name = IMAP_Utils.ReadString(pramsReader); if (string.IsNullOrEmpty(name)) { break; } string value = IMAP_Utils.ReadString(pramsReader); if (value == null) { value = ""; } retVal.m_pContentDisposition.Parameters[name] = MIME_Encoding_EncodedWord.DecodeTextS(value); } } } // NIL else { IMAP_Utils.ReadString(r); } } // NIL else { IMAP_Utils.ReadString(r); } // body language - nstring / "(" string *(SP string) ")" r.ReadToFirstChar(); if (r.StartsWith("(")) { retVal.m_Language = r.ReadParenthesized(); } else { retVal.m_Language = IMAP_Utils.ReadString(r); } // body location - nstring retVal.m_Location = IMAP_Utils.ReadString(r); #endregion return(retVal); }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <param name="reEncode">If true always specified encoding is used. If false and header field value not modified, original encoding is kept.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset, bool reEncode) { if (reEncode || this.IsModified) { StringBuilder retVal = new StringBuilder(); retVal.Append("Received: "); retVal.Append("from " + m_From); if (m_pFrom_TcpInfo != null) { retVal.Append(" (" + m_pFrom_TcpInfo.ToString() + ")"); } retVal.Append(" by " + m_By); if (m_pBy_TcpInfo != null) { retVal.Append(" (" + m_pBy_TcpInfo.ToString() + ")"); } if (!string.IsNullOrEmpty(m_Via)) { retVal.Append(" via " + m_Via); } if (!string.IsNullOrEmpty(m_With)) { retVal.Append(" with " + m_With); } if (!string.IsNullOrEmpty(m_ID)) { retVal.Append(" id " + m_ID); } if (!string.IsNullOrEmpty(m_For)) { retVal.Append(" for " + m_For); } retVal.Append("; " + MIME_Utils.DateTimeToRfc2822(m_Time)); retVal.Append("\r\n"); /* Some servers doesnt like uppercase. * retVal.Append("Received: "); * retVal.Append("FROM " + m_From); * if(m_pFrom_TcpInfo != null){ * retVal.Append(" (" + m_pFrom_TcpInfo.ToString() + ")"); * } * retVal.Append(" BY " + m_By); * if(m_pBy_TcpInfo != null){ * retVal.Append(" (" + m_pBy_TcpInfo.ToString() + ")"); * } * if(!string.IsNullOrEmpty(m_Via)){ * retVal.Append(" VIA " + m_Via); * } * if(!string.IsNullOrEmpty(m_With)){ * retVal.Append(" WITH " + m_With); * } * if(!string.IsNullOrEmpty(m_ID)){ * retVal.Append(" ID " + m_ID); * } * if(!string.IsNullOrEmpty(m_For)){ * retVal.Append(" FOR " + m_For); * } * retVal.Append("; " + MIME_Utils.DateTimeToRfc2822(m_Time)); * retVal.Append("\r\n");*/ return(retVal.ToString()); } else { return(m_ParseValue); } }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset) { if (IsModified) { StringBuilder retVal = new StringBuilder(); retVal.Append(Name + ": "); for (int i = 0; i < m_pAddresses.Count; i++) { if (i > 0) { retVal.Append("\t"); } // Don't add ',' for last item. if (i == (m_pAddresses.Count - 1)) { retVal.Append(m_pAddresses[i].ToString(wordEncoder) + "\r\n"); } else { retVal.Append(m_pAddresses[i].ToString(wordEncoder) + ",\r\n"); } } return retVal.ToString(); } else { return m_ParseValue; } }
public static void ConstructSinglePart(StructureBuilder builder, MIME_Entity entity, MIME_Encoding_EncodedWord wordEncoder, bool includeExtensions) { builder.Append("("); // NOTE: all header fields and parameters must in ENCODED form !!! // Add contentTypeMainMediaType if (entity.ContentType != null && entity.ContentType.Type != null) { builder.AppendQuoted(entity.ContentType.Type.ToUpperInvariant()); } else { builder.AppendQuoted("TEXT"); } // Add contentTypeSubMediaType if (entity.ContentType != null && entity.ContentType.SubType != null) { builder.SpaceNQuoted(entity.ContentType.SubType.ToUpperInvariant()); } else { builder.SpaceNQuoted("PLAIN"); } // conentTypeParameters - Syntax: {("name" SP "value" *(SP "name" SP "value"))} ConstructTypeParameters(builder, entity, wordEncoder); // contentID string contentID = entity.ContentID; if (contentID != null) { builder.SpaceNQuoted(wordEncoder.Encode(contentID)); } else { builder.AppendNil(); } // contentDescription string contentDescription = entity.ContentDescription; if (contentDescription != null) { builder.SpaceNQuoted(wordEncoder.Encode(contentDescription)); } else { builder.AppendNil(); } // contentEncoding if (entity.ContentTransferEncoding != null) { builder.SpaceNQuoted(entity.ContentTransferEncoding.ToUpperInvariant()); } else { // If not specified, then must be 7bit. builder.SpaceNQuoted("7bit"); } // contentSize if (entity.Body is MIME_b_SinglepartBase) { builder.Append(" ").Append(((MIME_b_SinglepartBase)entity.Body).EncodedData.Length.ToString()); } else { builder.Append(" 0"); } // envelope --->FOR ContentType: message / rfc822 ONLY ### if (entity.Body is MIME_b_MessageRfc822) { builder.Append(" "); ENVELOPE.ConstructEnvelope(builder, ((MIME_b_MessageRfc822)entity.Body).Message); // BODYSTRUCTURE builder.AppendNil(); // LINES builder.AppendNil(); } // contentLines ---> FOR ContentType: text/xxx ONLY ### if (entity.Body is MIME_b_Text) { builder.Append(" ").Append(GetLines(entity).ToString()); } #region BODYSTRUCTURE extention fields if (includeExtensions) { // body MD5 builder.AppendNil(); // body disposition Syntax: {(disposition-type [ SP ("name" SP "value" *(SP "name" SP "value"))])} ConstructBodyDisposition(builder, entity, wordEncoder); // body language builder.AppendNil(); // body location builder.AppendNil(); } #endregion builder.EndBracket(); }
public static void ConstructBodyDisposition(StructureBuilder builder, MIME_Entity entity, MIME_Encoding_EncodedWord wordEncoder) { if (entity.ContentDisposition != null && entity.ContentDisposition.Parameters.Count > 0) { builder.SpaceNBracket().AppendQuoted(entity.ContentDisposition.DispositionType.ToUpperInvariant()); if (entity.ContentDisposition.Parameters.Count > 0) { builder.SpaceNBracket(); bool first = true; foreach (MIME_h_Parameter parameter in entity.ContentDisposition.Parameters) { if (String.IsNullOrEmpty(parameter.Name)) { continue; } // For the first item, don't add SP. if (first) { first = false; } else { builder.Append(" "); } builder.AppendQuoted(parameter.Name.ToUpperInvariant()).SpaceNQuoted(wordEncoder.Encode(parameter.Value)); } builder.EndBracket(); } else { builder.AppendNil(); } builder.EndBracket(); } else { builder.AppendNil(); } }
/// <summary> /// Parses <b>address-list</b> from specified string value. /// </summary> /// <param name="value">The <b>address-list</b> string value.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception> /// <exception cref="ParseException">Is raised when <b>value</b> is not valid <b>address-list</b> value.</exception> public static Mail_t_AddressList Parse(string value) { if (value == null) { throw new ArgumentNullException("value"); } /* RFC 5322 3.4. * address = mailbox / group * mailbox = name-addr / addr-spec * name-addr = [display-name] angle-addr * angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr * group = display-name ":" [group-list] ";" [CFWS] * display-name = phrase * mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list * address-list = (address *("," address)) / obs-addr-list * group-list = mailbox-list / CFWS / obs-group-list */ MIME_Reader r = new MIME_Reader(value); Mail_t_AddressList retVal = new Mail_t_AddressList(); while (true) { string word = r.QuotedReadToDelimiter(new char[] { ',', '<', ':' }); // We processed all data. if (word == null && r.Available == 0) { break; } // group else if (r.Peek(true) == ':') { Mail_t_Group group = new Mail_t_Group(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word)) : null); // Consume ':' r.Char(true); while (true) { word = r.QuotedReadToDelimiter(new char[] { ',', '<', ':', ';' }); // We processed all data. if ((word == null && r.Available == 0) || r.Peek(false) == ';') { break; } // In valid address list value. else if (word == string.Empty) { throw new ParseException("Invalid address-list value '" + value + "'."); } // name-addr else if (r.Peek(true) == '<') { group.Members.Add(new Mail_t_Mailbox(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word)) : null, r.ReadParenthesized())); } // addr-spec else { group.Members.Add(new Mail_t_Mailbox(null, word)); } // We reached at the end of group. if (r.Peek(true) == ';') { r.Char(true); break; } // We have more addresses. if (r.Peek(true) == ',') { r.Char(false); } } retVal.Add(group); } // name-addr else if (r.Peek(true) == '<') { retVal.Add(new Mail_t_Mailbox(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word.Trim())) : null, r.ReadParenthesized())); } // addr-spec else { retVal.Add(new Mail_t_Mailbox(null, word)); } // We have more addresses. if (r.Peek(true) == ',') { r.Char(false); } } return(retVal); }
/// <summary> /// Returns address as string value. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <returns>Returns address as string value.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder) { if (string.IsNullOrEmpty(m_DisplayName)) { return "<" + m_Address.Trim() + ">"; } else { if (MIME_Encoding_EncodedWord.MustEncode(m_DisplayName)) { return wordEncoder == null ? (m_DisplayName + " " + "<" + m_Address.Trim() + ">") : (wordEncoder.Encode(m_DisplayName) + " " + "<" + m_Address.Trim() + ">"); } else { return TextUtils.QuoteString(m_DisplayName) + " " + "<" + m_Address.Trim() + ">"; } } }
/// <summary> /// Parses entity and it's child entities. /// </summary> internal void Parse(string text) { StringReader r = new StringReader(text); r.ReadToFirstChar(); // If starts with ( then multipart/xxx, otherwise normal single part entity if (r.StartsWith("(")) { // Entities are (entity1)(entity2)(...) <SP> ContentTypeSubType while (r.StartsWith("(")) { IMAP_BODY_Entity entity = new IMAP_BODY_Entity(); entity.Parse(r.ReadParenthesized()); entity.m_pParentEntity = this; m_pChildEntities.Add(entity); r.ReadToFirstChar(); } // Read multipart values. (nestedMimeEntries) contentTypeSubMediaType string contentTypeSubMediaType = r.ReadWord(); m_pContentType = new MIME_h_ContentType("multipart/" + contentTypeSubMediaType); } else { // Basic fields for non-multipart // contentTypeMainMediaType contentTypeSubMediaType (conentTypeParameters) contentID contentDescription contentEncoding contentSize [envelope] [contentLine] // Content-Type string contentTypeMainMediaType = r.ReadWord(); string contentTypeSubMediaType = r.ReadWord(); if (contentTypeMainMediaType.ToUpper() != "NIL" && contentTypeSubMediaType.ToUpper() != "NIL") { m_pContentType = new MIME_h_ContentType(contentTypeMainMediaType + "/" + contentTypeSubMediaType); } // Content-Type header field parameters // Parameters syntax: "name" <SP> "value" <SP> "name" <SP> "value" <SP> ... . r.ReadToFirstChar(); string conentTypeParameters = "NIL"; if (r.StartsWith("(")) { conentTypeParameters = r.ReadParenthesized(); StringReader contentTypeParamReader = new StringReader(conentTypeParameters); while (contentTypeParamReader.Available > 0) { string parameterName = contentTypeParamReader.ReadWord(); string parameterValue = MIME_Encoding_EncodedWord.DecodeS(contentTypeParamReader.ReadWord()); m_pContentType.Parameters[parameterName] = parameterValue; } } else { // Skip NIL r.ReadWord(); } // Content-ID: string contentID = r.ReadWord(); if (contentID.ToUpper() != "NIL") { m_ContentID = contentID; } // Content-Description: string contentDescription = r.ReadWord(); if (contentDescription.ToUpper() != "NIL") { m_ContentDescription = contentDescription; } // Content-Transfer-Encoding: string contentEncoding = r.ReadWord(); if (contentEncoding.ToUpper() != "NIL") { m_ContentEncoding = contentEncoding; } // Content Encoded data size in bytes string contentSize = r.ReadWord(); if (contentSize.ToUpper() != "NIL") { m_ContentSize = Convert.ToInt32(contentSize); } // Only for ContentType message/rfc822 if (string.Equals(this.ContentType.TypeWithSubype, MIME_MediaTypes.Message.rfc822, StringComparison.InvariantCultureIgnoreCase)) { r.ReadToFirstChar(); // envelope if (r.StartsWith("(")) { m_pEnvelope = new IMAP_Envelope(); m_pEnvelope.Parse(r.ReadParenthesized()); } else { // Skip NIL, ENVELOPE wasn't included r.ReadWord(); } // TODO: // BODYSTRUCTURE // contentLine } // Only for ContentType text/xxx if (contentTypeMainMediaType.ToLower() == "text") { // contentLine string contentLines = r.ReadWord(); if (contentLines.ToUpper() != "NIL") { m_ContentLines = Convert.ToInt32(contentLines); } } } }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset) { if (string.IsNullOrEmpty(m_Address)) { return "Return-Path: <>\r\n"; } else { return "Return-Path: <" + m_Address + ">\r\n"; } }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset) { return("TODO:"); }
/// <summary> /// Returns header field as string. /// </summary> /// <param name="wordEncoder">8-bit words ecnoder. Value null means that words are not encoded.</param> /// <param name="parmetersCharset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param> /// <returns>Returns header field as string.</returns> public override string ToString(MIME_Encoding_EncodedWord wordEncoder, Encoding parmetersCharset) { if (IsModified) { StringBuilder retVal = new StringBuilder(); retVal.Append("Received: "); retVal.Append("FROM " + m_From); if (m_pFrom_TcpInfo != null) { retVal.Append(" (" + m_pFrom_TcpInfo + ")"); } retVal.Append(" BY " + m_By); if (m_pBy_TcpInfo != null) { retVal.Append(" (" + m_pBy_TcpInfo + ")"); } if (!string.IsNullOrEmpty(m_Via)) { retVal.Append(" VIA " + m_Via); } if (!string.IsNullOrEmpty(m_With)) { retVal.Append(" WITH " + m_With); } if (!string.IsNullOrEmpty(m_ID)) { retVal.Append(" ID " + m_ID); } if (!string.IsNullOrEmpty(m_For)) { retVal.Append(" FOR " + m_For); } retVal.Append("; " + MIME_Utils.DateTimeToRfc2822(m_Time)); retVal.Append("\r\n"); return retVal.ToString(); } else { return m_ParseValue; } }
/// <summary> /// Parses header field from the specified value. /// </summary> /// <param name="value">Header field value. Header field name must be included. For example: 'Content-Type: text/plain'.</param> /// <returns>Returns parsed header field.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception> /// <exception cref="ParseException">Is raised when header field parsing errors.</exception> public static Mail_h_MailboxList Parse(string value) { if (value == null) { throw new ArgumentNullException("value"); } string[] name_value = value.Split(new[] { ':' }, 2); if (name_value.Length != 2) { throw new ParseException("Invalid header field value '" + value + "'."); } /* RFC 5322 3.4. * mailbox = name-addr / addr-spec * * name-addr = [display-name] angle-addr * * angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr * * display-name = phrase * * mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list */ MIME_Reader r = new MIME_Reader(MIME_Utils.UnfoldHeader(name_value.Length == 2 ? name_value[1].TrimStart() : "")); Mail_h_MailboxList retVal = new Mail_h_MailboxList(name_value[0], new Mail_t_MailboxList()); while (true) { string word = r.QuotedReadToDelimiter(new[] { ',', '<', ':' }); // We processed all data. if (word == null && r.Available == 0) { break; } // name-addr else if (r.Peek(true) == '<') { retVal.m_pAddresses.Add( new Mail_t_Mailbox( word != null ? MIME_Encoding_EncodedWord.DecodeAll(word) : null, r.ReadParenthesized())); } // addr-spec else { retVal.m_pAddresses.Add(new Mail_t_Mailbox(null, word)); } // We have more addresses. if (r.Peek(true) == ',') { r.Char(false); } } retVal.m_ParseValue = value; retVal.m_pAddresses.AcceptChanges(); return(retVal); }
private static string ConstructParts(MIME_Entity entity, bool bodystructure) { MIME_Encoding_EncodedWord mIME_Encoding_EncodedWord = new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.B, Encoding.UTF8); mIME_Encoding_EncodedWord.Split = false; StringBuilder stringBuilder = new StringBuilder(); if (entity.Body is MIME_b_Multipart) { stringBuilder.Append("("); foreach (MIME_Entity entity2 in ((MIME_b_Multipart)entity.Body).BodyParts) { stringBuilder.Append(IMAP_BODY.ConstructParts(entity2, bodystructure)); } if (entity.ContentType != null && entity.ContentType.SubType != null) { stringBuilder.Append(" \"" + entity.ContentType.SubType + "\""); } else { stringBuilder.Append(" NIL"); } stringBuilder.Append(")"); } else { stringBuilder.Append("("); if (entity.ContentType != null && entity.ContentType.Type != null) { stringBuilder.Append("\"" + entity.ContentType.Type + "\""); } else { stringBuilder.Append("NIL"); } if (entity.ContentType != null && entity.ContentType.SubType != null) { stringBuilder.Append(" \"" + entity.ContentType.SubType + "\""); } else { stringBuilder.Append(" NIL"); } if (entity.ContentType != null) { if (entity.ContentType.Parameters.Count > 0) { stringBuilder.Append(" ("); bool flag = true; foreach (MIME_h_Parameter mIME_h_Parameter in entity.ContentType.Parameters) { if (flag) { flag = false; } else { stringBuilder.Append(" "); } stringBuilder.Append(string.Concat(new string[] { "\"", mIME_h_Parameter.Name, "\" \"", mIME_Encoding_EncodedWord.Encode(mIME_h_Parameter.Value), "\"" })); } stringBuilder.Append(")"); } else { stringBuilder.Append(" NIL"); } } else { stringBuilder.Append(" NIL"); } string contentID = entity.ContentID; if (contentID != null) { stringBuilder.Append(" \"" + mIME_Encoding_EncodedWord.Encode(contentID) + "\""); } else { stringBuilder.Append(" NIL"); } string contentDescription = entity.ContentDescription; if (contentDescription != null) { stringBuilder.Append(" \"" + mIME_Encoding_EncodedWord.Encode(contentDescription) + "\""); } else { stringBuilder.Append(" NIL"); } if (entity.ContentTransferEncoding != null) { stringBuilder.Append(" \"" + mIME_Encoding_EncodedWord.Encode(entity.ContentTransferEncoding) + "\""); } else { stringBuilder.Append(" \"7bit\""); } if (entity.Body is MIME_b_SinglepartBase) { stringBuilder.Append(" " + ((MIME_b_SinglepartBase)entity.Body).EncodedData.Length.ToString()); } else { stringBuilder.Append(" 0"); } if (entity.Body is MIME_b_MessageRfc822) { stringBuilder.Append(" " + IMAP_Envelope.ConstructEnvelope(((MIME_b_MessageRfc822)entity.Body).Message)); } if (entity.Body is MIME_b_Text) { long num = 0L; StreamLineReader streamLineReader = new StreamLineReader(new MemoryStream(((MIME_b_SinglepartBase)entity.Body).EncodedData)); for (byte[] array = streamLineReader.ReadLine(); array != null; array = streamLineReader.ReadLine()) { num += 1L; } stringBuilder.Append(" " + num.ToString()); } stringBuilder.Append(")"); } return(stringBuilder.ToString()); }