public static Encoding GetEncoding(int codepage) { return(Encoding.GetEncoding(codepage)); }
internal static bool TryParseMailbox(byte[] text, int startIndex, ref int index, int endIndex, string name, int codepage, bool throwOnError, out InternetAddress address) { Encoding encoding = Encoding.GetEncoding(codepage); DomainList route = null; address = null; // skip over the '<' index++; if (index >= endIndex) { if (throwOnError) { throw new ParseException(string.Format("Incomplete mailbox at offset {0}", startIndex), startIndex, index); } return(false); } if (text[index] == (byte)'@') { if (!DomainList.TryParse(text, ref index, endIndex, throwOnError, out route)) { if (throwOnError) { throw new ParseException(string.Format("Invalid route in mailbox at offset {0}", startIndex), startIndex, index); } return(false); } if (index + 1 >= endIndex || text[index] != (byte)':') { if (throwOnError) { throw new ParseException(string.Format("Incomplete route in mailbox at offset {0}", startIndex), startIndex, index); } return(false); } index++; } string addrspec; if (!TryParseAddrspec(text, ref index, endIndex, (byte)'>', throwOnError, out addrspec)) { return(false); } if (!ParseUtils.SkipCommentsAndWhiteSpace(text, ref index, endIndex, throwOnError)) { return(false); } if (index >= endIndex || text[index] != (byte)'>') { if (throwOnError) { throw new ParseException(string.Format("Unexpected end of mailbox at offset {0}", startIndex), startIndex, index); } return(false); } if (route != null) { address = new MailboxAddress(encoding, name, route, addrspec); } else { address = new MailboxAddress(encoding, name, addrspec); } index++; return(true); }
/// <summary> /// Initializes a new instance of the <see cref="MimeKit.IO.Filters.CharsetFilter"/> class. /// </summary> /// <remarks> /// Creates a new <see cref="CharsetFilter"/> to convert text from the specified /// source encoding into the target charset encoding. /// </remarks> /// <param name="sourceCodePage">Source code page.</param> /// <param name="targetCodePage">Target code page.</param> /// <exception cref="System.ArgumentOutOfRangeException"> /// <para><paramref name="sourceCodePage"/> is less than zero or greater than 65535.</para> /// <para>-or-</para> /// <para><paramref name="targetCodePage"/> is less than zero or greater than 65535.</para> /// </exception> /// <exception cref="System.NotSupportedException"> /// <para>The <paramref name="sourceCodePage"/> is not supported by the system.</para> /// <para>-or-</para> /// <para>The <paramref name="targetCodePage"/> is not supported by the system.</para> /// </exception> public CharsetFilter(int sourceCodePage, int targetCodePage) : this(Encoding.GetEncoding(sourceCodePage), Encoding.GetEncoding(targetCodePage)) { }
static CharsetUtils() { int gb2312; #if NETSTANDARD Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); #endif try { Latin1 = Encoding.GetEncoding(28591, new EncoderExceptionFallback(), new DecoderExceptionFallback()); } catch (NotSupportedException) { // Note: Some ASP.NET web hosts such as GoDaddy's Windows environment do not have // iso-8859-1 support, they only have the built-in text encodings, so we need to // hack around it by using an alternative encoding. // Try to use Windows-1252 if it is available... Latin1 = Encoding.GetEncoding(1252, new EncoderExceptionFallback(), new DecoderExceptionFallback()); } // Note: Encoding.UTF8.GetString() replaces invalid bytes with a unicode '?' character, // so we use our own UTF8 instance when using GetString() if we do not want it to do that. UTF8 = Encoding.GetEncoding(65001, new EncoderExceptionFallback(), new DecoderExceptionFallback()); aliases = new Dictionary <string, int> (MimeUtils.OrdinalIgnoreCase); AddAliases(aliases, 65001, -1, "utf-8", "utf8"); // ANSI_X3.4-1968 is used on some systems and should be // treated the same as US-ASCII. AddAliases(aliases, 20127, -1, "ansi_x3.4-1968"); // ANSI_X3.110-1983 is another odd-ball charset that appears // every once in a while and seems closest to ISO-8859-1. AddAliases(aliases, 28591, -1, "ansi_x3.110-1983", "latin1"); // Macintosh aliases AddAliases(aliases, 10000, -1, "macintosh"); AddAliases(aliases, 10079, -1, "x-mac-icelandic"); // Korean charsets (aliases for euc-kr) // 'upgrade' ks_c_5601-1987 to euc-kr since it is a superset AddAliases(aliases, 51949, -1, "ks_c_5601-1987", "ksc-5601-1987", "ksc-5601_1987", "ksc-5601", "5601", "ks_c_5861-1992", "ksc-5861-1992", "ksc-5861_1992", "euckr-0", "euc-kr"); // Chinese charsets (aliases for big5) AddAliases(aliases, 950, -1, "big5", "big5-0", "big5-hkscs", "big5.eten-0", "big5hkscs-0"); // Chinese charsets (aliases for gb2312) gb2312 = AddAliases(aliases, 936, -1, "gb2312", "gb-2312", "gb2312-0", "gb2312-80", "gb2312.1980-0"); // Chinese charsets (euc-cn and gbk not supported on Mono) // https://bugzilla.mozilla.org/show_bug.cgi?id=844082 seems to suggest falling back to gb2312. AddAliases(aliases, 51936, gb2312, "euc-cn", "gbk-0", "x-gbk", "gbk"); // Chinese charsets (hz-gb-2312 not suported on Mono) AddAliases(aliases, 52936, gb2312, "hz-gb-2312", "hz-gb2312"); // Chinese charsets (aliases for gb18030) AddAliases(aliases, 54936, -1, "gb18030-0", "gb18030"); // Japanese charsets (aliases for euc-jp) AddAliases(aliases, 51932, -1, "eucjp-0", "euc-jp", "ujis-0", "ujis"); // Japanese charsets (aliases for Shift_JIS) AddAliases(aliases, 932, -1, "shift_jis", "jisx0208.1983-0", "jisx0212.1990-0", "pck"); // Note from http://msdn.microsoft.com/en-us/library/system.text.encoding.getencodings.aspx // Encodings 50220 and 50222 are both associated with the name "iso-2022-jp", but they // are not identical. Encoding 50220 converts half-width Katakana characters to // full-width Katakana characters, whereas encoding 50222 uses a shift-in/shift-out // sequence to encode half-width Katakana characters. The display name for encoding // 50222 is "Japanese (JIS-Allow 1 byte Kana - SO/SI)" to distinguish it from encoding // 50220, which has the display name "Japanese (JIS)". // // If your application requests the encoding name "iso-2022-jp", the .NET Framework // returns encoding 50220. However, the encoding that is appropriate for your application // will depend on the preferred treatment of the half-width Katakana characters. AddAliases(aliases, 50220, -1, "iso-2022-jp"); }
static CharsetUtils() { aliases = new Dictionary <string, int> (StringComparer.OrdinalIgnoreCase); aliases.Add("utf-8", 65001); aliases.Add("utf8", 65001); // ANSI_X3.4-1968 is used on some systems and should be // treated the same as US-ASCII. aliases.Add("ansi_x3.4-1968", 20127); // ANSI_X3.110-1983 is another odd-ball charset that appears // every once in a while and seems closest to ISO-8859-1. aliases.Add("ansi_x3.110-1983", 28591); // Macintosh aliases aliases.Add("macintosh", 10000); aliases.Add("x-mac-icelandic", 10079); // Korean charsets (aliases for euc-kr) // 'upgrade' ks_c_5601-1987 to euc-kr since it is a superset aliases.Add("ks_c_5601-1987", 51949); aliases.Add("5601", 51949); aliases.Add("ksc-5601", 51949); aliases.Add("ksc-5601-1987", 51949); aliases.Add("ksc-5601_1987", 51949); aliases.Add("ks_c_5861-1992", 51949); aliases.Add("euckr-0", 51949); aliases.Add("euc-kr", 51949); // Chinese charsets (aliases for big5) aliases.Add("big5", 950); aliases.Add("big5-0", 950); aliases.Add("big5-hkscs", 950); aliases.Add("big5.eten-0", 950); aliases.Add("big5hkscs-0", 950); // Chinese charsets (aliases for gb2312) aliases.Add("gb2312", 936); aliases.Add("gb-2312", 936); aliases.Add("gb2312-0", 936); aliases.Add("gb2312-80", 936); aliases.Add("gb2312.1980-0", 936); // Chinese charsets (euc-cn and gbk not supported on Mono) try { Encoding.GetEncoding(51936); aliases.Add("euc-cn", 51936); aliases.Add("gbk-0", 51936); aliases.Add("x-gbk", 51936); aliases.Add("gbk", 51936); } catch { // https://bugzilla.mozilla.org/show_bug.cgi?id=844082 seems to suggest falling back to gb2312. // fall back to gb2312 aliases.Add("euc-cn", 936); aliases.Add("gbk-0", 936); aliases.Add("x-gbk", 936); aliases.Add("gbk", 936); } // Chinese charsets (hz-gb-2312 not suported on Mono) try { Encoding.GetEncoding(52936); aliases.Add("hz-gb-2312", 52936); aliases.Add("hz-gb2312", 52936); } catch { // fall back to gb2312 aliases.Add("hz-gb-2312", 936); aliases.Add("hz-gb2312", 936); } // Chinese charsets (aliases for gb18030) aliases.Add("gb18030-0", 54936); aliases.Add("gb18030", 54936); // Japanese charsets (aliases for euc-jp) aliases.Add("eucjp-0", 51932); aliases.Add("euc-jp", 51932); aliases.Add("ujis-0", 51932); aliases.Add("ujis", 51932); // Japanese charsets (aliases for Shift_JIS) aliases.Add("jisx0208.1983-0", 932); aliases.Add("jisx0212.1990-0", 932); aliases.Add("pck", 932); // Note from http://msdn.microsoft.com/en-us/library/system.text.encoding.getencodings.aspx // Encodings 50220 and 50222 are both associated with the name "iso-2022-jp", but they // are not identical. Encoding 50220 converts half-width Katakana characters to // full-width Katakana characters, whereas encoding 50222 uses a shift-in/shift-out // sequence to encode half-width Katakana characters. The display name for encoding // 50222 is "Japanese (JIS-Allow 1 byte Kana - SO/SI)" to distinguish it from encoding // 50220, which has the display name "Japanese (JIS)". // // If your application requests the encoding name "iso-2022-jp", the .NET Framework // returns encoding 50220. However, the encoding that is appropriate for your application // will depend on the preferred treatment of the half-width Katakana characters. }
static void ExtractMapiProperties(TnefReader reader, MimeMessage message, BodyBuilder builder) { var prop = reader.TnefPropertyReader; var recipient = new EmailAddress(); var sender = new EmailAddress(); string normalizedSubject = null; string subjectPrefix = null; MailboxAddress mailbox; var msgid = false; while (prop.ReadNextProperty()) { switch (prop.PropertyTag.Id) { case TnefPropertyId.InternetMessageId: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { message.MessageId = prop.ReadValueAsString(); msgid = true; } break; case TnefPropertyId.TnefCorrelationKey: // According to MSDN, PidTagTnefCorrelationKey is a unique key that is // meant to be used to tie the TNEF attachment to the encapsulating // message. It can be a string or a binary blob. It seems that most // implementations use the Message-Id string, so if this property // value looks like a Message-Id, then us it as one (unless we get a // InternetMessageId property, in which case we use that instead. if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { if (!msgid) { var value = prop.ReadValueAsString(); if (value.Length > 5 && value[0] == '<' && value[value.Length - 1] == '>' && value.IndexOf('@') != -1) { message.MessageId = value; } } } break; case TnefPropertyId.Subject: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { message.Subject = prop.ReadValueAsString(); } break; case TnefPropertyId.SubjectPrefix: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { subjectPrefix = prop.ReadValueAsString(); } break; case TnefPropertyId.NormalizedSubject: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { normalizedSubject = prop.ReadValueAsString(); } break; case TnefPropertyId.SenderName: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { sender.Name = prop.ReadValueAsString(); } break; case TnefPropertyId.SenderEmailAddress: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { sender.Addr = prop.ReadValueAsString(); } break; case TnefPropertyId.SenderSearchKey: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { sender.SearchKey = prop.ReadValueAsString(); } break; case TnefPropertyId.SenderAddrtype: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { sender.AddrType = prop.ReadValueAsString(); } break; case TnefPropertyId.ReceivedByName: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { recipient.Name = prop.ReadValueAsString(); } break; case TnefPropertyId.ReceivedByEmailAddress: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { recipient.Addr = prop.ReadValueAsString(); } break; case TnefPropertyId.ReceivedBySearchKey: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { recipient.SearchKey = prop.ReadValueAsString(); } break; case TnefPropertyId.ReceivedByAddrtype: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { recipient.AddrType = prop.ReadValueAsString(); } break; case TnefPropertyId.RtfCompressed: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { var rtf = new TextPart("rtf"); var converter = new RtfCompressedToRtf(); var content = new MemoryBlockStream(); using (var filtered = new FilteredStream(content)) { filtered.Add(converter); using (var compressed = prop.GetRawValueReadStream()) { compressed.CopyTo(filtered, 4096); filtered.Flush(); } } rtf.Content = new MimeContent(content); content.Position = 0; builder.Attachments.Add(rtf); } break; case TnefPropertyId.BodyHtml: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { var html = new TextPart("html"); Encoding encoding; if (prop.PropertyTag.ValueTnefType != TnefPropertyType.Unicode) { encoding = Encoding.GetEncoding(reader.MessageCodepage); } else { encoding = CharsetUtils.UTF8; } html.SetText(encoding, prop.ReadValueAsString()); builder.Attachments.Add(html); } break; case TnefPropertyId.Body: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { var plain = new TextPart("plain"); Encoding encoding; if (prop.PropertyTag.ValueTnefType != TnefPropertyType.Unicode) { encoding = Encoding.GetEncoding(reader.MessageCodepage); } else { encoding = CharsetUtils.UTF8; } plain.SetText(encoding, prop.ReadValueAsString()); builder.Attachments.Add(plain); } break; case TnefPropertyId.Importance: // https://msdn.microsoft.com/en-us/library/ee237166(v=exchg.80).aspx switch (prop.ReadValueAsInt32()) { case 2: message.Importance = MessageImportance.High; break; case 1: message.Importance = MessageImportance.Normal; break; case 0: message.Importance = MessageImportance.Low; break; } break; case TnefPropertyId.Priority: // https://msdn.microsoft.com/en-us/library/ee159473(v=exchg.80).aspx switch (prop.ReadValueAsInt32()) { case 1: message.Priority = MessagePriority.Urgent; break; case 0: message.Priority = MessagePriority.Normal; break; case -1: message.Priority = MessagePriority.NonUrgent; break; } break; case TnefPropertyId.Sensitivity: // https://msdn.microsoft.com/en-us/library/ee217353(v=exchg.80).aspx // https://tools.ietf.org/html/rfc2156#section-5.3.4 switch (prop.ReadValueAsInt32()) { case 1: message.Headers[HeaderId.Sensitivity] = "Personal"; break; case 2: message.Headers[HeaderId.Sensitivity] = "Private"; break; case 3: message.Headers[HeaderId.Sensitivity] = "Company-Confidential"; break; case 0: message.Headers.Remove(HeaderId.Sensitivity); break; } break; } } if (string.IsNullOrEmpty(message.Subject) && !string.IsNullOrEmpty(normalizedSubject)) { if (!string.IsNullOrEmpty(subjectPrefix)) { message.Subject = subjectPrefix + normalizedSubject; } else { message.Subject = normalizedSubject; } } if (sender.TryGetMailboxAddress(out mailbox)) { message.From.Add(mailbox); } if (recipient.TryGetMailboxAddress(out mailbox)) { message.To.Add(mailbox); } }
static void ExtractMapiProperties(TnefReader reader, MimeMessage message, BodyBuilder builder) { var prop = reader.TnefPropertyReader; while (prop.ReadNextProperty()) { switch (prop.PropertyTag.Id) { case TnefPropertyId.InternetMessageId: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { message.MessageId = prop.ReadValueAsString(); } break; case TnefPropertyId.Subject: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { message.Subject = prop.ReadValueAsString(); } break; case TnefPropertyId.RtfCompressed: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { var rtf = new TextPart("rtf"); rtf.ContentType.Name = "body.rtf"; var converter = new RtfCompressedToRtf(); var content = new MemoryBlockStream(); using (var filtered = new FilteredStream(content)) { filtered.Add(converter); using (var compressed = prop.GetRawValueReadStream()) { compressed.CopyTo(filtered, 4096); filtered.Flush(); } } rtf.Content = new MimeContent(content); content.Position = 0; builder.Attachments.Add(rtf); } break; case TnefPropertyId.BodyHtml: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { var html = new TextPart("html"); html.ContentType.Name = "body.html"; Encoding encoding; if (prop.PropertyTag.ValueTnefType != TnefPropertyType.Unicode) { encoding = Encoding.GetEncoding(reader.MessageCodepage); } else { encoding = CharsetUtils.UTF8; } html.SetText(encoding, prop.ReadValueAsString()); builder.Attachments.Add(html); } break; case TnefPropertyId.Body: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { var plain = new TextPart("plain"); plain.ContentType.Name = "body.txt"; Encoding encoding; if (prop.PropertyTag.ValueTnefType != TnefPropertyType.Unicode) { encoding = Encoding.GetEncoding(reader.MessageCodepage); } else { encoding = CharsetUtils.UTF8; } plain.SetText(encoding, prop.ReadValueAsString()); builder.Attachments.Add(plain); } break; case TnefPropertyId.Importance: switch (prop.ReadValueAsInt32()) { case 2: message.Importance = MessageImportance.High; break; case 0: message.Importance = MessageImportance.Low; break; } break; case TnefPropertyId.Priority: switch (prop.ReadValueAsInt32()) { case 2: message.Priority = MessagePriority.Urgent; break; case 0: message.Priority = MessagePriority.NonUrgent; break; } break; } } }
/// <summary> /// Initializes a new instance of the <see cref="MimeKit.IO.Filters.CharsetFilter"/> class. /// </summary> /// <remarks> /// Creates a new <see cref="CharsetFilter"/> to convert text from the specified /// source encoding into the target charset encoding. /// </remarks> /// <param name="sourceEncodingName">Source encoding name.</param> /// <param name="targetEncodingName">Target encoding name.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="sourceEncodingName"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="targetEncodingName"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.NotSupportedException"> /// <para>The <paramref name="sourceEncodingName"/> is not supported by the system.</para> /// <para>-or-</para> /// <para>The <paramref name="targetEncodingName"/> is not supported by the system.</para> /// </exception> public CharsetFilter(string sourceEncodingName, string targetEncodingName) : this(Encoding.GetEncoding(sourceEncodingName), Encoding.GetEncoding(targetEncodingName)) { }