Pop3cli
1#region License2//------------------------------------------------------------------------------
3// Copyright (c) Dmitrii Evdokimov
4// Source https://github.com/diev/
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9// http://www.apache.org/licenses/LICENSE-2.0
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//------------------------------------------------------------------------------
16
17// based on an article https://www.codeproject.com/Articles/15611/POP3-Email-Client-with-full-MIME-Support-NET-2-0
18
19// POP3 Quoted Printable
20// =====================
21//
22// copyright by Peter Huber, Singapore, 2006
23// this code is provided as is, bugs are probable, free for any use, no responsiblity accepted :-)
24//
25// based on QuotedPrintable Class from ASP emporium, http://www.aspemporium.com/classes.aspx?cid=6
26#endregion27
28using System;29using System.IO;30using System.Security;31using System.Text;32using System.Text.RegularExpressions;33
34namespace Mime35{
36/// <summary>37/// <para>38/// Robust and fast implementation of Quoted Printable39/// Multipart Internet Mail Encoding (MIME) which encodes every40/// character, not just "special characters" for transmission over SMTP.41/// </para>42/// <para>43/// More information on the quoted-printable encoding can be found44/// here: http://www.freesoft.org/CIE/RFC/1521/6.htm45/// </para>46/// </summary>47/// <remarks>48/// <para>49/// detailed in: RFC 152150/// </para>51/// <para>52/// more info: http://www.freesoft.org/CIE/RFC/1521/6.htm53/// </para>54/// <para>55/// The QuotedPrintable class encodes and decodes strings and files56/// that either were encoded or need encoded in the Quoted-Printable57/// MIME encoding for Internet mail. The encoding methods of the class58/// use pointers wherever possible to guarantee the fastest possible59/// encoding times for any size file or string. The decoding methods60/// use only the .NET framework classes.61/// </para>62/// <para>63/// The Quoted-Printable implementation64/// is robust which means it encodes every character to ensure that the65/// information is decoded properly regardless of machine or underlying66/// operating system or protocol implementation. The decode can recognize67/// robust encodings as well as minimal encodings that only encode special68/// characters and any implementation in between. Internally, the69/// class uses a regular expression replace pattern to decode a quoted-70/// printable string or file.71/// </para>72/// </remarks>73/// <example>74/// This example shows how to quoted-printable encode an html file and then75/// decode it.76/// <code>77/// string encoded = QuotedPrintable.EncodeFile(78/// @"C:\WEBS\wwwroot\index.html"79/// );80///81/// string decoded = QuotedPrintable.Decode(encoded);82///83/// Console.WriteLine(decoded);84/// </code>85/// </example>86internal class QuotedPrintable87{88private QuotedPrintable() { }89
90/// <summary>91/// Gets the maximum number of characters per quoted-printable92/// line as defined in the RFC minus 1 to allow for the =93/// character (soft line break).94/// </summary>95/// <remarks>96/// (Soft Line Breaks): The Quoted-Printable encoding REQUIRES97/// that encoded lines be no more than 76 characters long. If98/// longer lines are to be encoded with the Quoted-Printable99/// encoding, 'soft' line breaks must be used. An equal sign100/// as the last character on a encoded line indicates such a101/// non-significant ('soft') line break in the encoded text.102/// </remarks>103public const int RFC_1521_MAX_CHARS_PER_LINE = 75;104
105private static string HexDecoderEvaluator(Match m)106{107string hex = m.Groups[2].Value;108int iHex = Convert.ToInt32(hex, 16);109char c = (char)iHex;110
111return c.ToString();112}113
114private static string HexDecoder(string line)115{116if (line == null)117{118throw new ArgumentNullException();119}120
121//parse looking for =XX where XX is hexadecimal122Regex re = new Regex("(\\=([0-9A-F][0-9A-F]))", RegexOptions.IgnoreCase);123
124return re.Replace(line, new MatchEvaluator(HexDecoderEvaluator));125}126
127/// <summary>128/// Decodes an entire file's contents into plain text that129/// was encoded with quoted-printable.130/// </summary>131/// <param name="filepath">132/// The path to the quoted-printable encoded file to decode.133/// </param>134/// <returns>The decoded string.</returns>135/// <exception cref="ObjectDisposedException">136/// A problem occurred while attempting to decode the137/// encoded string.138/// </exception>139/// <exception cref="OutOfMemoryException">140/// There is insufficient memory to allocate a buffer for the141/// returned string.142/// </exception>143/// <exception cref="ArgumentNullException">144/// A string is passed in as a null reference.145/// </exception>146/// <exception cref="IOException">147/// An I/O error occurs, such as the stream being closed.148/// </exception>149/// <exception cref="FileNotFoundException">150/// The file was not found.151/// </exception>152/// <exception cref="SecurityException">153/// The caller does not have the required permission to open154/// the file specified in filepath.155/// </exception>156/// <exception cref="UnauthorizedAccessException">157/// filepath is read-only or a directory.158/// </exception>159/// <remarks>160/// Decodes a quoted-printable encoded file into a string161/// of unencoded text of any size.162/// </remarks>163public static string DecodeFile(string filepath)164{165if (filepath == null)166{167throw new ArgumentNullException();168}169
170FileInfo f = new FileInfo(filepath);171
172if (!f.Exists)173{174throw new FileNotFoundException();175}176
177string line;178StringBuilder decodedHtml = new StringBuilder();179
180using (StreamReader sr = f.OpenText())181{182while ((line = sr.ReadLine()) != null)183{184decodedHtml.Append(Decode(line));185}186
187return decodedHtml.ToString();188}189}190
191/// <summary>192/// Decodes a Quoted-Printable string of any size into193/// its original text.194/// </summary>195/// <param name="encoded">196/// The encoded string to decode.197/// </param>198/// <returns>The decoded string.</returns>199/// <exception cref="ArgumentNullException">200/// A string is passed in as a null reference.201/// </exception>202/// <remarks>203/// Decodes a quoted-printable encoded string into a string204/// of unencoded text of any size.205/// </remarks>206public static string Decode(string encoded)207{208if (encoded == null)209{210throw new ArgumentNullException();211}212
213string line;214using (StringWriter sw = new StringWriter())215using (StringReader sr = new StringReader(encoded))216{217while ((line = sr.ReadLine()) != null)218{219if (line.EndsWith("="))220{221sw.Write(HexDecoder(line.Substring(0, line.Length - 1)));222}223else224{225sw.WriteLine(HexDecoder(line));226}227
228sw.Flush();229}230
231return sw.ToString();232}233}234}235}
236