mirror of
git://opensimulator.org/git/opensim-libs
synced 2026-08-14 00:58:00 +00:00
add DotNetOpenMail source
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenMail", "DotNetOpenMail\DotNetOpenMail.csproj", "{6FBB299F-81A1-49EA-B00A-E916F8F797B3}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenMailTests", "DotNetOpenMailTests\DotNetOpenMailTests.csproj", "{74F3DCD7-1325-4968-B466-38618A380CE9}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{6FBB299F-81A1-49EA-B00A-E916F8F797B3}.Debug.ActiveCfg = Debug|.NET
|
||||
{6FBB299F-81A1-49EA-B00A-E916F8F797B3}.Debug.Build.0 = Debug|.NET
|
||||
{6FBB299F-81A1-49EA-B00A-E916F8F797B3}.Release.ActiveCfg = Release|.NET
|
||||
{6FBB299F-81A1-49EA-B00A-E916F8F797B3}.Release.Build.0 = Release|.NET
|
||||
{74F3DCD7-1325-4968-B466-38618A380CE9}.Debug.ActiveCfg = Debug|.NET
|
||||
{74F3DCD7-1325-4968-B466-38618A380CE9}.Debug.Build.0 = Debug|.NET
|
||||
{74F3DCD7-1325-4968-B466-38618A380CE9}.Release.ActiveCfg = Release|.NET
|
||||
{74F3DCD7-1325-4968-B466-38618A380CE9}.Release.Build.0 = Release|.NET
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionItems) = postSolution
|
||||
CHANGES.txt = CHANGES.txt
|
||||
DotNetOpenMailTests.dll.config = DotNetOpenMailTests.dll.config
|
||||
DotNetOpenMailTests.dll.config.demo = DotNetOpenMailTests.dll.config.demo
|
||||
DotNetOpenMailTests.dll.log4net = DotNetOpenMailTests.dll.log4net
|
||||
LICENSE.txt = LICENSE.txt
|
||||
README.txt = README.txt
|
||||
README_NUNIT.txt = README_NUNIT.txt
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// This is an abstract version of the email attachment. It may or
|
||||
/// may not contain content, a character encoding method, a
|
||||
/// mime-encoding method, a content-type designation, a content-id
|
||||
/// designation, among other things
|
||||
/// </summary>
|
||||
public abstract class AbstractEmailAttachment : IEmailStringable
|
||||
{
|
||||
internal static readonly String CONTENTTYPE="Content-Type";
|
||||
internal static readonly String CONTENTTRANSFERENCODING="Content-Transfer-Encoding";
|
||||
internal static readonly String CONTENTDIPOSITION="Content-Disposition";
|
||||
internal static readonly String CONTENTID="Content-ID";
|
||||
internal static readonly String CONTENTDESCRIPTION="Content-Description";
|
||||
internal static readonly String CHARSET="charset";
|
||||
|
||||
/// <summary>
|
||||
/// The mail encoding type (e.g. quoted-printable, etc)
|
||||
/// </summary>
|
||||
protected EncodingType _encodingtype;
|
||||
|
||||
/// <summary>
|
||||
/// The "content type" of the attachment
|
||||
/// </summary>
|
||||
protected String _contenttype;
|
||||
|
||||
/// <summary>
|
||||
/// The content-transfer encoding of the attachment
|
||||
/// </summary>
|
||||
protected String _contenttransferencoding;
|
||||
|
||||
/// <summary>
|
||||
/// The content disposition of the attachment
|
||||
/// </summary>
|
||||
protected String _contentdisposition;
|
||||
|
||||
/// <summary>
|
||||
/// The content description of the attachment
|
||||
/// </summary>
|
||||
protected String _contentdescription;
|
||||
|
||||
/// <summary>
|
||||
/// The character set of the encoded text
|
||||
/// </summary>
|
||||
protected System.Text.Encoding _charset=null;
|
||||
|
||||
/// <summary>
|
||||
/// The unencoded contents, as a string (optional)
|
||||
/// </summary>
|
||||
protected String _contents=null;
|
||||
|
||||
/// <summary>
|
||||
/// An optional content id
|
||||
/// </summary>
|
||||
protected String _contentid=null;
|
||||
|
||||
/// <summary>
|
||||
/// The file name to identify the content.
|
||||
/// (This can be different from the actual file name,
|
||||
/// if there was one.)
|
||||
/// </summary>
|
||||
protected String _filename=null;
|
||||
|
||||
/// <summary>
|
||||
/// The file source to read from
|
||||
/// </summary>
|
||||
protected FileInfo _fileinfo=null;
|
||||
|
||||
/// <summary>
|
||||
/// The binary source of the file
|
||||
/// </summary>
|
||||
protected Byte[] _contentbytes=null;
|
||||
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
public AbstractEmailAttachment()
|
||||
{
|
||||
}
|
||||
|
||||
#region GetEncodedContents
|
||||
/// <summary>
|
||||
/// Get the contents, encoded for shipping via SMTP
|
||||
/// </summary>
|
||||
/// <param name="encoder">The encoder to encode the contents</param>
|
||||
/// <returns>returns the encoded string, ready for SMTP transfer</returns>
|
||||
internal virtual String GetEncodedContents(IEncoder encoder)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
System.Text.Encoding charset=null;
|
||||
if (_charset==null)
|
||||
{
|
||||
charset=System.Text.Encoding.UTF8;
|
||||
}
|
||||
else
|
||||
{
|
||||
charset=this._charset;
|
||||
}
|
||||
|
||||
if (_contents!=null)
|
||||
{
|
||||
encoder.Encode(new StringReader(_contents), new StringWriter(sb), charset);
|
||||
}
|
||||
else if (_fileinfo!=null)
|
||||
{
|
||||
encoder.Encode(_fileinfo.OpenRead(), new StringWriter(sb), charset);
|
||||
}
|
||||
else if (_contentbytes!=null)
|
||||
{
|
||||
encoder.Encode(new BinaryReader(new MemoryStream(_contentbytes)), new StringWriter(sb));
|
||||
}
|
||||
String encodedcontents=sb.ToString();
|
||||
|
||||
if (encodedcontents.Length!=0 && encodedcontents[encodedcontents.Length-1]!='\n')
|
||||
{
|
||||
return encodedcontents+SmtpProxy.ENDOFLINE+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return encodedcontents+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Return the encoded contents, including mime
|
||||
/// header.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
IEncoder encoder=EncoderFactory.GetEncoder(Encoding);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
sb.Append(GetInternalMimeHeader(encoder));
|
||||
sb.Append(GetEncodedContents(encoder));
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encoding
|
||||
/// <summary>
|
||||
/// The encoding type for this attachment.
|
||||
/// </summary>
|
||||
public EncodingType Encoding
|
||||
{
|
||||
get {return _encodingtype;}
|
||||
set {_encodingtype=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentType
|
||||
/// <summary>
|
||||
/// The "content type" of the attachment
|
||||
/// </summary>
|
||||
public String ContentType
|
||||
{
|
||||
get {return _contenttype;}
|
||||
set {_contenttype=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CharSet
|
||||
/// <summary>
|
||||
/// The character set of the encoded text
|
||||
/// </summary>
|
||||
public System.Text.Encoding CharSet
|
||||
{
|
||||
get {return _charset;}
|
||||
set {_charset=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentId
|
||||
/// <summary>
|
||||
/// An optional content id that is used to refer to
|
||||
/// the attachment from elsewhere within a multipart/related
|
||||
/// email.
|
||||
/// </summary>
|
||||
public String ContentId
|
||||
{
|
||||
get {return _contentid;}
|
||||
set {_contentid=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileName
|
||||
/// <summary>
|
||||
/// The file name to attach to the attachment.
|
||||
/// </summary>
|
||||
public String FileName
|
||||
{
|
||||
get {return _filename;}
|
||||
set {_filename=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Contents
|
||||
/// <summary>
|
||||
/// The unencoded contents, as a string (optional)
|
||||
/// </summary>
|
||||
public String Contents
|
||||
{
|
||||
get {return _contents;}
|
||||
set {_contents=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentBytes
|
||||
/// <summary>
|
||||
/// The raw bytes of the content (if this is the way
|
||||
/// it was set.)
|
||||
/// </summary>
|
||||
public byte[] ContentBytes
|
||||
{
|
||||
get {return _contentbytes;}
|
||||
set {_contentbytes=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInternalMimeHeader
|
||||
/// <summary>
|
||||
/// Create the internal mime header, as found on the
|
||||
/// mime-attachment itself.
|
||||
/// </summary>
|
||||
/// <param name="encoder"></param>
|
||||
/// <returns></returns>
|
||||
protected String GetInternalMimeHeader(IEncoder encoder)
|
||||
{
|
||||
return MakeContentType()+
|
||||
MakeTransferEncoding(encoder)+
|
||||
MakeContentId()+
|
||||
MakeContentDisposition()+
|
||||
MakeContentDescription()+
|
||||
SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeContentType
|
||||
private String MakeContentType()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder(AbstractEmailAttachment.CONTENTTYPE+": "+ContentType+";"+SmtpProxy.ENDOFLINE);
|
||||
if (_charset!=null)
|
||||
{
|
||||
// changed by Pietrovich to fix
|
||||
// windows-1251 .NET encoding bug.
|
||||
// windows-1251 BodyName returns "koi8-r"
|
||||
// instead of "windows-1251"
|
||||
// but still encodes string as windows-1251
|
||||
string bodyName = _charset.BodyName;
|
||||
|
||||
//#if (FORCEWIN1251)
|
||||
if ("koi8-r" == _charset.BodyName && "windows-1251" == _charset.HeaderName)
|
||||
{
|
||||
bodyName = _charset.HeaderName;
|
||||
}
|
||||
//#endif
|
||||
|
||||
sb.Append(" "+AbstractEmailAttachment.CHARSET + "=\"" +
|
||||
bodyName + "\""+SmtpProxy.ENDOFLINE);
|
||||
// _charset.BodyName + "\""+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
if (FileName!=null)
|
||||
{
|
||||
sb.Append(" name=\""+FileName+"\""+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
return sb.ToString();
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeTransferEncoding
|
||||
private String MakeTransferEncoding(IEncoder encoder)
|
||||
{
|
||||
return AbstractEmailAttachment.CONTENTTRANSFERENCODING+": "+encoder.ContentTransferEncodingString+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeContentId
|
||||
private String MakeContentId()
|
||||
{
|
||||
if (ContentId!=null)
|
||||
{
|
||||
return AbstractEmailAttachment.CONTENTID+": <" + ContentId + ">" + SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
return "";
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeContentDisposition
|
||||
private String MakeContentDisposition()
|
||||
{
|
||||
if (ContentId!=null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
if (ContentType!=null && FileName !=null)
|
||||
{
|
||||
return AbstractEmailAttachment.CONTENTDIPOSITION+": attachment;"+SmtpProxy.ENDOFLINE+
|
||||
" filename=\""+FileName+"\""+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
return "";
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeContentDescription
|
||||
private String MakeContentDescription()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
@@ -0,0 +1,309 @@
|
||||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.10.3077"
|
||||
SchemaVersion = "2.0"
|
||||
ProjectGuid = "{6FBB299F-81A1-49EA-B00A-E916F8F797B3}"
|
||||
>
|
||||
<Build>
|
||||
<Settings
|
||||
ApplicationIcon = ""
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "DotNetOpenMail"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "Library"
|
||||
PreBuildEvent = ""
|
||||
PostBuildEvent = ""
|
||||
RootNamespace = "DotNetOpenMail"
|
||||
RunPostBuildEvent = "OnBuildSuccess"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
Name = "Debug"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE"
|
||||
DocumentationFile = "DotNetOpenMail.xml"
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
NoStdLib = "false"
|
||||
NoWarn = ""
|
||||
Optimize = "false"
|
||||
OutputPath = "bin\Debug\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "TRACE"
|
||||
DocumentationFile = "DotNetOpenMail.xml"
|
||||
DebugSymbols = "false"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
NoStdLib = "false"
|
||||
NoWarn = ""
|
||||
Optimize = "true"
|
||||
OutputPath = "bin\Release\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
</Settings>
|
||||
<References>
|
||||
<Reference
|
||||
Name = "System"
|
||||
AssemblyName = "System"
|
||||
HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Data"
|
||||
AssemblyName = "System.Data"
|
||||
HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.XML"
|
||||
AssemblyName = "System.Xml"
|
||||
HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
<Include>
|
||||
<File
|
||||
RelPath = "AbstractEmailAttachment.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "AssemblyInfo.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "EhloSmtpResponse.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "EmailAddress.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "EmailAddressCollection.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "EmailMessage.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "FileAttachment.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "HtmlAttachment.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "IEmailStringable.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "ISendableMessage.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "ISmtpProxy.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "MailException.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "MessageHeader.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "MessageHeaderCollection.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "MimeBoundary.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "MimeContainer.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "RawEmailMessage.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "RFC2822Date.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpException.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpProxy.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpResponse.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpResponseCode.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpServer.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TextAttachment.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\Base64Encoder.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\DoNothingEncoder.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\EightBitEncoder.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\EncoderFactory.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\EncodingType.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\IEncoder.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\QPEncoder.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\SevenBitEncoder.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Logging\Logger.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Logging\LogMessage.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Resources\ARM.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Resources\DotNetOpenMail.resx"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpAuth\ISmtpAuthToken.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpAuth\LoginAuthToken.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpAuth\SmtpAuthFactory.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpAuth\SmtpAuthToken.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Utils\BinaryStreamUtil.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Utils\Configuration.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Utils\EmailAddressParser.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Utils\VersionInfo.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
</Include>
|
||||
</Files>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<VisualStudioProject>
|
||||
<CSHARP LastOpenVersion = "7.10.3077" >
|
||||
<Build>
|
||||
<Settings ReferencePath = "C:\Visual Studio Projects\DotNetOpenMail\lib\" >
|
||||
<Config
|
||||
Name = "Debug"
|
||||
EnableASPDebugging = "false"
|
||||
EnableASPXDebugging = "false"
|
||||
EnableUnmanagedDebugging = "false"
|
||||
EnableSQLServerDebugging = "false"
|
||||
RemoteDebugEnabled = "false"
|
||||
RemoteDebugMachine = ""
|
||||
StartAction = "Project"
|
||||
StartArguments = ""
|
||||
StartPage = ""
|
||||
StartProgram = ""
|
||||
StartURL = ""
|
||||
StartWorkingDirectory = ""
|
||||
StartWithIE = "true"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
EnableASPDebugging = "false"
|
||||
EnableASPXDebugging = "false"
|
||||
EnableUnmanagedDebugging = "false"
|
||||
EnableSQLServerDebugging = "false"
|
||||
RemoteDebugEnabled = "false"
|
||||
RemoteDebugMachine = ""
|
||||
StartAction = "Project"
|
||||
StartArguments = ""
|
||||
StartPage = ""
|
||||
StartProgram = ""
|
||||
StartURL = ""
|
||||
StartWorkingDirectory = ""
|
||||
StartWithIE = "true"
|
||||
/>
|
||||
</Settings>
|
||||
</Build>
|
||||
<OtherProjectSettings
|
||||
CopyProjectDestinationFolder = ""
|
||||
CopyProjectUncPath = ""
|
||||
CopyProjectOption = "0"
|
||||
ProjectView = "ShowAllFiles"
|
||||
ProjectTrust = "0"
|
||||
/>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using DotNetOpenMail.SmtpAuth;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// The server response from EHLO
|
||||
/// </summary>
|
||||
public class EhloSmtpResponse
|
||||
{
|
||||
private int _responseCode=0;
|
||||
private String _message;
|
||||
|
||||
ArrayList smtpAuthTypes=new ArrayList();
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the EhloSmtpResponse class
|
||||
/// </summary>
|
||||
public EhloSmtpResponse()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the available Auth Types strings
|
||||
/// as reported by the server.
|
||||
/// (e.g. "login", etc.)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String[] GetAvailableAuthTypes()
|
||||
{
|
||||
String[] stringArray=new String[smtpAuthTypes.Count];
|
||||
smtpAuthTypes.CopyTo(stringArray);
|
||||
|
||||
return stringArray;
|
||||
//return (SmtpAuthType[]) smtpAuthTypes.ToArray(typeof (SmtpAuthType[]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an Auth type (by string as contained in the
|
||||
/// EHLO authentication. These are converted to lower
|
||||
/// case.
|
||||
/// </summary>
|
||||
/// <param name="authType">The auth type from EHLO</param>
|
||||
public void AddAvailableAuthType(String authType)
|
||||
{
|
||||
smtpAuthTypes.Add(authType.Trim().ToLower());
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Add an Auth type
|
||||
/// </summary>
|
||||
/// <param name="smtpAuthType"></param>
|
||||
public void AddAvailableAuthType(SmtpAuthType smtpAuthType)
|
||||
{
|
||||
smtpAuthTypes.Add(smtpAuthType);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// The SMTP Reponse code
|
||||
/// </summary>
|
||||
public int ResponseCode
|
||||
{
|
||||
get { return _responseCode; }
|
||||
set { _responseCode=value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The SMTP Message. This will be "OK" if successful,
|
||||
/// otherwise it will be the part that failed.
|
||||
/// </summary>
|
||||
public String Message
|
||||
{
|
||||
get { return _message; }
|
||||
set { _message=value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// An email address.
|
||||
/// The two parts of the email address object
|
||||
/// are the email address itself and the
|
||||
/// name. The name may be encoded if desired.
|
||||
/// </summary>
|
||||
public class EmailAddress : IEmailStringable
|
||||
{
|
||||
private String _email=null;
|
||||
private String _name=null;
|
||||
private System.Text.Encoding _charset;
|
||||
private Encoding.EncodingType _encodingtype=Encoding.EncodingType.QuotedPrintable;
|
||||
|
||||
#region EmailAddress
|
||||
/// <summary>
|
||||
/// Create an instance of an email address object.
|
||||
/// </summary>
|
||||
/// <param name="email">The address portion of the email</param>
|
||||
/// <param name="name">The name portion of the email.</param>
|
||||
public EmailAddress(String email, String name)
|
||||
{
|
||||
if (email!=null)
|
||||
{
|
||||
email=email.Trim();
|
||||
}
|
||||
this._email=email;
|
||||
this._name=name;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EmailAddress
|
||||
/// <summary>
|
||||
/// Create an instance of an email address object.
|
||||
/// </summary>
|
||||
/// <param name="email">The address portion of the email</param>
|
||||
public EmailAddress(String email)
|
||||
{
|
||||
if (email!=null)
|
||||
{
|
||||
email=email.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
email="";
|
||||
}
|
||||
this._email=email;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EmailAddress
|
||||
/// <summary>
|
||||
/// Create an character-encoded instance of an email address object.
|
||||
/// </summary>
|
||||
/// <param name="email">The address portion of the email</param>
|
||||
/// <param name="name">The name portion of the email.</param>
|
||||
/// <param name="charset">The character set to encode the name portion of the email address.</param>
|
||||
/// <param name="encodingtype">The encoding type to use to encode the name portion of the mail address.</param>
|
||||
public EmailAddress(String email, String name, Encoding.EncodingType encodingtype, System.Text.Encoding charset)
|
||||
{
|
||||
|
||||
if (email!=null)
|
||||
{
|
||||
email=email.Trim();
|
||||
}
|
||||
this._email=email;
|
||||
this._name=name;
|
||||
this._charset=charset;
|
||||
this._encodingtype=encodingtype;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Email
|
||||
/// <summary>
|
||||
/// The email address portion of the email address object
|
||||
/// </summary>
|
||||
public String Email
|
||||
{
|
||||
get {return _email;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Name
|
||||
/// <summary>
|
||||
/// The name portion of the email address object
|
||||
/// </summary>
|
||||
public String Name
|
||||
{
|
||||
get {return _name;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region QuoteSpecials
|
||||
private String QuoteSpecials(String str)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
bool needsQuotes=false;
|
||||
for (int i=0; i< str.Length; i++)
|
||||
{
|
||||
char ch=str[i];
|
||||
if (ch=='\"')
|
||||
{
|
||||
needsQuotes=true;
|
||||
sb.Append('\\');
|
||||
}
|
||||
else if (ch=='(' || ch==')' ||
|
||||
ch=='<' || ch=='>' ||
|
||||
ch==']' || ch=='[' ||
|
||||
ch==':' || ch==';' ||
|
||||
ch=='@' || ch=='\\' ||
|
||||
ch==',' || ch=='.')
|
||||
{
|
||||
needsQuotes=true;
|
||||
|
||||
}
|
||||
sb.Append(ch);
|
||||
|
||||
}
|
||||
if (needsQuotes)
|
||||
{
|
||||
return "\""+sb.ToString()+"\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Create the string representation of this email address
|
||||
/// (encoded or otherwise) as it will appear in the email
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
if (_name!=null && _name.Trim()!="")
|
||||
{
|
||||
|
||||
IEncoder encoder=Encoding.EncoderFactory.GetEncoder(_encodingtype);
|
||||
System.Text.Encoding thecharset=_charset;
|
||||
if (thecharset==null)
|
||||
{
|
||||
thecharset=Utils.Configuration.GetInstance().GetDefaultCharset();
|
||||
}
|
||||
String encodedname=encoder.EncodeHeaderString("", QuoteSpecials(Name.Trim()), thecharset, false);
|
||||
|
||||
return encodedname+" <"+Email+">";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<"+Email+">";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString
|
||||
/// <summary>
|
||||
/// Calls ToDataString.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
return ToDataString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of EmailAddress objects. Implements
|
||||
/// CollectionBase
|
||||
/// </summary>
|
||||
public class EmailAddressCollection : CollectionBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new instance of the EmailAddressCollection
|
||||
/// </summary>
|
||||
public EmailAddressCollection()
|
||||
{
|
||||
}
|
||||
|
||||
#region Add
|
||||
/// <summary>
|
||||
/// Add an object to the collection
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">The EmailAddress object to add</param>
|
||||
/// <returns></returns>
|
||||
public int Add( EmailAddress emailaddress )
|
||||
{
|
||||
return( List.Add( emailaddress ) );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add
|
||||
/// <summary>
|
||||
/// Append a collection of objects to the existing collection
|
||||
/// </summary>
|
||||
/// <param name="emailaddresses">The EmailAddressCollection to append to the existing collection.</param>
|
||||
public void AddCollection( EmailAddressCollection emailaddresses )
|
||||
{
|
||||
foreach (EmailAddress emailaddress in emailaddresses)
|
||||
{
|
||||
List.Add(emailaddress);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IndexOf
|
||||
/// <summary>
|
||||
/// Find the index of the EmailAddress in the collection
|
||||
/// </summary>
|
||||
/// <param name="value">The object to find.</param>
|
||||
/// <returns>The index, from 0, or -1 if not found.</returns>
|
||||
public int IndexOf( EmailAddress value )
|
||||
{
|
||||
return( List.IndexOf( value ) );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
/// <summary>
|
||||
/// Insert an EmailAddress into the collection at the
|
||||
/// specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index, starting at zero.</param>
|
||||
/// <param name="emailaddress">The email address to add to the collection</param>
|
||||
public void Insert( int index, EmailAddress emailaddress )
|
||||
{
|
||||
List.Insert( index, emailaddress );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Remove
|
||||
/// <summary>
|
||||
/// Remove an address, if found, from the collection.
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">The EmailAddress to remove</param>
|
||||
public void Remove( EmailAddress emailaddress )
|
||||
{
|
||||
List.Remove( emailaddress );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Render the email addresses in a comma-separated list,
|
||||
/// suitable for being rendered in an email.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
bool doneone=false;
|
||||
foreach (EmailAddress emailaddress in List)
|
||||
{
|
||||
if (!doneone)
|
||||
{
|
||||
doneone=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(", ");
|
||||
}
|
||||
sb.Append(emailaddress.ToDataString());
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString
|
||||
/// <summary>
|
||||
/// Calls ToDataString().
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
return ToDataString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,675 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
using DotNetOpenMail.Resources;
|
||||
using DotNetOpenMail.Utils;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
//using log4net;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// An Email Message
|
||||
/// </summary>
|
||||
public class EmailMessage : ISendableMessage
|
||||
{
|
||||
|
||||
#region variables
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(EmailMessage));
|
||||
|
||||
private String _subject=null;
|
||||
private String _organization=null;
|
||||
private String _bodytext=null;
|
||||
|
||||
private EmailAddress _fromaddress=null;
|
||||
private EmailAddressCollection _toaddresses=new EmailAddressCollection();
|
||||
private EmailAddressCollection _ccaddresses=new EmailAddressCollection();
|
||||
private EmailAddressCollection _bccaddresses=new EmailAddressCollection();
|
||||
|
||||
private EmailAddress _envelopefromaddress=null;
|
||||
|
||||
private String _contenttype;
|
||||
private MimeBoundary _mimeboundary;
|
||||
|
||||
private TextAttachment _textpart=null;
|
||||
private HtmlAttachment _htmlpart=null;
|
||||
|
||||
private String _xmailer=null;
|
||||
|
||||
private ArrayList _mixedfileattachments=new ArrayList();
|
||||
private ArrayList _relatedfileattachments=new ArrayList();
|
||||
private MessageHeaderCollection _custommessageheaders=new MessageHeaderCollection();
|
||||
private System.Text.Encoding _charset;
|
||||
private Encoding.EncodingType _encodingtype=Encoding.EncodingType.QuotedPrintable;
|
||||
#endregion
|
||||
|
||||
#region EmailMessage
|
||||
/// <summary>
|
||||
/// Create a new instance of an EmailMessage.
|
||||
/// </summary>
|
||||
public EmailMessage()
|
||||
{
|
||||
_mimeboundary=new MimeBoundary();
|
||||
_charset=System.Text.Encoding.GetEncoding(Configuration.GetInstance().GetDefaultEncoding("iso-8859-1"));
|
||||
_bodytext=GetNoMimeMessage();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Subject
|
||||
/// <summary>
|
||||
/// The subject line or subject header of the
|
||||
/// email.
|
||||
/// </summary>
|
||||
public String Subject
|
||||
{
|
||||
get {return _subject;}
|
||||
set {_subject=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FromAddress
|
||||
/// <summary>
|
||||
/// The address that appears in the From header. It will
|
||||
/// also be used as the Envelope From address in the SMTP
|
||||
/// negotiation, unless it is overridden by the EnvelopeFromAddress
|
||||
/// setting.
|
||||
/// </summary>
|
||||
public EmailAddress FromAddress
|
||||
{
|
||||
get {return _fromaddress;}
|
||||
set {_fromaddress=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EnvelopeFromAddress
|
||||
/// <summary>
|
||||
/// Normally the FromAddress is used as the
|
||||
/// envelope-from address, but it can be
|
||||
/// overridden here, if it is not null.
|
||||
/// </summary>
|
||||
public EmailAddress EnvelopeFromAddress
|
||||
{
|
||||
get {return _envelopefromaddress;}
|
||||
set {_envelopefromaddress=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddToAddress
|
||||
/// <summary>
|
||||
/// Add a To address to the Headers. This will also
|
||||
/// be used during the "RCPT TO" SMTP negotiation
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">Email Address object of the recipient</param>
|
||||
public void AddToAddress(EmailAddress emailaddress)
|
||||
{
|
||||
_toaddresses.Add(emailaddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Add a To address to the Headers. This will also
|
||||
/// be used during the "RCPT TO" SMTP negotiation
|
||||
/// </summary>
|
||||
/// <param name="email">The plain email address (don't include the name)</param>
|
||||
public void AddToAddress(String email)
|
||||
{
|
||||
_toaddresses.Add(new EmailAddress(email));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToAddresses
|
||||
/// <summary>
|
||||
/// Retrieve the collection of recipients
|
||||
/// that will appear in the "To" header of the
|
||||
/// email.
|
||||
/// </summary>
|
||||
public EmailAddressCollection ToAddresses
|
||||
{
|
||||
get {return _toaddresses;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddCcAddress
|
||||
/// <summary>
|
||||
/// Add a Cc address to the Headers. This will also
|
||||
/// be used during the "RCPT TO" SMTP negotiation
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">Email Address object of the recipient</param>
|
||||
public void AddCcAddress(EmailAddress emailaddress)
|
||||
{
|
||||
_ccaddresses.Add(emailaddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Add a Cc address to the Headers. This will also
|
||||
/// be used during the "RCPT TO" SMTP negotiation
|
||||
/// </summary>
|
||||
/// <param name="email">The plain email address (don't include the name)</param>
|
||||
public void AddCcAddress(String email)
|
||||
{
|
||||
_ccaddresses.Add(new EmailAddress(email));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CcAddresses
|
||||
/// <summary>
|
||||
/// Retrieve the collection of recipients
|
||||
/// that will appear in the "Cc" header of the
|
||||
/// email.
|
||||
/// </summary>
|
||||
public EmailAddressCollection CcAddresses
|
||||
{
|
||||
get {return _ccaddresses;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddBccAddress
|
||||
/// <summary>
|
||||
/// Add a recipient who will be "Blind Carbon Copied"
|
||||
/// as a recipient of the email. BCC addresses are
|
||||
/// not added to the email headers, but only appear
|
||||
/// during the "RCPT TO" SMTP negotiation.
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">The EmailAddress object</param>
|
||||
public void AddBccAddress(EmailAddress emailaddress)
|
||||
{
|
||||
_bccaddresses.Add(emailaddress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a recipient who will be "Blind Carbon Copied"
|
||||
/// as a recipient of the email. BCC addresses are
|
||||
/// not added to the email headers, but only appear
|
||||
/// during the "RCPT TO" SMTP negotiation.
|
||||
/// </summary>
|
||||
/// <param name="email">The plain email address (don't include the name)</param>
|
||||
public void AddBccAddress(String email)
|
||||
{
|
||||
_bccaddresses.Add(new EmailAddress(email));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BccAddresses
|
||||
/// <summary>
|
||||
/// Get the current EmailAddressCollection of BCC addresses
|
||||
/// </summary>
|
||||
public EmailAddressCollection BccAddresses
|
||||
{
|
||||
get {return _bccaddresses;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Organization
|
||||
/// <summary>
|
||||
/// Get/set the organization (as it will appear in the organization
|
||||
/// header
|
||||
/// </summary>
|
||||
public String Organization
|
||||
{
|
||||
get {return _organization;}
|
||||
set {_organization=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region XMailer
|
||||
/// <summary>
|
||||
/// Get the current XMailer setting for the X-Mailer header.
|
||||
/// </summary>
|
||||
public String XMailer
|
||||
{
|
||||
get {return this._xmailer;}
|
||||
set {this._xmailer=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddCustomHeader
|
||||
/// <summary>
|
||||
/// Add a custom mail header, e.g. "X-MyHeader".
|
||||
/// </summary>
|
||||
/// <param name="header">The header name (without a colon)</param>
|
||||
/// <param name="val">The value of the header. This value will not
|
||||
/// be encoded.</param>
|
||||
public void AddCustomHeader(String header, String val)
|
||||
{
|
||||
_custommessageheaders.Add(new MessageHeader(header, val));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HeaderCharSet
|
||||
/// <summary>
|
||||
/// The charset that is used for encoding the headers
|
||||
/// </summary>
|
||||
public System.Text.Encoding HeaderCharSet
|
||||
{
|
||||
get {return _charset;}
|
||||
set {_charset=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HeaderEncoding
|
||||
/// <summary>
|
||||
/// The mime encoding that is used for encoding the headers
|
||||
/// </summary>
|
||||
public Encoding.EncodingType HeaderEncoding
|
||||
{
|
||||
get {return this._encodingtype;}
|
||||
set {_encodingtype=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetStandardHeaders
|
||||
/// <summary>
|
||||
/// Get the minimal header set in the specified character,
|
||||
/// and using the mime encoder provided.
|
||||
/// </summary>
|
||||
private MessageHeaderCollection GetStandardHeaders(System.Text.Encoding charset, IEncoder encoder)
|
||||
{
|
||||
|
||||
MessageHeaderCollection standardheaders=new MessageHeaderCollection();
|
||||
|
||||
standardheaders.Add(new MessageHeader("From", _fromaddress.ToDataString()));
|
||||
standardheaders.Add(new MessageHeader("To", _toaddresses.ToDataString()));
|
||||
|
||||
if (_ccaddresses.Count>0)
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("Cc", _ccaddresses.ToString()));
|
||||
}
|
||||
//if (_bccaddresses.Count>0)
|
||||
//{
|
||||
//standardheaders.Add(new MessageHeader("Bcc", _bccaddresses.ToString()));
|
||||
//}
|
||||
|
||||
String subject=_subject;
|
||||
if (subject==null || subject.Trim()=="")
|
||||
{
|
||||
subject=EncodeHeaderValue("Subject", ARM.GetInstance().GetString("no_subject"));
|
||||
}
|
||||
standardheaders.Add(new MessageHeader("Subject", EncodeHeaderValue("Subject", subject)));
|
||||
standardheaders.Add(new MessageHeader("Date", new RFC2822Date(DateTime.Now, TimeZone.CurrentTimeZone).ToString()));
|
||||
if (!HasBodyTextOnly())
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("MIME-Version", "1.0"));
|
||||
}
|
||||
#region X-Mailer Header
|
||||
if (_xmailer!=null)
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("X-Mailer", _xmailer));
|
||||
}
|
||||
else
|
||||
{
|
||||
String xmailer=Configuration.GetInstance().GetXSender();
|
||||
if (xmailer!=null)
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("X-Mailer", xmailer));
|
||||
}
|
||||
else
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("X-Mailer", "DotNetOpenMail "+VersionInfo.GetInstance().ToString()));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
String contentType=null;
|
||||
if (HasBodyTextOnly())
|
||||
{
|
||||
// ignore the mime stuff for now
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HasMixedContent())
|
||||
{
|
||||
contentType="multipart/mixed;"+SmtpProxy.ENDOFLINE+
|
||||
" boundary=\""+_mimeboundary.BoundaryString+"\"";
|
||||
}
|
||||
else if (HasRelatedContent())
|
||||
{
|
||||
contentType="multipart/related;"+SmtpProxy.ENDOFLINE+
|
||||
" boundary=\""+_mimeboundary.BoundaryString+"\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
contentType="multipart/alternative;"+SmtpProxy.ENDOFLINE+
|
||||
" boundary=\""+_mimeboundary.BoundaryString+"\"";
|
||||
}
|
||||
|
||||
// note: see http://www.faqs.org/rfcs/rfc2045.html , part 6.4
|
||||
//contentType+=" charset=\""+charset.BodyName+"\"";
|
||||
|
||||
standardheaders.Add(new MessageHeader("Content-Type", contentType));
|
||||
//standardheaders.Add(new MessageHeader("Content-Transfer-Encoding", encoder.ContentTransferEncodingString));
|
||||
}
|
||||
return standardheaders;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeHeaderValue
|
||||
/// <summary>
|
||||
/// Encode a header value using the current header encoder and charset.
|
||||
/// </summary>
|
||||
/// <param name="name">The header name</param>
|
||||
/// <param name="val">The header value</param>
|
||||
/// <returns></returns>
|
||||
private String EncodeHeaderValue(String name, String val)
|
||||
{
|
||||
IEncoder encoder=Encoding.EncoderFactory.GetEncoder(this.HeaderEncoding);
|
||||
return encoder.EncodeHeaderString(name, val, this.HeaderCharSet, false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HasMixedContent
|
||||
/// <summary>
|
||||
/// Returns true if there is content that should be "multipart/mixed"
|
||||
/// </summary>
|
||||
/// <returns>true if the content is multipart/mixed.</returns>
|
||||
private bool HasMixedContent()
|
||||
{
|
||||
return (_mixedfileattachments.Count > 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HasRelatedContent
|
||||
/// <summary>
|
||||
/// Returns true if there is content that should be "multipart/related"
|
||||
/// </summary>
|
||||
/// <returns>true if the content is multipart/related.</returns>
|
||||
private bool HasRelatedContent()
|
||||
{
|
||||
return (_relatedfileattachments.Count > 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataStringHeaders
|
||||
/// <summary>
|
||||
/// Encode the headers as they will appear in the email
|
||||
/// </summary>
|
||||
/// <param name="charset">the charset encoding for the string</param>
|
||||
/// <param name="encoder">the mime encoding</param>
|
||||
/// <returns>the encoded string</returns>
|
||||
internal String ToDataStringHeaders(System.Text.Encoding charset, IEncoder encoder)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
MessageHeaderCollection standardheaders=GetStandardHeaders(charset, encoder);
|
||||
sb.Append(standardheaders.ToDataString());
|
||||
|
||||
if (_custommessageheaders.Count > 0)
|
||||
{
|
||||
sb.Append(_custommessageheaders.ToDataString());
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HasBodyTextOnly
|
||||
private bool HasBodyTextOnly()
|
||||
{
|
||||
return (_textpart==null
|
||||
&& _htmlpart==null
|
||||
&& !HasMixedContent()
|
||||
&& !HasRelatedContent());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataStringBody
|
||||
/// <summary>
|
||||
/// Encode the email body as it will appear in the email
|
||||
/// </summary>
|
||||
/// <returns>the encoded body</returns>
|
||||
internal String ToDataStringBody()
|
||||
{
|
||||
bool mixedistop=false;
|
||||
bool relatedistop=false;
|
||||
bool alternativeistop=false;
|
||||
|
||||
if (HasBodyTextOnly())
|
||||
{
|
||||
return FormatBodyText(_bodytext);
|
||||
}
|
||||
|
||||
MimeBoundary relatedcontentmimeboundary=null;
|
||||
MimeBoundary mixedcontentmimeboundary=null;
|
||||
MimeBoundary altertnativecontentmimeboundary=null;
|
||||
|
||||
#region Determine which uses the top-level boundary
|
||||
if (HasMixedContent())
|
||||
{
|
||||
mixedistop=true;
|
||||
mixedcontentmimeboundary=_mimeboundary;
|
||||
relatedcontentmimeboundary=new MimeBoundary();
|
||||
altertnativecontentmimeboundary=new MimeBoundary();
|
||||
}
|
||||
else if (HasRelatedContent())
|
||||
{
|
||||
relatedistop=true;
|
||||
relatedcontentmimeboundary=_mimeboundary;
|
||||
altertnativecontentmimeboundary=new MimeBoundary();
|
||||
}
|
||||
else
|
||||
{
|
||||
alternativeistop=true;
|
||||
altertnativecontentmimeboundary=_mimeboundary;
|
||||
}
|
||||
#endregion
|
||||
|
||||
MimeContainer alternativemimecontainer=new MimeContainer(altertnativecontentmimeboundary, "multipart/alternative", alternativeistop);
|
||||
MimeContainer topcontainer=alternativemimecontainer;
|
||||
|
||||
#region Text & HTML Parts
|
||||
if (_textpart!=null)
|
||||
{
|
||||
alternativemimecontainer.AddAttachment(_textpart);
|
||||
}
|
||||
|
||||
if (_htmlpart!=null)
|
||||
{
|
||||
alternativemimecontainer.AddAttachment(_htmlpart);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Related Content
|
||||
if (HasRelatedContent())
|
||||
{
|
||||
//topcontainer=new MimeContainer(relatedcontentmimeboundary, "multipart/related", relatedistop);
|
||||
topcontainer=new MimeContainer(relatedcontentmimeboundary, "multipart/related;\r\n type=\"multipart/alternative\"", relatedistop);
|
||||
topcontainer.AddMimeContainer(alternativemimecontainer);
|
||||
foreach (FileAttachment attachment in _relatedfileattachments)
|
||||
{
|
||||
topcontainer.AddAttachment(attachment);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Mixed Content
|
||||
if (HasMixedContent())
|
||||
{
|
||||
|
||||
MimeContainer oldtopcontainer=topcontainer;
|
||||
topcontainer=new MimeContainer(mixedcontentmimeboundary, "multipart/mixed", mixedistop);
|
||||
topcontainer.AddMimeContainer(oldtopcontainer);
|
||||
|
||||
foreach (FileAttachment attachment in _mixedfileattachments)
|
||||
{
|
||||
topcontainer.AddAttachment(attachment);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
if (_bodytext==null)
|
||||
{
|
||||
return topcontainer.ToDataString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return FormatBodyText(_bodytext)+".\r\n\r\n"
|
||||
+topcontainer.ToDataString();
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FormatBodyText
|
||||
/// <summary>
|
||||
/// format the body text---not implemented yet.
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns></returns>
|
||||
private String FormatBodyText(String text)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetNoMimeMessage
|
||||
private String GetNoMimeMessage()
|
||||
{
|
||||
return ARM.GetInstance().GetString("this_is_mime");
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The text that occurs within the body. By default,
|
||||
/// it is a MIME notice, but it can be overridden here.
|
||||
/// NOTE: This is only useful for 7 bit us-ascii currently.
|
||||
/// </summary>
|
||||
public String BodyText
|
||||
{
|
||||
get { return _bodytext;}
|
||||
set { _bodytext=value;}
|
||||
}
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Render the encoded message for smtp "DATA" transmission.
|
||||
/// This is the final version that will get sent to the
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
IEncoder encoder=EncoderFactory.GetEncoder(HeaderEncoding);
|
||||
return ToDataStringHeaders(this.HeaderCharSet, encoder)+SmtpProxy.ENDOFLINE+ToDataStringBody();
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
/// <summary>
|
||||
/// Send out the email via the smtp server given. If
|
||||
/// the SMTP server throws an error, an SmtpException will
|
||||
/// be thrown. All other exceptions will be MailExceptions
|
||||
/// </summary>
|
||||
/// <param name="smtpserver">The outgoing SMTP server.</param>
|
||||
/// <returns>true if sent successfully. (note that this
|
||||
/// will not currently return false, but in the future
|
||||
/// a false value may be used)</returns>
|
||||
public bool Send(SmtpServer smtpserver)
|
||||
{
|
||||
//SmtpProxy smtpproxy=smtpserver.GetSmtpProxy();
|
||||
if(_fromaddress == null)
|
||||
{
|
||||
throw new MailException(ARM.GetInstance().GetString("error_no_from"));
|
||||
}
|
||||
|
||||
EmailAddress envelopefrom=_envelopefromaddress;
|
||||
if (envelopefrom==null)
|
||||
{
|
||||
envelopefrom=_fromaddress;
|
||||
}
|
||||
EmailAddressCollection allrecipients=new EmailAddressCollection();
|
||||
allrecipients.AddCollection(_toaddresses);
|
||||
allrecipients.AddCollection(_ccaddresses);
|
||||
allrecipients.AddCollection(_bccaddresses);
|
||||
return smtpserver.Send(this, allrecipients, envelopefrom);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentType
|
||||
/// <summary>
|
||||
/// Set the content type string in the mime header
|
||||
/// </summary>
|
||||
public String ContentType
|
||||
{
|
||||
get {return _contenttype;}
|
||||
set {_contenttype=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TextPart
|
||||
/// <summary>
|
||||
/// Set the plain text part of the email. This is optional
|
||||
/// </summary>
|
||||
public TextAttachment TextPart
|
||||
{
|
||||
set {_textpart=value;}
|
||||
get {return _textpart;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HtmlPart
|
||||
/// <summary>
|
||||
/// Set the html part of the email. This is optional
|
||||
/// </summary>
|
||||
public HtmlAttachment HtmlPart
|
||||
{
|
||||
set {_htmlpart=value;}
|
||||
get {return _htmlpart;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddMixedAttachment
|
||||
/// <summary>
|
||||
/// Add an attachment which will appear to the user as
|
||||
/// a separate file. (It is not referred to in the email itself.)
|
||||
/// </summary>
|
||||
/// <param name="fileattachment">The file attachment</param>
|
||||
public void AddMixedAttachment(FileAttachment fileattachment)
|
||||
{
|
||||
_mixedfileattachments.Add(fileattachment);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddRelatedAttachment
|
||||
/// <summary>
|
||||
/// Add an image which is referred to from another part of
|
||||
/// the email (probably the HTML attachment). You should
|
||||
/// set the ContentID of the file attachment before passing
|
||||
/// it in.
|
||||
/// </summary>
|
||||
/// <param name="fileattachment">The file attachment</param>
|
||||
public void AddRelatedAttachment(FileAttachment fileattachment)
|
||||
{
|
||||
_relatedfileattachments.Add(fileattachment);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Encode a file in Base64 Encoding.
|
||||
///
|
||||
/// See: http://www.freesoft.org/CIE/RFC/1521/7.htm
|
||||
/// </summary>
|
||||
public class Base64Encoder : IEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum chars per line before end of line char(s)
|
||||
/// </summary>
|
||||
public static readonly int MAX_CHARS_PER_LINE=76;
|
||||
|
||||
/// <summary>
|
||||
/// The end-of-line character(s) to use
|
||||
/// </summary>
|
||||
public static readonly String END_OF_LINE="\r\n";
|
||||
|
||||
#region Base64Encoder
|
||||
/// <summary>
|
||||
/// Empty Constructor
|
||||
/// </summary>
|
||||
private Base64Encoder()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInstance
|
||||
/// <summary>
|
||||
/// Create an instance of this class
|
||||
/// </summary>
|
||||
public static Base64Encoder GetInstance()
|
||||
{
|
||||
return new Base64Encoder();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the Stringreader's data in base64.
|
||||
///
|
||||
/// Note: This is not particularly efficient on memory.
|
||||
/// This method should probably be improved to
|
||||
/// take advantage of the Reader, rather than
|
||||
/// taking the whole string into memory.
|
||||
/// </summary>
|
||||
/// <param name="stringreader">Reader for incoming string</param>
|
||||
/// <param name="stringwriter">Writer for outgoing encoded string</param>
|
||||
/// <param name="encoding">The character encoding for the encoded string.</param>
|
||||
public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding encoding)
|
||||
{
|
||||
try
|
||||
{
|
||||
String sourceString=stringreader.ReadToEnd();
|
||||
stringwriter.Write(EncodeString(sourceString, encoding));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new Exception("Error in base64Encode" + e.Message);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the File's data in base64.
|
||||
/// </summary>
|
||||
/// <param name="filestream">Reader for incoming string</param>
|
||||
/// <param name="stringwriter">Writer for outgoing encoded string</param>
|
||||
/// <param name="charset">The character set for the encoded string</param>
|
||||
public void Encode(FileStream filestream, StringWriter stringwriter, System.Text.Encoding charset)
|
||||
{
|
||||
//fs = finfo.OpenRead();
|
||||
byte[] buffer = new byte[filestream.Length];
|
||||
filestream.Read(buffer, 0, buffer.Length);
|
||||
filestream.Close();
|
||||
stringwriter.Write(MakeLines(System.Convert.ToBase64String(buffer, 0, buffer.Length)));
|
||||
|
||||
//Encode(new StringReader(System.Text.Encoding.ASCII.GetString(buffer)), stringwriter);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the File's data in base64.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">Reader for incoming string</param>
|
||||
/// <param name="stringwriter">Writer for outgoing encoded string</param>
|
||||
public void Encode(BinaryReader binaryreader, StringWriter stringwriter)
|
||||
{
|
||||
//fs = finfo.OpenRead();
|
||||
byte[] b;
|
||||
int charstoread=Base64Encoder.MAX_CHARS_PER_LINE * 102;
|
||||
while (true)
|
||||
{
|
||||
b = binaryreader.ReadBytes(charstoread);
|
||||
if (b.Length > 0)
|
||||
{
|
||||
stringwriter.Write(MakeLines(Convert.ToBase64String(b)));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Encode(new StringReader(System.Text.Encoding.ASCII.GetString(buffer)), stringwriter);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeString
|
||||
/// <summary>
|
||||
/// Encode a string in Base64 in a particular characters set
|
||||
/// </summary>
|
||||
/// <param name="sourceString">The source text</param>
|
||||
/// <param name="charset">the charset for the encoded text</param>
|
||||
/// <returns>Returns an encoded string</returns>
|
||||
public String EncodeString(String sourceString, System.Text.Encoding charset)
|
||||
{
|
||||
byte[] sourceBytes = new byte[sourceString.Length];
|
||||
sourceBytes = charset.GetBytes(sourceString);
|
||||
//sourceBytes = System.Text.Encoding.UTF8.GetBytes(sourceString);
|
||||
String result=Convert.ToBase64String(sourceBytes);
|
||||
return (MakeLines(result));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeHeaderString
|
||||
/// <summary>
|
||||
/// Encode header as per RFC 2047:
|
||||
/// http://www.faqs.org/rfcs/rfc2047.html
|
||||
/// </summary>
|
||||
/// <param name="name">The header name</param>
|
||||
/// <param name="val">The header text to be encoded (data only)</param>
|
||||
/// <param name="charset">The charset for the encoded string</param>
|
||||
/// <param name="forceencoding">ignored for this class</param>
|
||||
/// <returns>Returns the encoded string</returns>
|
||||
public String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding)
|
||||
{
|
||||
String encodedtext=EncodeString(val, charset);
|
||||
String tmp="=?"+charset.HeaderName+"?B?"+encodedtext+"?=";
|
||||
return tmp;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region MakeLines
|
||||
/// <summary>
|
||||
/// Chop the text into lines that are smaller
|
||||
/// than MAX_CHARS_PER_LINE
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
private String MakeLines(String source)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
int pos=0;
|
||||
for (int i=0; i<source.Length; i++)
|
||||
{
|
||||
sb.Append(source[i]);
|
||||
pos++;
|
||||
if (pos>=Base64Encoder.MAX_CHARS_PER_LINE)
|
||||
{
|
||||
sb.Append(Base64Encoder.END_OF_LINE);
|
||||
pos=0;
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public String ContentTransferEncodingString
|
||||
{
|
||||
get {return "base64";}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// An encoder that does nothing. (This is essentially
|
||||
/// what the 7bit and 8bit encodings are; they are just
|
||||
/// markers, not actual encodings)
|
||||
/// </summary>
|
||||
public abstract class DoNothingEncoder : IEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
public DoNothingEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Echo the text back unchanged.
|
||||
/// </summary>
|
||||
/// <param name="stringreader">Reader for the incoming string</param>
|
||||
/// <param name="stringwriter">Writer for the outgoing string</param>
|
||||
/// <param name="encoding">The encodigng for the outgoing string (ignored)</param>
|
||||
public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding encoding)
|
||||
{
|
||||
try
|
||||
{
|
||||
stringwriter.Write(stringreader.ReadToEnd());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new Exception("Error writing during Encoding" + e.Message);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Echo the text back unchanged
|
||||
/// </summary>
|
||||
/// <param name="filestream">The incoming filestream</param>
|
||||
/// <param name="stringwriter">The outgoing filestream</param>
|
||||
/// <param name="charset">Charset (ignored)</param>
|
||||
public void Encode(FileStream filestream, StringWriter stringwriter, System.Text.Encoding charset)
|
||||
{
|
||||
byte[] buffer = new byte[filestream.Length];
|
||||
filestream.Read(buffer, 0, buffer.Length);
|
||||
filestream.Close();
|
||||
stringwriter.Write(buffer);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Echo the text back unchanged (good for 7bit text only).
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">The incoming binaryreader</param>
|
||||
/// <param name="stringwriter">The outgoing stream</param>
|
||||
public void Encode(BinaryReader binaryreader, StringWriter stringwriter)
|
||||
{
|
||||
throw new Exception("Binary reader doesn't do anything for this reader");
|
||||
//stringwriter.Write(binaryreader.ReadString());
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Do nothing to the header string
|
||||
/// </summary>
|
||||
/// <param name="name">The header key</param>
|
||||
/// <param name="val">The header value</param>
|
||||
/// <param name="charset">The charset to encode in (ignored)</param>
|
||||
/// <param name="forceencoding">(ignored)</param>
|
||||
/// <returns></returns>
|
||||
public String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public virtual String ContentTransferEncodingString
|
||||
{
|
||||
get {throw new ApplicationException("Implement this");}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Denotes 8bit encoding. Note that this doesn't really
|
||||
/// encode anything; it just specifies that this email is already
|
||||
/// in 8-bit encoding.
|
||||
/// </summary>
|
||||
public class EightBitEncoder : DoNothingEncoder
|
||||
{
|
||||
#region EightBitEncoder
|
||||
/// <summary>
|
||||
/// Empty Constructor
|
||||
/// </summary>
|
||||
private EightBitEncoder()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInstance
|
||||
/// <summary>
|
||||
/// Create the EightBitEncoder object.
|
||||
/// </summary>
|
||||
public static EightBitEncoder GetInstance()
|
||||
{
|
||||
return new EightBitEncoder();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public override String ContentTransferEncodingString
|
||||
{
|
||||
get {return "8bit";}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory for instantiating the right encoder class,
|
||||
/// given an encoding
|
||||
/// </summary>
|
||||
internal class EncoderFactory
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Empty Constructor.
|
||||
/// </summary>
|
||||
internal EncoderFactory()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method for determining the correct encoder for this
|
||||
/// encoding type.
|
||||
/// </summary>
|
||||
/// <param name="encodingtype">Enumerated encoding type</param>
|
||||
/// <returns>Returns the proper IEncoder implementation</returns>
|
||||
/// <exception cref="ApplicationException">Throws an ApplicationException if the specified encoding is unknown.</exception>
|
||||
public static IEncoder GetEncoder(EncodingType encodingtype)
|
||||
{
|
||||
if (encodingtype==EncodingType.Base64)
|
||||
{
|
||||
return Base64Encoder.GetInstance();
|
||||
}
|
||||
else if (encodingtype==EncodingType.QuotedPrintable)
|
||||
{
|
||||
return QPEncoder.GetInstance();
|
||||
}
|
||||
else if (encodingtype==EncodingType.SevenBit)
|
||||
{
|
||||
return SevenBitEncoder.GetInstance();
|
||||
}
|
||||
else if (encodingtype==EncodingType.EightBit)
|
||||
{
|
||||
return EightBitEncoder.GetInstance();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ApplicationException("This encoder type is not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration of encoding types.
|
||||
/// </summary>
|
||||
public enum EncodingType
|
||||
{
|
||||
/// <summary>
|
||||
/// The Quoted-Printable encoding
|
||||
/// </summary>
|
||||
QuotedPrintable,
|
||||
/// <summary>
|
||||
/// The Base-65 encoding
|
||||
/// </summary>
|
||||
Base64,
|
||||
/// <summary>
|
||||
/// The 7Bit encoding marker
|
||||
/// </summary>
|
||||
SevenBit,
|
||||
/// <summary>
|
||||
/// The 8Bit encoding marker
|
||||
/// </summary>
|
||||
EightBit
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface for a string encoder
|
||||
/// </summary>
|
||||
public interface IEncoder
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Encode from the stringreader to the stringwriter.
|
||||
/// </summary>
|
||||
/// <param name="source">an open stringreader to the source string</param>
|
||||
/// <param name="destination">where the output is written</param>
|
||||
/// <param name="charset">the outgoing charset</param>
|
||||
void Encode(StringReader source, StringWriter destination, System.Text.Encoding charset);
|
||||
|
||||
/// <summary>
|
||||
/// Encode the file stream into the stringwriter.
|
||||
/// </summary>
|
||||
/// <param name="filestream">an open stream to file to be read</param>
|
||||
/// <param name="destination">where the output is written</param>
|
||||
/// <param name="charset">the outgoing charset</param>
|
||||
void Encode(FileStream filestream, StringWriter destination, System.Text.Encoding charset);
|
||||
|
||||
/// <summary>
|
||||
/// Encode the binary reader into the stringwriter.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">an open binary reader for the data to be encoded.</param>
|
||||
/// <param name="destination">where the output is written</param>
|
||||
void Encode(BinaryReader binaryreader, StringWriter destination);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Encode the string according to rfc-2047 if some of it
|
||||
/// falls outside the 7bit ASCII charset.
|
||||
/// </summary>
|
||||
/// <param name="name">The header key</param>
|
||||
/// <param name="val">The header value string</param>
|
||||
/// <param name="charset">Charset for the encoded string</param>
|
||||
/// <param name="forceencoding">Force encoding, even if in ascii-only.</param>
|
||||
/// <returns>The encoded string</returns>
|
||||
String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding);
|
||||
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
String ContentTransferEncodingString {get;}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
//using log4net;
|
||||
|
||||
using DotNetOpenMail;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// See: http://www.freesoft.org/CIE/RFC/1521/6.htm
|
||||
/// </summary>
|
||||
public class QPEncoder : IEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Logger
|
||||
/// </summary>
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(QPEncoder));
|
||||
|
||||
/// <summary>
|
||||
/// Maximum characters per line, before the end-of-line character
|
||||
/// </summary>
|
||||
public static readonly int MAX_CHARS_PER_LINE=76;
|
||||
|
||||
/// <summary>
|
||||
/// The end-of-line character(s).
|
||||
/// </summary>
|
||||
public static readonly String END_OF_LINE="\r\n";
|
||||
|
||||
|
||||
#region QPEncoder
|
||||
/// <summary>
|
||||
/// Empty Constructor
|
||||
/// </summary>
|
||||
private QPEncoder()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInstance
|
||||
/// <summary>
|
||||
/// Create an instance of the encoder
|
||||
/// </summary>
|
||||
/// <returns>The instantiated Quoted-printable encoder</returns>
|
||||
public static QPEncoder GetInstance()
|
||||
{
|
||||
return new QPEncoder();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the incoming stream in quoted-printable encoding.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">The incoming binary reader</param>
|
||||
/// <param name="stringwriter">The outgoing string writer</param>
|
||||
public void Encode(BinaryReader binaryreader, StringWriter stringwriter)
|
||||
{
|
||||
throw new ApplicationException("Not Implemented Yet; use a base64 encoder instead.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the incoming stream in quoted-printable encoding.
|
||||
/// </summary>
|
||||
/// <param name="filestream">The incoming file stream</param>
|
||||
/// <param name="stringwriter">The outgoing string writer</param>
|
||||
/// <param name="charset">The charset to write the outgoing string in</param>
|
||||
public void Encode(FileStream filestream, StringWriter stringwriter, System.Text.Encoding charset)
|
||||
{
|
||||
throw new ApplicationException("Not Implemented Yet; use a base64 encoder instead.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the string read by the stringreader into the
|
||||
/// stringwriter. This implementation does not encode
|
||||
/// the characters where encoding is optional, and does
|
||||
/// not encode spaces or tabs (except at the end of a line).
|
||||
///
|
||||
/// Line breaks are converted to the RFC line break (CRLF).
|
||||
// The last linebreak is not included, if any, but this
|
||||
/// </summary>
|
||||
/// <param name="stringreader">The incoming string reader</param>
|
||||
/// <param name="stringwriter">The outgoing stringwriter</param>
|
||||
/// <param name="charset">The outgoing charset for the string</param>
|
||||
public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding charset)
|
||||
{
|
||||
Encode(stringreader, stringwriter, charset, false, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeString
|
||||
/// <summary>
|
||||
/// Encode the string in quoted printable format
|
||||
/// </summary>
|
||||
/// <param name="str">The source string</param>
|
||||
/// <param name="charset">The outgoing charset</param>
|
||||
/// <returns>the encoded string</returns>
|
||||
public String EncodeString(String str, System.Text.Encoding charset)
|
||||
{
|
||||
return EncodeString(str, charset, false, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeString
|
||||
/// <summary>
|
||||
/// Encode the string in quoted printable format
|
||||
/// </summary>
|
||||
/// <param name="sourceString">The source string</param>
|
||||
/// <param name="charset">The outgoing charset</param>
|
||||
/// <param name="forceRFC2047">Force encoding, even if not required by qp RFC</param>
|
||||
/// <param name="offset">The total characters outside the encoding. This is used to figure
|
||||
/// out how long the line will be after encoding.</param>
|
||||
/// <returns>the encoded string</returns>
|
||||
public String EncodeString(String sourceString, System.Text.Encoding charset, bool forceRFC2047, int offset)
|
||||
{
|
||||
|
||||
StringReader sr=new StringReader(sourceString);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
StringWriter sw=new StringWriter(sb);
|
||||
Encode(sr, sw, charset, forceRFC2047, offset);
|
||||
return sb.ToString();
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeHeaderString
|
||||
/// <summary>
|
||||
/// Encode header as per RFC 2047:
|
||||
/// http://www.faqs.org/rfcs/rfc2047.html
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>This doesn't split long lines yet</remarks>
|
||||
/// <param name="name">the header name</param>
|
||||
/// <param name="val">the string to encode</param>
|
||||
/// <param name="charset">The charset to encode to</param>
|
||||
/// <param name="forceencoding">Force encoding, even if not required by qp RFC</param>
|
||||
/// <returns>the encoded string, suitable for use in a header</returns>
|
||||
public String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding)
|
||||
{
|
||||
if (forceencoding || IsNonAscii(val))
|
||||
{
|
||||
|
||||
String start="=?"+charset.HeaderName+"?Q?";
|
||||
String end="?=";
|
||||
|
||||
int offset=name.Length+start.Length+end.Length+2; // the 2 is for the colon and space
|
||||
|
||||
String encodedtext=EncodeString(val, charset, true, offset);
|
||||
//log.Debug("LINE BEFORE SPLIT IS "+encodedtext);
|
||||
if (encodedtext.Length + offset > QPEncoder.MAX_CHARS_PER_LINE)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder("");
|
||||
foreach (String line in encodedtext.Split('\n'))
|
||||
{
|
||||
String tmp=line;
|
||||
if (sb.Length>0)
|
||||
{
|
||||
sb.Append(QPEncoder.END_OF_LINE+" ");
|
||||
}
|
||||
tmp=line.TrimEnd(new char[] {'\r', '='});
|
||||
//if (line.LastIndexOf("\r") == line.Length-1)
|
||||
//{
|
||||
//tmp=line.Substring(0, line.Length-1);
|
||||
//}
|
||||
sb.Append(start+tmp+end);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return start+encodedtext+end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return val;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeChar
|
||||
/// <summary>
|
||||
/// Encode a char according to quoted-printable
|
||||
/// standard
|
||||
/// </summary>
|
||||
/// <param name="ch">the char to encode</param>
|
||||
/// <returns>the encoded char representation</returns>
|
||||
private String EncodeChar(char ch)
|
||||
{
|
||||
int intch=(int) ch;
|
||||
if (intch > 255)
|
||||
{
|
||||
//log.Debug("encoding qp: "+String.Format("0x{0:X4}", intch));
|
||||
int ch1=intch >> 8;
|
||||
int ch2=intch & 0xff;
|
||||
return String.Format("={0:X2}={1:X2}", ch1, ch2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return String.Format("={0:X2}",(int) ch);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeByte
|
||||
/// <summary>
|
||||
/// Encode a byte according to quoted-printable
|
||||
/// standard
|
||||
/// </summary>
|
||||
/// <param name="ch">the byte to encode</param>
|
||||
/// <returns>the encoded byte representation</returns>
|
||||
private String EncodeByte(byte ch)
|
||||
{
|
||||
return String.Format("={0:X2}",(int) ch);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public String ContentTransferEncodingString
|
||||
{
|
||||
get {return "quoted-printable";}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NeedsEncoding
|
||||
/// <summary>
|
||||
/// Return true if the char needs to be encoded.
|
||||
/// </summary>
|
||||
/// <param name="ch"></param>
|
||||
/// <param name="forceRFC2047"></param>
|
||||
/// <returns></returns>
|
||||
internal bool NeedsEncoding(char ch, bool forceRFC2047)
|
||||
{
|
||||
if ((ch <= 0x1f && ch != 0x09) || // less than space (except tab)
|
||||
ch == 0x3d || // equal sign
|
||||
ch>= 0x7f // above 7bit
|
||||
|| (forceRFC2047 && (ch==0x20 || ch==0x09 || ch==0x3f))
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NeedsEncoding
|
||||
/// <summary>
|
||||
/// Return true if the byte needs to be encoded.
|
||||
/// </summary>
|
||||
/// <param name="ch"></param>
|
||||
/// <param name="forceRFC2047"></param>
|
||||
/// <returns></returns>
|
||||
internal bool NeedsEncoding(byte ch, bool forceRFC2047)
|
||||
{
|
||||
if ((ch <= 0x1f && ch != 0x09) || // less than space (except tab)
|
||||
ch == 0x3d || // equal sign
|
||||
ch>= 0x7f // above 7bit
|
||||
|| (forceRFC2047 && (ch==0x20 || ch==0x09 || ch==0x3f))
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsNonAscii
|
||||
/// <summary>
|
||||
/// Return true if the string needs to be encoded.
|
||||
/// </summary>
|
||||
/// <param name="str">The string to check</param>
|
||||
/// <returns>true if outside 127-bit, or one of the
|
||||
/// quoted-printable special characters.</returns>
|
||||
internal bool IsNonAscii(String str)
|
||||
{
|
||||
for (int i=0; i<str.Length; i++)
|
||||
{
|
||||
if (IsNonAscii(str[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsNonAscii
|
||||
/// <summary>
|
||||
/// Check if the character is one of the non-qp
|
||||
/// characters
|
||||
/// </summary>
|
||||
/// <param name="ch">the character to check</param>
|
||||
/// <returns>true if outside the acceptable qp range</returns>
|
||||
internal bool IsNonAscii(char ch)
|
||||
{
|
||||
if ((ch <= 0x1f && ch != 0x09) || // less than space (except tab)
|
||||
ch == 0x3d || // equal sign
|
||||
ch>= 0x7f // above 7bit
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the string read by the stringreader into the
|
||||
/// stringwriter. This implementation does not encode
|
||||
/// the characters where encoding is optional, and does
|
||||
/// not encode spaces or tabs (except at the end of a line).
|
||||
///
|
||||
/// Line breaks are converted to the RFC line break (CRLF).
|
||||
// The last linebreak is not included, if any---although this
|
||||
/// may change in the future.
|
||||
/// </summary>
|
||||
/// <param name="stringreader">The incoming string reader</param>
|
||||
/// <param name="stringwriter">The outgoing stringwriter</param>
|
||||
/// <param name="charset">The outgoing charset for the string</param>
|
||||
/// <param name="forceRFC2047">If true, force the encoding of all the
|
||||
/// <param name="offset">These are the number of characters that
|
||||
/// will appear outside this string, e.g. the header name, etc.</param>
|
||||
/// characters (not just those that are given in RFC2027).</param>
|
||||
public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding charset, bool forceRFC2047, int offset)
|
||||
{
|
||||
if (offset > QPEncoder.MAX_CHARS_PER_LINE - 15)
|
||||
{
|
||||
throw new MailException("Invalid offset (header name is too long): "+offset);
|
||||
}
|
||||
|
||||
String line=null;
|
||||
|
||||
bool forceencoding=false;
|
||||
if (charset==null)
|
||||
{
|
||||
charset=Utils.Configuration.GetInstance().GetDefaultCharset();
|
||||
}
|
||||
while((line=stringreader.ReadLine())!=null)
|
||||
{
|
||||
int columnposition=0;
|
||||
|
||||
byte[] bytes=charset.GetBytes(line);
|
||||
|
||||
// see Rule #3 (spaces and tabs at end of line are encoded)
|
||||
StringBuilder blankendchars=new StringBuilder("");
|
||||
|
||||
int endpos=bytes.Length-1;
|
||||
|
||||
while (endpos >=0 && (bytes[endpos]==0x20 || bytes[endpos]==0x09) )
|
||||
{
|
||||
blankendchars.Insert(blankendchars.Length, EncodeByte(bytes[endpos]));
|
||||
endpos--;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<=endpos; i++)
|
||||
{
|
||||
String towrite="";
|
||||
if (forceencoding || NeedsEncoding(bytes[i], forceRFC2047))
|
||||
{
|
||||
columnposition+=3;
|
||||
towrite=EncodeByte(bytes[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
columnposition+=1;
|
||||
// this is a single byte, so multibyte chars won't
|
||||
// be affected by this.
|
||||
towrite=charset.GetString(new byte[]{bytes[i]});
|
||||
}
|
||||
|
||||
if (offset + columnposition > QPEncoder.MAX_CHARS_PER_LINE )
|
||||
{
|
||||
stringwriter.Write("="+QPEncoder.END_OF_LINE);
|
||||
columnposition=0;
|
||||
}
|
||||
stringwriter.Write(towrite);
|
||||
}
|
||||
|
||||
if (blankendchars.Length > 0)
|
||||
{
|
||||
if (offset+columnposition+blankendchars.Length > QPEncoder.MAX_CHARS_PER_LINE)
|
||||
{
|
||||
stringwriter.Write("="+QPEncoder.END_OF_LINE);
|
||||
}
|
||||
stringwriter.Write(blankendchars);
|
||||
}
|
||||
if (stringreader.Peek() >= 0)
|
||||
{
|
||||
stringwriter.Write("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Denotes 7bit encoding. Note that this doesn't really
|
||||
/// encode anything; it just specifies that this email is already
|
||||
/// in 7-bit ascii encoding.
|
||||
/// </summary>
|
||||
public class SevenBitEncoder : DoNothingEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
private SevenBitEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of this class.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SevenBitEncoder GetInstance()
|
||||
{
|
||||
return new SevenBitEncoder();
|
||||
}
|
||||
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public override String ContentTransferEncodingString
|
||||
{
|
||||
get {return "7bit";}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
//using log4net;
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A mime representation of a file which can be transferred
|
||||
/// via email.
|
||||
/// </summary>
|
||||
public class FileAttachment : AbstractEmailAttachment
|
||||
{
|
||||
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(FileAttachment));
|
||||
|
||||
/// <summary>
|
||||
/// Create a new File attachment from a FileInfo object
|
||||
/// </summary>
|
||||
/// <param name="fileinfo">A fileinfo object which points to a local file.</param>
|
||||
public FileAttachment(FileInfo fileinfo) : this(fileinfo, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new text file attachment from a StreamReader.
|
||||
/// </summary>
|
||||
/// <param name="streamreader">An open streamreader</param>
|
||||
public FileAttachment(StreamReader streamreader) : this(streamreader, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new binary file attachment from a BinaryReader.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">An open binaryreader</param>
|
||||
public FileAttachment(BinaryReader binaryreader) : this(binaryreader, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new binary file attachment from an array of bytes.
|
||||
/// </summary>
|
||||
/// <param name="bytes">An array of bytes</param>
|
||||
public FileAttachment(byte[] bytes) : this(bytes, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new file attachment from a String.
|
||||
/// </summary>
|
||||
/// <param name="content">The contents of the file</param>
|
||||
public FileAttachment(String content) : this(content, null)
|
||||
{
|
||||
}
|
||||
|
||||
#region FileAttachment
|
||||
/// <summary>
|
||||
/// Create a new File attachment with a contentid from a FileInfo object.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="fileinfo">A fileinfo object which points to a local file.</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(FileInfo fileinfo, String contentid)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
if (FileName==null)
|
||||
{
|
||||
FileName=fileinfo.Name;
|
||||
}
|
||||
this._fileinfo=fileinfo;
|
||||
this._contentid=contentid;
|
||||
this.CharSet=null;
|
||||
//this.Contents=contents;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
//this.Encoder=EncoderFactory.GetEncoder(EncoderFactory.GetEncoder(EncodingType);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileAttachment
|
||||
/// <summary>
|
||||
/// Create a new file attachment from a StreamReader.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="streamreader">An open streamreader</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(StreamReader streamreader, String contentid)
|
||||
{
|
||||
if (this.ContentType==null)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
}
|
||||
String tmp=streamreader.ReadToEnd();
|
||||
streamreader.Close();
|
||||
this.Contents=tmp;
|
||||
this.CharSet=null;
|
||||
this._contentid=contentid;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileAttachment
|
||||
/// <summary>
|
||||
/// Create a new file attachment from a BinaryReader.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">An open binary readerr</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(BinaryReader binaryreader, String contentid)
|
||||
{
|
||||
if (this.ContentType==null)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
}
|
||||
|
||||
this._contentbytes=Utils.BinaryReaderUtil.ReadIntoByteArray(binaryreader);
|
||||
binaryreader.Close();
|
||||
this.CharSet=null;
|
||||
this._contentid=contentid;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileAttachment
|
||||
/// <summary>
|
||||
/// Create a new file attachment from a byte array.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="bytes">An array of bytes</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(byte[] bytes, String contentid)
|
||||
{
|
||||
if (this.ContentType==null)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
}
|
||||
this.ContentBytes=bytes;
|
||||
this.CharSet=null;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Create a new text file attachment from a String.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="content">The contents of the file</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(String content, String contentid)
|
||||
{
|
||||
if (this.ContentType==null)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
}
|
||||
this.Contents=content;
|
||||
this.CharSet=null;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
this._contentid=contentid;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using DotNetOpenMail.Encoding;
|
||||
using DotNetOpenMail.Utils;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// An HTML email attachment
|
||||
/// </summary>
|
||||
public class HtmlAttachment : AbstractEmailAttachment
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Create a new HTML Attachment. It flags the content/type
|
||||
/// as "text/html", uses Quoted Printable encoding by
|
||||
/// default, and uses the default character set, which is
|
||||
/// ISO-8859-1 unless otherwise specified in the .config file.
|
||||
/// </summary>
|
||||
/// <param name="contents">The HTML content of the attachment</param>
|
||||
public HtmlAttachment(String contents)
|
||||
{
|
||||
this.ContentType="text/html";
|
||||
this.Contents=contents;
|
||||
this.CharSet=System.Text.Encoding.GetEncoding(Configuration.GetInstance().GetDefaultEncoding("iso-8859-1"));
|
||||
this.Encoding=EncodingType.QuotedPrintable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// Objects of a class which implements this interface
|
||||
/// can be converted to a string which can be used in
|
||||
/// an email.
|
||||
/// </summary>
|
||||
internal interface IEmailStringable
|
||||
{
|
||||
String ToDataString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A message which can be sent.
|
||||
/// </summary>
|
||||
internal interface ISendableMessage : IEmailStringable
|
||||
{
|
||||
bool Send(SmtpServer smtpserver);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
//using log4net;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// Interact directly with the SMTP server.
|
||||
/// </summary>
|
||||
public interface ISmtpProxy
|
||||
{
|
||||
/// <summary>
|
||||
/// Open the connection
|
||||
/// </summary>
|
||||
/// <returns>The SMTP response</returns>
|
||||
SmtpResponse Open();
|
||||
|
||||
/// <summary>
|
||||
/// Send the HELO command
|
||||
/// </summary>
|
||||
/// <param name="localHostName"></param>
|
||||
/// <returns></returns>
|
||||
SmtpResponse Helo(String localHostName);
|
||||
|
||||
/// <summary>
|
||||
/// Send the EHLO command
|
||||
/// </summary>
|
||||
/// <param name="localHostName"></param>
|
||||
/// <returns></returns>
|
||||
EhloSmtpResponse Ehlo(String localHostName);
|
||||
|
||||
/// <summary>
|
||||
/// Send the MAIL FROM command
|
||||
/// </summary>
|
||||
/// <param name="mailfrom"></param>
|
||||
/// <returns></returns>
|
||||
SmtpResponse MailFrom(EmailAddress mailfrom);
|
||||
|
||||
/// <summary>
|
||||
/// Send one RCPT TO command
|
||||
/// </summary>
|
||||
/// <param name="rcptto"></param>
|
||||
/// <returns></returns>
|
||||
SmtpResponse RcptTo(EmailAddress rcptto);
|
||||
|
||||
/// <summary>
|
||||
/// Send the DATA command
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
SmtpResponse Data();
|
||||
|
||||
/// <summary>
|
||||
/// Write the message content
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
SmtpResponse WriteData(String str);
|
||||
|
||||
/// <summary>
|
||||
/// Send the QUIT message to the server
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
SmtpResponse Quit();
|
||||
|
||||
/// <summary>
|
||||
/// Close the connection
|
||||
/// </summary>
|
||||
/// <returns>The SMTP response</returns>
|
||||
void Close();
|
||||
|
||||
/// <summary>
|
||||
/// Send the AUTH command
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
SmtpResponse Auth(String authtype);
|
||||
|
||||
/// <summary>
|
||||
/// Send any old string to the proxy
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
SmtpResponse SendString(String str);
|
||||
|
||||
/// <summary>
|
||||
/// Turn the SMTP Conversation Capture off/on.
|
||||
/// If on, GetSmtpConversation will contain the
|
||||
/// most recent conversation.
|
||||
/// </summary>
|
||||
/// <returns>the on/off value</returns>
|
||||
bool CaptureSmtpConversation {get; set;}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for LogMessage.
|
||||
/// </summary>
|
||||
public class LogMessage
|
||||
{
|
||||
private Object _sender=null;
|
||||
private String _message=null;
|
||||
|
||||
/// <summary>
|
||||
/// The log message
|
||||
/// </summary>
|
||||
public String Message
|
||||
{
|
||||
get {return _message;}
|
||||
set {_message=value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The sender object
|
||||
/// </summary>
|
||||
public Object Sender
|
||||
{
|
||||
get {return _sender;}
|
||||
set {_sender=value;}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Log a message
|
||||
/// </summary>
|
||||
/// <param name="sender">The object logging the message</param>
|
||||
/// <param name="message">The message to be logged</param>
|
||||
public LogMessage(Object sender, String message)
|
||||
{
|
||||
this._sender=sender;
|
||||
this._message=message;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Logger.
|
||||
/// </summary>
|
||||
public class Logger
|
||||
{
|
||||
/// <summary>
|
||||
/// Log handler delegate
|
||||
/// </summary>
|
||||
public delegate void LogHandler(LogMessage logMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Log event
|
||||
/// </summary>
|
||||
//public event LogHandler LogEvent;
|
||||
|
||||
private static Logger _logger=new Logger();
|
||||
|
||||
private Logger()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the singleton object
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Logger GetInstance()
|
||||
{
|
||||
return _logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a message with level "Info"
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void LogInfo(String message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a message with level "Debug"
|
||||
/// </summary>
|
||||
public void LogDebug(String message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a message with level "Error"
|
||||
/// </summary>
|
||||
public void LogError(String message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log the output of sending smtp
|
||||
/// </summary>
|
||||
public void LogWriteSMTP(String message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log the reply via smtp
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void LogReceiveSMTP(String message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// General Mail Exception, including network errors,
|
||||
/// connection errors, and configuration errors.
|
||||
/// </summary>
|
||||
public class MailException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an instance of a MailException
|
||||
/// </summary>
|
||||
public MailException() : base()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Create an instance of a MailException
|
||||
/// </summary>
|
||||
/// <param name="message">The message describing the exception</param>
|
||||
public MailException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of a MailException
|
||||
/// </summary>
|
||||
/// <param name="message">The message describing the exception</param>
|
||||
/// <param name="inner">The inner exception</param>
|
||||
public MailException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents one of the message headers as it
|
||||
/// appears in the email.
|
||||
/// </summary>
|
||||
public class MessageHeader : IEmailStringable
|
||||
{
|
||||
private String _name;
|
||||
private String _value;
|
||||
private String _encodedvalue=null;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of a MessageHeader
|
||||
/// </summary>
|
||||
/// <param name="name">The header name (without a colon)</param>
|
||||
/// <param name="value">The unencoded value</param>
|
||||
public MessageHeader(string name, String value)
|
||||
{
|
||||
this._name=name;
|
||||
this._value=value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of a MessageHeader, with a mime-encoded
|
||||
/// value.
|
||||
/// </summary>
|
||||
/// <param name="name">The header name (without a colon)</param>
|
||||
/// <param name="value">The non-encoded header value</param>
|
||||
/// <param name="encodedvalue">The mime-encoded value</param>
|
||||
public MessageHeader(string name, String value, String encodedvalue)
|
||||
{
|
||||
this._name=name;
|
||||
this._value=value;
|
||||
this._encodedvalue=encodedvalue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the header.
|
||||
/// </summary>
|
||||
public String Name
|
||||
{
|
||||
get {return this._name;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The unencoded value of the header
|
||||
/// </summary>
|
||||
public String Value
|
||||
{
|
||||
get {return this._value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The mime-encoded value of the header
|
||||
/// </summary>
|
||||
public String EncodedValue
|
||||
{
|
||||
get {return this._encodedvalue;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The string representation of the header, as it will
|
||||
/// appear in the email.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
if (_encodedvalue!=null)
|
||||
{
|
||||
return Name+": "+EncodedValue+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Name+": "+Value+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of MessageHeader objects
|
||||
/// Implements the CollectionBase interface.
|
||||
/// </summary>
|
||||
public class MessageHeaderCollection : CollectionBase, IEmailStringable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ArrayList class.
|
||||
/// </summary>
|
||||
public MessageHeaderCollection()
|
||||
{
|
||||
}
|
||||
|
||||
#region Add
|
||||
/// <summary>
|
||||
/// Adds an object to the end of the MessageHeaderCollection
|
||||
/// </summary>
|
||||
/// <param name="MessageHeader">The Object to be added to the end of the MessageHeaderCollection.
|
||||
/// The value can be a null reference (Nothing in Visual Basic). </param>
|
||||
/// <returns>The MessageHeaderCollection index at which the value has been added.</returns>
|
||||
public int Add( MessageHeader MessageHeader )
|
||||
{
|
||||
return( List.Add( MessageHeader ) );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IndexOf
|
||||
/// <summary>
|
||||
/// Returns the zero-based index of the first occurrence of a
|
||||
/// value in the MessageHeaderCollection or in a portion of it.
|
||||
/// </summary>
|
||||
/// <param name="value">The Object to locate in the MessageHeaderCollection. The value
|
||||
/// can be a null reference (Nothing in Visual Basic). </param>
|
||||
/// <returns></returns>
|
||||
public int IndexOf( MessageHeader value )
|
||||
{
|
||||
return( List.IndexOf( value ) );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
/// <summary>
|
||||
/// Inserts an element into the MessageHeaderCollection at
|
||||
/// the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which value should be inserted</param>
|
||||
/// <param name="MessageHeader">The MessageHeader to insert.
|
||||
/// The value can be a null reference (Nothing in Visual Basic). </param>
|
||||
public void Insert( int index, MessageHeader MessageHeader )
|
||||
{
|
||||
List.Insert( index, MessageHeader );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Remove
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of a
|
||||
/// specific MessageHeader from the MessageHeaderCollection.
|
||||
/// </summary>
|
||||
/// <param name="MessageHeader">The object to remove from the MessageHeaderCollection</param>
|
||||
public void Remove( MessageHeader MessageHeader )
|
||||
{
|
||||
List.Remove( MessageHeader );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Write the MessageHeaderCollection to a string that can be
|
||||
/// included in an email.
|
||||
/// </summary>
|
||||
/// <returns>The String as it will appear in the resulting email.</returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder("");
|
||||
foreach (MessageHeader messageheader in List)
|
||||
{
|
||||
sb.Append(messageheader.ToDataString());
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A boundary which delimits a MIME object.
|
||||
/// </summary>
|
||||
internal class MimeBoundary
|
||||
{
|
||||
protected static readonly String MimeChars="abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
private String _theboundary=null;
|
||||
private static Random random=new Random();
|
||||
|
||||
public MimeBoundary()
|
||||
{
|
||||
_theboundary=MakeMimeBoundary();
|
||||
}
|
||||
|
||||
public String BoundaryString
|
||||
{
|
||||
get
|
||||
{
|
||||
return _theboundary;
|
||||
}
|
||||
}
|
||||
|
||||
public String BoundaryStringStart
|
||||
{
|
||||
get
|
||||
{
|
||||
return "--"+_theboundary;
|
||||
}
|
||||
}
|
||||
|
||||
public String BoundaryStringEnd
|
||||
{
|
||||
get
|
||||
{
|
||||
return "--"+_theboundary+"--";
|
||||
}
|
||||
}
|
||||
|
||||
private String MakeMimeBoundary()
|
||||
{
|
||||
int mimelength=32;
|
||||
StringBuilder sb=new StringBuilder();
|
||||
for (int i=0; i<MimeBoundary.MimeChars.Length; i++)
|
||||
{
|
||||
sb.Append(MimeChars[random.Next(mimelength)]);
|
||||
|
||||
}
|
||||
return "_=DotNetOpenMail=_"+sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A MIME container for content or other mime containers.
|
||||
/// </summary>
|
||||
internal class MimeContainer : IEmailStringable
|
||||
{
|
||||
private MimeBoundary _mimeboundary=null;
|
||||
private ArrayList _attachments=new ArrayList();
|
||||
private ArrayList _mimecontainers=new ArrayList();
|
||||
private String _contenttype=null;
|
||||
private bool _istoplevel=true;
|
||||
|
||||
public MimeContainer(MimeBoundary mimeboundary, String contenttype, bool istoplevel)
|
||||
{
|
||||
this._mimeboundary=mimeboundary;
|
||||
this._contenttype=contenttype;
|
||||
this._istoplevel=istoplevel;
|
||||
}
|
||||
|
||||
public void AddAttachment(AbstractEmailAttachment attachment)
|
||||
{
|
||||
_attachments.Add(attachment);
|
||||
}
|
||||
|
||||
public void AddMimeContainer(MimeContainer mimecontainer)
|
||||
{
|
||||
_mimecontainers.Add(mimecontainer);
|
||||
}
|
||||
|
||||
private void WriteHeader(StringBuilder sb)
|
||||
{
|
||||
sb.Append("Content-Type: "+_contenttype+";"+SmtpProxy.ENDOFLINE);
|
||||
sb.Append(" boundary=\""+_mimeboundary.BoundaryString+"\""+SmtpProxy.ENDOFLINE+SmtpProxy.ENDOFLINE);
|
||||
//sb.Append(_mimeboundary.BoundaryStringStart+SmtpProxy.ENDOFLINE);
|
||||
|
||||
}
|
||||
|
||||
public String ToDataString()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
bool hasheader=false;
|
||||
if (!_istoplevel)
|
||||
{
|
||||
WriteHeader(sb);
|
||||
}
|
||||
foreach (MimeContainer mimecontainer in _mimecontainers)
|
||||
{
|
||||
hasheader=true;
|
||||
sb.Append(_mimeboundary.BoundaryStringStart+SmtpProxy.ENDOFLINE);
|
||||
sb.Append(mimecontainer.ToDataString());
|
||||
//sb.Append(_mimeboundary.BoundaryStringEnd);
|
||||
}
|
||||
foreach (AbstractEmailAttachment attachment in _attachments)
|
||||
{
|
||||
hasheader=true;
|
||||
sb.Append(_mimeboundary.BoundaryStringStart+SmtpProxy.ENDOFLINE);
|
||||
sb.Append(attachment.ToDataString());
|
||||
//sb.Append(_mimeboundary.BoundaryStringEnd);
|
||||
}
|
||||
if (hasheader)
|
||||
{
|
||||
sb.Append(_mimeboundary.BoundaryStringEnd+SmtpProxy.ENDOFLINE+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a RFC 2822-compliant date.
|
||||
///
|
||||
/// See section 3.3 in
|
||||
/// http://ftp.rfc-editor.org/in-notes/rfc2822.txt
|
||||
/// </summary>
|
||||
public class RFC2822Date
|
||||
{
|
||||
private DateTime _datetime;
|
||||
private TimeZone _timezone;
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the RFC 2822 date object.
|
||||
/// </summary>
|
||||
/// <param name="datetime">The date to convert</param>
|
||||
/// <param name="timezone">The timezone to use in the conversion</param>
|
||||
public RFC2822Date(DateTime datetime, TimeZone timezone)
|
||||
{
|
||||
this._datetime=datetime;
|
||||
this._timezone=timezone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the date string
|
||||
/// </summary>
|
||||
/// <returns>A RFC-2822 error code</returns>
|
||||
public override String ToString()
|
||||
{
|
||||
TimeZone current=TimeZone.CurrentTimeZone;
|
||||
|
||||
TimeSpan timespan=current.GetUtcOffset(_datetime);
|
||||
String tz=String.Format("{0:00}{1:00}", timespan.Hours, Math.Abs(timespan.Minutes %60));
|
||||
if (timespan.TotalHours >= 0)
|
||||
{
|
||||
tz="+"+tz;
|
||||
}
|
||||
// Note: fixed for non-English default cultures; thanks, Angel Marin
|
||||
return _datetime.ToString("ddd, d MMM yyyy HH:mm:ss "+tz, System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A full, preformatted email message, including headers
|
||||
/// </summary>
|
||||
public class RawEmailMessage : ISendableMessage
|
||||
{
|
||||
private String _content=null;
|
||||
private EmailAddressCollection _rcpttoaddresses=new EmailAddressCollection();
|
||||
private EmailAddress _mailfrom=null;
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the RawEmailMessage
|
||||
/// </summary>
|
||||
public RawEmailMessage()
|
||||
{
|
||||
}
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// The raw content of the email
|
||||
/// </summary>
|
||||
public String Content
|
||||
{
|
||||
get { return _content; }
|
||||
set { _content = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MailFrom
|
||||
/// <summary>
|
||||
/// The address to use in the envelope-from
|
||||
/// SMTP negotiation
|
||||
/// </summary>
|
||||
public EmailAddress MailFrom
|
||||
{
|
||||
get { return _mailfrom; }
|
||||
set { _mailfrom = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RcptToAddresses
|
||||
/// <summary>
|
||||
/// The recipient addresses
|
||||
/// </summary>
|
||||
public EmailAddressCollection RcptToAddresses
|
||||
{
|
||||
get { return _rcpttoaddresses; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddRcptToAddress
|
||||
/// <summary>
|
||||
/// Add a recipient to the EmailAddressCollection
|
||||
/// of recipients
|
||||
/// </summary>
|
||||
/// <param name="emailaddress"></param>
|
||||
public void AddRcptToAddress(EmailAddress emailaddress)
|
||||
{
|
||||
_rcpttoaddresses.Add(emailaddress);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
/// <summary>
|
||||
/// Send the email via the specified SMTP server
|
||||
/// </summary>
|
||||
/// <param name="smtpserver">The SMTP server to use</param>
|
||||
/// <returns>true if the email was sent</returns>
|
||||
public bool Send(SmtpServer smtpserver)
|
||||
{
|
||||
// smtpproxy=SmtpProxy.GetInstance(smtpserver);
|
||||
if (_rcpttoaddresses.Count==0)
|
||||
{
|
||||
throw new MailException("Please include a RCPT TO address");
|
||||
}
|
||||
if (_mailfrom==null)
|
||||
{
|
||||
throw new MailException("Please include a MAIL FROM address");
|
||||
}
|
||||
return smtpserver.Send(this, _rcpttoaddresses, _mailfrom);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Render the message for smtp "DATA" transmission.
|
||||
/// </summary>
|
||||
/// <returns>The rendered String, which in this
|
||||
/// case is the content itself, untouched.</returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
return _content;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
namespace DotNetOpenMail.Resources
|
||||
{
|
||||
/// <summary>
|
||||
/// ARM= Assembly Resource Manager. Manage the strings for the
|
||||
/// various CultureInfo types.
|
||||
/// </summary>
|
||||
public sealed class ARM
|
||||
{
|
||||
/// <summary>
|
||||
/// The singleton object
|
||||
/// </summary>
|
||||
private static ARM _theinstance=new ARM();
|
||||
/// <summary>
|
||||
/// The namespace of the resource files
|
||||
/// </summary>
|
||||
private string _pathname="DotNetOpenMail.Resources.DotNetOpenMail";
|
||||
/// <summary>
|
||||
/// The singleton System.Resources.ResourceManager.
|
||||
/// </summary>
|
||||
private ResourceManager _resources=null;
|
||||
|
||||
/// <summary>
|
||||
/// Create the singleton
|
||||
/// </summary>
|
||||
private ARM()
|
||||
{
|
||||
_resources=new ResourceManager(_pathname, typeof(ARM).Assembly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the instance of the class
|
||||
/// </summary>
|
||||
/// <returns>the ARM instance</returns>
|
||||
public static ARM GetInstance()
|
||||
{
|
||||
return _theinstance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an object from the file
|
||||
/// </summary>
|
||||
/// <param name="name">The key</param>
|
||||
/// <returns>The key lookup for the default culture</returns>
|
||||
public object GetObject(string name)
|
||||
{
|
||||
return GetObject(null, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an object for the specified CultureInfo
|
||||
/// </summary>
|
||||
/// <param name="culture">The specified culture for the resource</param>
|
||||
/// <param name="name">The key for the resource</param>
|
||||
/// <returns>returns an object, if one is found, else null</returns>
|
||||
public object GetObject(CultureInfo culture, string name)
|
||||
{
|
||||
if (_resources != null)
|
||||
{
|
||||
return _resources.GetObject(name, culture);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string for the specified CultureInfo for the
|
||||
/// default culture
|
||||
/// </summary>
|
||||
/// <param name="name">The key for the resource</param>
|
||||
/// <returns>returns a string, if one is found, else null</returns>
|
||||
public string GetString(string name)
|
||||
{
|
||||
return GetString(null, name, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string for the specified CultureInfo for the
|
||||
/// default culture. If not found, return defaultvalue
|
||||
/// </summary>
|
||||
/// <param name="name">The key for the resource</param>
|
||||
/// <param name="defaultvalue">The value to return if there
|
||||
/// is no value found.</param>
|
||||
/// <returns>returns a string, if one is found, else defaultvalue</returns>
|
||||
public string GetString(string name, string defaultvalue)
|
||||
{
|
||||
return GetString(null, name, defaultvalue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string for the specified CultureInfo for the
|
||||
/// current culture. If not found, return null
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture of the resulting string</param>
|
||||
/// <param name="name">The key for the resource</param>
|
||||
/// <returns>returns a string, if one is found, else
|
||||
/// null</returns>
|
||||
public string GetString(CultureInfo culture, string name)
|
||||
{
|
||||
return GetString(culture, name, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string for the specified CultureInfo for the
|
||||
/// default culture. If not found, return defaultvalue
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture of the resulting string</param>
|
||||
/// <param name="name">The key for the resource</param>
|
||||
/// <param name="defaultvalue">The value to return if there
|
||||
/// is no value found.</param>
|
||||
/// <returns>returns a string, if one is found, else defaultvalue</returns>
|
||||
public string GetString(CultureInfo culture, string name, string defaultvalue)
|
||||
{
|
||||
if (_resources != null)
|
||||
{
|
||||
String result=_resources.GetString(name, culture);
|
||||
if (result==null)
|
||||
{
|
||||
return defaultvalue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
throw new ApplicationException("The Resources are uninitialized");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the entire resource set for this culture.
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture to examine</param>
|
||||
/// <returns>The resource set, if any.</returns>
|
||||
public ResourceSet GetResourceSet(CultureInfo culture)
|
||||
{
|
||||
return _resources.GetResourceSet(culture, false, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="ResMimeType">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="Version">
|
||||
<value>1.0.0.0</value>
|
||||
</resheader>
|
||||
<resheader name="Reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="Writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="no_subject">
|
||||
<value>(no subject)</value>
|
||||
</data>
|
||||
<data name="this_is_mime">
|
||||
<value>This is a multi-part message in MIME format</value>
|
||||
</data>
|
||||
<data name="unrecognized_auth_type">
|
||||
<value>Unrecognized authentication type</value>
|
||||
</data>
|
||||
<data name="error_no_from">
|
||||
<value>Please include a MAIL FROM address.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.SmtpAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for ISmtpAuthenticationToken.
|
||||
/// </summary>
|
||||
public interface ISmtpAuthToken
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The user's login
|
||||
/// </summary>
|
||||
String UserName
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The user's password
|
||||
/// </summary>
|
||||
String Password
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Negotiate AUTH with the SmtpProxy.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
SmtpResponse Negotiate(ISmtpProxy smtpProxy, String[] supportedAuthTypes);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
//using log4net;
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail.SmtpAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// A LOCAL SMTP AUTH token
|
||||
/// </summary>
|
||||
public class LoginAuthToken : ISmtpAuthToken
|
||||
{
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(LoginAuthToken));
|
||||
private String _userName;
|
||||
private String _password;
|
||||
private System.Text.Encoding _charEncoding=System.Text.Encoding.GetEncoding("iso-8859-1");
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of the LOCAL SMTP
|
||||
/// AUTH token
|
||||
/// </summary>
|
||||
public LoginAuthToken(String userName, String password)
|
||||
{
|
||||
this._userName=userName;
|
||||
this._password=password;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The User's password
|
||||
/// </summary>
|
||||
public String Password
|
||||
{
|
||||
get {return _password;}
|
||||
set {_password=value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The User's login
|
||||
/// </summary>
|
||||
public String UserName
|
||||
{
|
||||
get {return _userName;}
|
||||
set {_userName=value;}
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Return true if this is among the supported AUTH
|
||||
/// types.
|
||||
/// </summary>
|
||||
/// <param name="authtypes"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsSupported(SmtpAuthType[] authtypes)
|
||||
{
|
||||
log.Debug("CHECKING SUPPORTED TYPES");
|
||||
for (int i=0; i<authtypes.Length; i++)
|
||||
{
|
||||
log.Debug("CHECKING IF "+authtypes[i]+"="+SmtpAuthType.Login);
|
||||
if (authtypes[i]==SmtpAuthType.Login)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Return the 235 response code if valid, otherwise
|
||||
/// return the error.
|
||||
/// </summary>
|
||||
/// <param name="smtpProxy"></param>
|
||||
/// <param name="supportedAuthTypes">the supported auth types</param>
|
||||
/// <returns></returns>
|
||||
public SmtpResponse Negotiate(ISmtpProxy smtpProxy, String[] supportedAuthTypes)
|
||||
{
|
||||
SmtpResponse response=smtpProxy.Auth("login");
|
||||
//log.Debug("RESPONSE WAS "+response.ResponseCode+" "+response.Message);
|
||||
if (response.ResponseCode!=334)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
Base64Encoder encoder=Base64Encoder.GetInstance();
|
||||
response=smtpProxy.SendString(encoder.EncodeString(this.UserName, this._charEncoding ));
|
||||
if (response.ResponseCode!=334)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
response=smtpProxy.SendString(encoder.EncodeString(this.Password, this._charEncoding ));
|
||||
if (response.ResponseCode!=334)
|
||||
{
|
||||
// here it's an error
|
||||
return response;
|
||||
}
|
||||
else
|
||||
{
|
||||
// here it's ok.
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
//using log4net;
|
||||
|
||||
namespace DotNetOpenMail.SmtpAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for SmtpAuthHelper.
|
||||
/// </summary>
|
||||
internal class SmtpAuthFactory
|
||||
{
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(SmtpAuthFactory));
|
||||
|
||||
internal SmtpAuthFactory()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Auth type from the SMTP EHLO response.
|
||||
/// If it is unrecognized or unimplemented,
|
||||
/// return null. Case doesn't matter.
|
||||
/// </summary>
|
||||
/// <param name="authType">The string as returned in EHLO negotiation.</param>
|
||||
/// <param name="username">The user's login</param>
|
||||
/// <param name="password">The User's password</param>
|
||||
internal static ISmtpAuthToken GetAuthTokenFromString(String authType, String username, String password)
|
||||
{
|
||||
authType=authType.ToLower().Trim();
|
||||
|
||||
if (authType.Equals("login"))
|
||||
{
|
||||
return new LoginAuthToken(username, password);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
//using log4net;
|
||||
|
||||
namespace DotNetOpenMail.SmtpAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Token which will negotiate an authentication type
|
||||
/// with the server.
|
||||
/// </summary>
|
||||
public class SmtpAuthToken : ISmtpAuthToken
|
||||
{
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(SmtpAuthToken));
|
||||
private String _userName;
|
||||
private String _password;
|
||||
private System.Text.Encoding _charEncoding=System.Text.Encoding.GetEncoding("iso-8859-1");
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of the LOCAL SMTP
|
||||
/// AUTH token
|
||||
/// </summary>
|
||||
public SmtpAuthToken(String userName, String password)
|
||||
{
|
||||
this._userName=userName;
|
||||
this._password=password;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The User's password
|
||||
/// </summary>
|
||||
public String Password
|
||||
{
|
||||
get {return _password;}
|
||||
set {_password=value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The User's login
|
||||
/// </summary>
|
||||
public String UserName
|
||||
{
|
||||
get {return _userName;}
|
||||
set {_userName=value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the 235 response code if valid, otherwise
|
||||
/// return the error.
|
||||
/// </summary>
|
||||
/// <param name="smtpProxy">The SmtpProxy being used</param>
|
||||
/// <param name="supportedAuthTypes">String array of EHLO-specified auth types</param>
|
||||
/// <returns></returns>
|
||||
public SmtpResponse Negotiate(ISmtpProxy smtpProxy, String[] supportedAuthTypes)
|
||||
{
|
||||
ISmtpAuthToken token=null;
|
||||
foreach (String authType in supportedAuthTypes)
|
||||
{
|
||||
|
||||
if (authType.Equals("login"))
|
||||
{
|
||||
token=new LoginAuthToken(_userName, _password);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (token==null)
|
||||
{
|
||||
return new SmtpResponse(504, DotNetOpenMail.Resources.ARM.GetInstance().GetString("unrecognized_auth_type"));
|
||||
}
|
||||
|
||||
return token.Negotiate(smtpProxy, supportedAuthTypes);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// An SmtpException represents an SMTP response
|
||||
/// code and an error message. Network and connection
|
||||
/// errors are represented by a MailException instead.
|
||||
/// </summary>
|
||||
public class SmtpException : Exception
|
||||
{
|
||||
private int _errorcode;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of the SmtpException
|
||||
/// </summary>
|
||||
/// <param name="errorcode">The SMTP error code</param>
|
||||
public SmtpException(int errorcode)
|
||||
{
|
||||
this._errorcode=errorcode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of the SmtpException
|
||||
/// </summary>
|
||||
/// <param name="errorcode">The SMTP error code</param>
|
||||
/// <param name="message">The SMTP error message</param>
|
||||
public SmtpException(int errorcode, string message) : base(message)
|
||||
{
|
||||
this._errorcode=errorcode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of the SmtpException
|
||||
/// </summary>
|
||||
/// <param name="errorcode">The SMTP error code</param>
|
||||
/// <param name="message">The SMTP error message</param>
|
||||
/// <param name="inner">The inner exception</param>
|
||||
public SmtpException(int errorcode, string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
this._errorcode=errorcode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The SMTP error code.
|
||||
/// </summary>
|
||||
public int ErrorCode
|
||||
{
|
||||
get {return _errorcode;}
|
||||
set {_errorcode=value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert to a string
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return _errorcode+" "+this.Message;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using DotNetOpenMail.SmtpAuth;
|
||||
|
||||
//using log4net;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A proxy to access an SMTP server. This drives
|
||||
/// the protocol interaction.
|
||||
/// </summary>
|
||||
public class SmtpProxy : TcpClient, ISmtpProxy
|
||||
{
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(SmtpProxy));
|
||||
private SmtpServer _smtpserver=null;
|
||||
internal static readonly String ENDOFLINE="\r\n";
|
||||
private bool _isConnected=false;
|
||||
private bool _captureConversation=false;
|
||||
private static readonly String SERVER_LOG_PROMPT="READ> ";
|
||||
private static readonly String CLIENT_LOG_PROMPT="SENT> ";
|
||||
|
||||
//private StringBuilder _conversation=new StringBuilder();
|
||||
//private IPEndPoint _iEndPoint=null;
|
||||
|
||||
/*
|
||||
#region SmtpProxy
|
||||
private SmtpProxy(System.Net.IPAddress ipaddress, int portno)
|
||||
{
|
||||
_iendpoint = new IPEndPoint (ipaddress, portno);
|
||||
}
|
||||
#endregion
|
||||
*/
|
||||
|
||||
#region SmtpProxy
|
||||
private SmtpProxy(SmtpServer smtpserver)
|
||||
{
|
||||
_smtpserver=smtpserver;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInstance
|
||||
/// <summary>
|
||||
/// Get an instance of the SMTP Proxy
|
||||
/// </summary>
|
||||
/// <param name="smtpserver"></param>
|
||||
/// <returns></returns>
|
||||
public static SmtpProxy GetInstance(SmtpServer smtpserver)
|
||||
{
|
||||
return new SmtpProxy(smtpserver);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Open
|
||||
/// <summary>
|
||||
/// Connect to the server and return the initial
|
||||
/// welcome string. Throw a MailException if we
|
||||
/// can't connect.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SmtpResponse Open()
|
||||
{
|
||||
this.ReceiveTimeout=_smtpserver.ServerTimeout;
|
||||
|
||||
IPEndPoint ipendpoint=_smtpserver.GetIPEndPoint();
|
||||
try
|
||||
{
|
||||
|
||||
Connect(ipendpoint);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//throw new MailException("Could not connect to "+ipendpoint+":"+ipendpoint.Port, ex);
|
||||
throw new MailException("Could not connect to "+ipendpoint, ex);
|
||||
}
|
||||
_isConnected=true;
|
||||
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Helo
|
||||
/// <summary>
|
||||
/// Send the HELO string.
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse Helo(String localHostName)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
String message = "HELO "+localHostName+SmtpProxy.ENDOFLINE;
|
||||
//LogDebug("SENDING: "+message);
|
||||
|
||||
Write(message);
|
||||
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Ehlo
|
||||
/// <summary>
|
||||
/// Send the EHLO string.
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public EhloSmtpResponse Ehlo(String localHostName)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
String message = "EHLO "+localHostName+SmtpProxy.ENDOFLINE;
|
||||
//LogDebug("SENDING: "+message);
|
||||
|
||||
Write(message);
|
||||
|
||||
return ReadEhloSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MailFrom
|
||||
/// <summary>
|
||||
/// Send the MAIL FROM command
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <param name="mailfrom">The Envelope-From address</param>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse MailFrom(EmailAddress mailfrom)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
String message = "MAIL FROM: <"+mailfrom.Email+">"+SmtpProxy.ENDOFLINE;
|
||||
Write(message);
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RcptTo
|
||||
/// <summary>
|
||||
/// Send the MAIL FROM command
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <param name="rcpttoaddress">A recipient's address</param>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse RcptTo(EmailAddress rcpttoaddress)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
|
||||
String message= "RCPT TO: <"+rcpttoaddress.Email+">"+SmtpProxy.ENDOFLINE;
|
||||
//LogDebug("SENDING: "+message);
|
||||
//OnLogWriteSmtp
|
||||
Write(message);
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
/// <summary>
|
||||
/// Send the DATA string (without the data)
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse Data()
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
String message = "DATA"+SmtpProxy.ENDOFLINE;
|
||||
//LogDebug("SENDING: "+message);
|
||||
|
||||
Write(message);
|
||||
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WriteData
|
||||
/// <summary>
|
||||
/// Send the message content string
|
||||
/// Throw a MailException if we can't
|
||||
/// connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse WriteData(String message)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
|
||||
StringReader reader=new StringReader(message);
|
||||
String line=null;
|
||||
|
||||
while ((line=reader.ReadLine())!=null)
|
||||
{
|
||||
// checking for dot at the beginning of the
|
||||
// line (RFC821 sec. 4.5.2)
|
||||
|
||||
if (line.Length > 0 && line[0]=='.')
|
||||
{
|
||||
Write("."+line+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Write(line+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
}
|
||||
Write(SmtpProxy.ENDOFLINE+"."+SmtpProxy.ENDOFLINE);
|
||||
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadSmtpResponse
|
||||
private SmtpResponse ReadSmtpResponse()
|
||||
{
|
||||
String response=ReadResponse();
|
||||
if (response.Length < 3)
|
||||
{
|
||||
throw new MailException("Invalid response from server: \""+response+"\"");
|
||||
}
|
||||
String responseCodeStr=response.Substring(0, 3);
|
||||
String responseMessage="";
|
||||
if (response.Length > 4)
|
||||
{
|
||||
responseMessage=response.Substring(4);
|
||||
}
|
||||
try
|
||||
{
|
||||
int responseCode=Convert.ToInt32(responseCodeStr);
|
||||
return new SmtpResponse(responseCode, responseMessage);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new MailException("Could not understand response from server: "+response);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadEhloSmtpResponse
|
||||
/// <summary>
|
||||
/// Parse the response from the EHLO into an
|
||||
/// EhloSmtpResponse. Returns 250 "OK" if successful.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private EhloSmtpResponse ReadEhloSmtpResponse()
|
||||
{
|
||||
//log.Debug("READ THE RESPONSE");
|
||||
EhloSmtpResponse ehloResponse=new EhloSmtpResponse();
|
||||
String multiLineResponse=ReadResponse();
|
||||
StringReader sr=new StringReader(multiLineResponse);
|
||||
|
||||
String line=null;
|
||||
//log.Debug("READING...");
|
||||
while ((line=sr.ReadLine()) !=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
String responseMessage=String.Empty;
|
||||
if (line.Length > 4)
|
||||
{
|
||||
responseMessage=line.Substring(4).Trim();
|
||||
}
|
||||
|
||||
//log.Debug("Reading "+line);
|
||||
int responseCode=Convert.ToInt32(line.Substring(0, 3));
|
||||
if (responseCode==250)
|
||||
{
|
||||
if (responseMessage.ToLower().IndexOf("auth")==0)
|
||||
{
|
||||
// parse the auth types from the response
|
||||
if (responseMessage.Length > 4)
|
||||
{
|
||||
// RFC 2554 SMTP Authentication:
|
||||
// (3) The AUTH EHLO keyword contains as a parameter a space separated
|
||||
// list of the names of supported SASL mechanisms.
|
||||
foreach (String authtype in responseMessage.Substring(5).Split(' '))
|
||||
{
|
||||
ehloResponse.AddAvailableAuthType(authtype.ToLower());
|
||||
}
|
||||
}
|
||||
// return new SmtpResponse(responseCode, responseMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ehloResponse.ResponseCode=responseCode;
|
||||
ehloResponse.Message=responseMessage;
|
||||
return ehloResponse;
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new MailException("Could not understand response from server: "+multiLineResponse);
|
||||
}
|
||||
}
|
||||
ehloResponse.ResponseCode=250;
|
||||
ehloResponse.Message="OK";
|
||||
return ehloResponse;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Auth
|
||||
/// <summary>
|
||||
/// Send the AUTH command
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse Auth(String authtype)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
Write("AUTH "+authtype+SmtpProxy.ENDOFLINE);
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SendString
|
||||
/// <summary>
|
||||
/// Send any old string to the proxy
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse SendString(String str)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
Write(str+SmtpProxy.ENDOFLINE);
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Write
|
||||
/// <summary>
|
||||
/// Write a string to the current connection.
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
private void Write(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
//log.Debug(message);
|
||||
_smtpserver.OnLogWriteSmtp(this, message);
|
||||
if (_captureConversation)
|
||||
{
|
||||
|
||||
_smtpserver.AppendConversation(SmtpProxy.CLIENT_LOG_PROMPT+message);
|
||||
}
|
||||
|
||||
System.Text.ASCIIEncoding en = new System.Text.ASCIIEncoding() ;
|
||||
byte[] WriteBuffer = new byte[1024] ;
|
||||
WriteBuffer = en.GetBytes(message) ;
|
||||
|
||||
NetworkStream stream = GetStream() ;
|
||||
if (!stream.CanWrite)
|
||||
{
|
||||
throw new MailException("Stream could not be opened for writing.");
|
||||
}
|
||||
stream.Write(WriteBuffer,0,WriteBuffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogError(ex.Message);
|
||||
throw new MailException("Error while sending data to the server: "+ex.Message, ex);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Quit
|
||||
/// <summary>
|
||||
/// Send the QUIT command
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse Quit()
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
Write("QUIT"+SmtpProxy.ENDOFLINE);
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadResponse
|
||||
private string ReadResponse()
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\d{3}\s.+");
|
||||
string response = String.Empty;
|
||||
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
|
||||
byte[] serverbuff = new Byte[1024];
|
||||
NetworkStream stream = GetStream();
|
||||
|
||||
if (!stream.CanRead)
|
||||
{
|
||||
throw new MailException("Stream could not be read.");
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
// read until last response has been received
|
||||
// (indicated by whitespace after the numerical response code)
|
||||
do
|
||||
{
|
||||
int LoopTimeout = 0;
|
||||
if (stream.DataAvailable)
|
||||
{
|
||||
count = stream.Read(serverbuff, 0, serverbuff.Length);
|
||||
response = String.Concat(response, enc.GetString(serverbuff, 0, count));
|
||||
}
|
||||
|
||||
if ((LoopTimeout += 100) > this._smtpserver.ServerTimeout)
|
||||
{
|
||||
throw new MailException("Multiline server response timed out");
|
||||
}
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
while(! regex.IsMatch(response));
|
||||
|
||||
_smtpserver.OnLogReceiveSmtp(this, response);
|
||||
if (_captureConversation)
|
||||
{
|
||||
this._smtpserver.AppendConversation(SmtpProxy.SERVER_LOG_PROMPT+response);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogError(ex.Message);
|
||||
throw new MailException("Error while receiving data from server: "+ex.Message, ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CaptureSmtpConversation
|
||||
/// <summary>
|
||||
/// Set this to "true" if you want to capture the SMTP negotiation.
|
||||
/// Once the conversation has finished, use "GetConversation" to
|
||||
/// view it.
|
||||
/// </summary>
|
||||
public bool CaptureSmtpConversation
|
||||
{
|
||||
get {return this._captureConversation;}
|
||||
set {this._captureConversation=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/*
|
||||
#region LogError
|
||||
private void LogError(String message)
|
||||
{
|
||||
//System.Console.Error.WriteLine(message);
|
||||
//log.Error(message);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LogDebug
|
||||
private void LogDebug(String message)
|
||||
{
|
||||
//System.Console.Out.WriteLine(message);
|
||||
//log.Debug(message);
|
||||
}
|
||||
#endregion
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// The response from the SMTP server
|
||||
/// </summary>
|
||||
public class SmtpResponse
|
||||
{
|
||||
private int _responseCode;
|
||||
private String _message;
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the SmtpResponse
|
||||
/// </summary>
|
||||
/// <param name="responseCode"></param>
|
||||
/// <param name="message"></param>
|
||||
public SmtpResponse(int responseCode, String message)
|
||||
{
|
||||
this._responseCode=responseCode;
|
||||
this._message=message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The SMTP Reponse code
|
||||
/// </summary>
|
||||
public int ResponseCode
|
||||
{
|
||||
get { return _responseCode; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The SMTP Response String
|
||||
/// </summary>
|
||||
|
||||
public String Message
|
||||
{
|
||||
get { return _message; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Was the response a fatal error?
|
||||
/// </summary>
|
||||
public bool IsFatalError
|
||||
{
|
||||
get {
|
||||
return (this._responseCode>=500 && this._responseCode <= 599);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Was the response an OK message?
|
||||
/// </summary>
|
||||
public bool IsOk
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this._responseCode>=200 && this._responseCode <= 299);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert this response to an exception
|
||||
/// </summary>
|
||||
/// <returns>The SmtpException corresponding to this response</returns>
|
||||
public SmtpException GetException()
|
||||
{
|
||||
return new SmtpException(this._responseCode, this._message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// SMTP server response codes and their meanings.
|
||||
/// </summary>
|
||||
public enum SmtpResponseCode: int
|
||||
{
|
||||
/// <remarks>
|
||||
/// System status, or system help reply.
|
||||
/// </remarks>
|
||||
SystemStatus = 211,
|
||||
/// <remarks>
|
||||
/// Help message.
|
||||
/// </remarks>
|
||||
Help = 214,
|
||||
/// <remarks>
|
||||
/// Domain service ready. Ready to start TLS.
|
||||
/// </remarks>
|
||||
HeloReply = 220,
|
||||
/// <remarks>
|
||||
/// Domain service closing transmission channel.
|
||||
/// </remarks>
|
||||
Quit = 221,
|
||||
/// <remarks>
|
||||
/// Authentication successfully completed.
|
||||
/// </remarks>
|
||||
AuthSuccessful = 235,
|
||||
/// <remarks>
|
||||
/// OK, queuing for node node started. Requested mail action completed.
|
||||
/// </remarks>
|
||||
Ok = 250,
|
||||
/// <remarks>
|
||||
/// OK, no messages waiting for node node. User not local, will forward to forwardpath.
|
||||
/// </remarks>
|
||||
OkWillForward = 251,
|
||||
/// <remarks>
|
||||
/// OK, pending messages for node node started. Cannot VRFY user (e.g., info is not local), but will take message for this user and attempt delivery.
|
||||
/// </remarks>
|
||||
OkWithoutVerify = 252,
|
||||
/// <remarks>
|
||||
/// OK, messages pending messages for node node started.
|
||||
/// </remarks>
|
||||
OkMsgStarted = 253,
|
||||
/// <remarks>
|
||||
/// Start mail input, end with CRLF.CRLF
|
||||
/// </remarks>
|
||||
StartMailInput = 354,
|
||||
/// <remarks>
|
||||
/// Octet-offset is the transaction offset.
|
||||
/// </remarks>
|
||||
TransactionOffset = 355,
|
||||
/// <remarks>
|
||||
/// Domain service not available, closing transmission channel.
|
||||
/// </remarks>
|
||||
ServiceNotAvailable = 421,
|
||||
/// <remarks>
|
||||
/// A password transition is needed.
|
||||
/// </remarks>
|
||||
PasswordNeeded = 432,
|
||||
/// <remarks>
|
||||
/// Requested mail action not taken: mailbox unavailable.
|
||||
/// </remarks>
|
||||
MailboxBusy = 450,
|
||||
/// <remarks>
|
||||
/// Requested action aborted: local error in processing. Unable to process ATRN request now.
|
||||
/// </remarks>
|
||||
ErrorProcessing = 451,
|
||||
/// <remarks>
|
||||
/// Requested action not taken: insufficient system storage.
|
||||
/// </remarks>
|
||||
InsufficientStorage = 452,
|
||||
/// <remarks>
|
||||
/// You have no mail.
|
||||
/// </remarks>
|
||||
NoMail = 453,
|
||||
/// <remarks>
|
||||
/// TLS not available. Encryption required for requested authentication mechanism.
|
||||
/// </remarks>
|
||||
TlsNotAvailable = 454,
|
||||
/// <remarks>
|
||||
/// Unable to queue messages for node node.
|
||||
/// </remarks>
|
||||
NoMsgQueue = 458,
|
||||
/// <remarks>
|
||||
/// Node node not allowed: reason.
|
||||
/// </remarks>
|
||||
NodeNotAllowed = 459,
|
||||
/// <remarks>
|
||||
/// Command not recognized: command. Syntax error.
|
||||
/// </remarks>
|
||||
UnknownCmd = 500,
|
||||
/// <remarks>
|
||||
/// Syntax error, no parameters allowed.
|
||||
/// </remarks>
|
||||
SyntaxError = 501,
|
||||
/// <remarks>
|
||||
/// Command not implemented.
|
||||
/// </remarks>
|
||||
CmdNotImplemented = 502,
|
||||
/// <remarks>
|
||||
/// Bad sequence of commands.
|
||||
/// </remarks>
|
||||
BadSequence = 503,
|
||||
/// <remarks>
|
||||
/// Command parameter not implemented.
|
||||
/// </remarks>
|
||||
ParamNotImplemented = 504,
|
||||
/// <remarks>
|
||||
/// Security error.
|
||||
/// </remarks>
|
||||
SecurityError = 505,
|
||||
/// <remarks>
|
||||
/// Machine does not accept mail.
|
||||
/// </remarks>
|
||||
MailNotAccepted = 521,
|
||||
/// <remarks>
|
||||
/// Must issue a STARTTLS command first. Encryption required for requested authentication mechanism.
|
||||
/// </remarks>
|
||||
StartTLSneeded = 530,
|
||||
/// <remarks>
|
||||
/// Authentication mechanism is too weak.
|
||||
/// </remarks>
|
||||
AuthTooWeak = 534,
|
||||
/// <remarks>
|
||||
/// Encryption required for requested authentication mechanism.
|
||||
/// </remarks>
|
||||
EncryptionRequired = 538,
|
||||
/// <remarks>
|
||||
/// Requested action not taken: mailbox unavailable.
|
||||
/// </remarks>
|
||||
ActionNotTaken = 550,
|
||||
/// <remarks>
|
||||
/// User not local, please try forward path.
|
||||
/// </remarks>
|
||||
NotLocalPleaseForward = 551,
|
||||
/// <remarks>
|
||||
/// Requested mail action aborted: exceeded storage allocation.
|
||||
/// </remarks>
|
||||
ExceedStorageAllowance = 552,
|
||||
/// <remarks>
|
||||
/// Requested action not taken: mailbox name not allowed.
|
||||
/// </remarks>
|
||||
MailboxNameNotAllowed = 553,
|
||||
/// <remarks>
|
||||
/// Transaction failed.
|
||||
/// </remarks>
|
||||
TransactionFailed = 554
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using DotNetOpenMail.SmtpAuth;
|
||||
using DotNetOpenMail.Logging;
|
||||
|
||||
//using DomainKeys;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A description of an SMTP server.
|
||||
/// </summary>
|
||||
public class SmtpServer
|
||||
{
|
||||
//public delegate void SmtpDataMessagePresendHandler(object sender, MyEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Logging delegate
|
||||
/// </summary>
|
||||
public delegate void LogHandler(LogMessage logMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Handle a message about to be sent
|
||||
/// </summary>
|
||||
public event LogHandler LogSmtpWrite;
|
||||
|
||||
/// <summary>
|
||||
/// Handle a message received
|
||||
/// </summary>
|
||||
public event LogHandler LogSmtpReceive;
|
||||
|
||||
/// <summary>
|
||||
/// Log that the conversation has completed
|
||||
/// </summary>
|
||||
public event LogHandler LogSmtpCompleted;
|
||||
|
||||
//private static Logger _logger=new Logger();
|
||||
|
||||
#region Data Members
|
||||
private IPEndPoint _ipendpoint;
|
||||
private IPAddress _ipaddress;
|
||||
private String _hostname;
|
||||
private int _port=25;
|
||||
private String _id; // some human readable name
|
||||
private int _serverTimeout=30000; // the timeout in milliseconds
|
||||
private String _helohost=null;
|
||||
private ISmtpAuthToken _authToken=null;
|
||||
private ISmtpProxy _smtpProxy=null;
|
||||
private bool _captureSmtpConversation=false;
|
||||
private StringBuilder _smtpConversation=new StringBuilder();
|
||||
#endregion
|
||||
|
||||
#region SmtpServer
|
||||
/// <summary>
|
||||
/// Create a new SMTP server at this hostname and
|
||||
/// port.
|
||||
/// </summary>
|
||||
/// <param name="hostname">The address or hostname of the smtp server</param>
|
||||
/// <param name="port">The port of the smtp server.</param>
|
||||
public SmtpServer(String hostname, int port)
|
||||
{
|
||||
_id=hostname+":"+port;
|
||||
_hostname=hostname;
|
||||
_port=port;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SmtpServer
|
||||
/// <summary>
|
||||
/// Create a new SMTP server at this hostname and
|
||||
/// port.
|
||||
/// </summary>
|
||||
/// <param name="hostname">The address or hostname of the smtp server</param>
|
||||
public SmtpServer(String hostname)
|
||||
{
|
||||
_id=hostname+":"+_port;
|
||||
_hostname=hostname;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SmtpServer
|
||||
/// <summary>
|
||||
/// Create a new SMTP server at this hostname and
|
||||
/// port.
|
||||
/// </summary>
|
||||
/// <param name="ipaddress">The ip address of the SMTP server</param>
|
||||
/// <param name="port">The port number of SMTP server</param>
|
||||
public SmtpServer(IPAddress ipaddress, int port)
|
||||
{
|
||||
_id=ipaddress.ToString()+":"+port;
|
||||
_ipaddress=ipaddress;
|
||||
_port=port;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetIPEndPoint
|
||||
/// <summary>
|
||||
/// Get the end point for the SMTP server. The IPEndpoint will
|
||||
/// be saved for later to prevent multiple hostname lookups.
|
||||
/// </summary>
|
||||
/// <exception>SmtpException is thrown if the host doesn't resolve.</exception>
|
||||
/// <returns>returns an IPEndPoint for the SMTPServer.</returns>
|
||||
internal IPEndPoint GetIPEndPoint()
|
||||
{
|
||||
if (_ipendpoint!=null)
|
||||
{
|
||||
return _ipendpoint;
|
||||
}
|
||||
if (_hostname!=null)
|
||||
{
|
||||
IPHostEntry iphostentry=System.Net.Dns.Resolve(_hostname);
|
||||
if (iphostentry.AddressList.Length==0)
|
||||
{
|
||||
throw new MailException("unable to resolve host: "+_hostname);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ipendpoint=new IPEndPoint(iphostentry.AddressList[0], _port);
|
||||
}
|
||||
return this._ipendpoint;
|
||||
}
|
||||
else if (_ipaddress!=null)
|
||||
{
|
||||
_ipendpoint=new IPEndPoint(_ipaddress, _port);
|
||||
return _ipendpoint;
|
||||
}
|
||||
else throw new MailException("Invalid IPEndPoint");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ServerTimeout
|
||||
/// <summary>
|
||||
/// The timeout waiting for an SMTP command, in
|
||||
/// milliseconds
|
||||
/// </summary>
|
||||
public int ServerTimeout
|
||||
{
|
||||
get {return _serverTimeout;}
|
||||
set {_serverTimeout=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetSmtpProxy
|
||||
/// <summary>
|
||||
/// Get an instance of an SmtpProxy
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal ISmtpProxy GetSmtpProxy()
|
||||
{
|
||||
if (_smtpProxy!=null)
|
||||
{
|
||||
return _smtpProxy;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SmtpProxy.GetInstance(this);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetHeloHost
|
||||
private String GetHeloHost()
|
||||
{
|
||||
if (_helohost!=null)
|
||||
{
|
||||
return _helohost;
|
||||
}
|
||||
else
|
||||
{
|
||||
//String hostname=Environment.MachineName.ToLower();
|
||||
String hostname=Dns.GetHostName();
|
||||
if (hostname!=null)
|
||||
{
|
||||
return hostname;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "localhost";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UseEhlo
|
||||
/// <summary>
|
||||
/// Figure out whether we need EHLO or not.
|
||||
/// Currently, this is only for SMTP AUTH
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool UseEhlo()
|
||||
{
|
||||
if (this._authToken!=null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
/// <summary>
|
||||
/// Send the email.
|
||||
/// </summary>
|
||||
/// <param name="emailMessage">The completed message</param>
|
||||
/// <param name="rcpttocollection">A list of email addresses which
|
||||
/// are to be used in the RCPT TO SMTP communication</param>
|
||||
/// <param name="mailfrom">An email address for the MAIL FROM
|
||||
/// part of the SMTP protocol.</param>
|
||||
/// <exception cref="SmtpException">throws an SmtpException if there
|
||||
/// is an unexpected SMTP error number sent from the server.</exception>
|
||||
/// <exception cref="MailException">throws a MailException if there
|
||||
/// is a network problem, connection problem, or other issue.</exception>
|
||||
/// <returns></returns>
|
||||
internal bool Send(ISendableMessage emailMessage, EmailAddressCollection rcpttocollection, EmailAddress mailfrom)
|
||||
{
|
||||
//ISmtpNegotiator negotiator=_smtpserver.GetSmtpNegotiator();
|
||||
ISmtpProxy smtpproxy=GetSmtpProxy();
|
||||
//smtpproxy.CaptureSmtpConversation=CaptureSmtpConversation;
|
||||
SmtpResponse smtpResponse=smtpproxy.Open();
|
||||
try
|
||||
{
|
||||
#region Connect
|
||||
if (smtpResponse.ResponseCode!=220)
|
||||
{
|
||||
throw smtpResponse.GetException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HELO / EHLO
|
||||
if (UseEhlo())
|
||||
{
|
||||
EhloSmtpResponse esmtpResponse=smtpproxy.Ehlo(GetHeloHost());
|
||||
if (esmtpResponse.ResponseCode!=250)
|
||||
{
|
||||
// TODO: FIX THIS
|
||||
throw new SmtpException(esmtpResponse.ResponseCode, esmtpResponse.Message);
|
||||
}
|
||||
|
||||
// do SMTP AUTH
|
||||
if (this._authToken!=null)
|
||||
{
|
||||
|
||||
smtpResponse=_authToken.Negotiate(smtpproxy, esmtpResponse.GetAvailableAuthTypes());
|
||||
if (smtpResponse.ResponseCode!=235)
|
||||
{
|
||||
throw smtpResponse.GetException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
smtpResponse=smtpproxy.Helo(GetHeloHost());
|
||||
if (smtpResponse.ResponseCode!=250)
|
||||
{
|
||||
throw smtpResponse.GetException();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MAIL FROM
|
||||
smtpResponse=smtpproxy.MailFrom(mailfrom);
|
||||
if (smtpResponse.ResponseCode!=250)
|
||||
{
|
||||
throw smtpResponse.GetException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RCPT TO
|
||||
|
||||
foreach ( EmailAddress rcpttoaddress in rcpttocollection)
|
||||
{
|
||||
smtpResponse=smtpproxy.RcptTo(rcpttoaddress);
|
||||
if (smtpResponse.ResponseCode!=250)
|
||||
{
|
||||
throw smtpResponse.GetException();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DATA
|
||||
|
||||
smtpResponse=smtpproxy.Data();
|
||||
if (smtpResponse.ResponseCode!=354)
|
||||
{
|
||||
throw smtpResponse.GetException();
|
||||
}
|
||||
//smtpResponse=negotiator.WriteData();
|
||||
|
||||
String message=emailMessage.ToDataString();
|
||||
if (message==null)
|
||||
{
|
||||
throw new MailException("The message content is null");
|
||||
}
|
||||
/*
|
||||
// START Test With Domain Keys
|
||||
// (this would appear as an event callback if it works)
|
||||
MailSigner mailsigner=new MailSigner();
|
||||
bool signed = mailsigner.signMail(message);
|
||||
if (!signed)
|
||||
{
|
||||
throw new MailException("Error creating DomainKeys signature.");
|
||||
}
|
||||
message=mailsigner.signedHeader + message;
|
||||
// END Test With Domain Keys
|
||||
*/
|
||||
|
||||
|
||||
// Send the data
|
||||
smtpResponse=smtpproxy.WriteData(message);
|
||||
if (smtpResponse.ResponseCode!=250)
|
||||
{
|
||||
throw smtpResponse.GetException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region QUIT
|
||||
// QUIT
|
||||
smtpResponse=smtpproxy.Quit();
|
||||
if (smtpResponse.ResponseCode!=221)
|
||||
{
|
||||
throw smtpResponse.GetException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
smtpproxy.Close();
|
||||
OnLogSmtpCompleted(this, "Connection Closed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OverrideSmtpProxy
|
||||
/// <summary>
|
||||
/// Override the SmtpProxy. This is only
|
||||
/// for testing smtp negotiation without an
|
||||
/// smtp server.
|
||||
/// </summary>
|
||||
/// <param name="smtpProxy"></param>
|
||||
public void OverrideSmtpProxy(ISmtpProxy smtpProxy)
|
||||
{
|
||||
_smtpProxy=smtpProxy;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SmtpAuthToken
|
||||
/// <summary>
|
||||
/// Get or set the SMTP AUTH token for the server.
|
||||
/// </summary>
|
||||
public ISmtpAuthToken SmtpAuthToken
|
||||
{
|
||||
get {return _authToken;}
|
||||
set {_authToken = value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CaptureSmtpConversation
|
||||
/// <summary>
|
||||
/// If true, the following call to "Send" will capture the
|
||||
/// most recent SMTP conversation to the SmtpServer object.
|
||||
/// This is intended for debugging only.
|
||||
/// This is deprecated in favour of the log message events.
|
||||
/// </summary>
|
||||
[ObsoleteAttribute("This property is deprecated. You "+
|
||||
"should use LogSmtpWrite and LogSmtpReceive instead. "+
|
||||
"This will be removed in a future version.", false)]
|
||||
public bool CaptureSmtpConversation
|
||||
{
|
||||
get
|
||||
{
|
||||
return _captureSmtpConversation;
|
||||
}
|
||||
set
|
||||
{
|
||||
_captureSmtpConversation=value;
|
||||
if (!_captureSmtpConversation)
|
||||
{
|
||||
this._smtpConversation=new StringBuilder();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AppendConversation
|
||||
/// <summary>
|
||||
/// Append this string to the conversation log.
|
||||
/// </summary>
|
||||
/// <param name="str">the string from the SMTP conversation</param>
|
||||
internal void AppendConversation(String str)
|
||||
{
|
||||
this._smtpConversation.Append(str);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetSmtpConversation
|
||||
/// <summary>
|
||||
/// If CaptureSmtpConversation is true, a Send() will
|
||||
/// be captured, and will be accessible here.
|
||||
/// </summary>
|
||||
/// <returns>The SMTP Conversation or null.</returns>
|
||||
[ObsoleteAttribute("This method is deprecated. You "+
|
||||
"should use LogSmtpWrite and LogSmtpReceive instead. "+
|
||||
"This will be removed in a future version.", false)]
|
||||
public String GetSmtpConversation()
|
||||
{
|
||||
if (_smtpConversation==null || _smtpConversation.Length==0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _smtpConversation.ToString();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region OnLogWriteSmtp
|
||||
internal void OnLogWriteSmtp(Object sender, String message)
|
||||
{
|
||||
if (LogSmtpWrite!=null)
|
||||
{
|
||||
LogSmtpWrite(new LogMessage(sender, message));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OnLogReceiveSmtp
|
||||
internal void OnLogReceiveSmtp(Object sender, String message)
|
||||
{
|
||||
if (LogSmtpReceive!=null)
|
||||
{
|
||||
LogSmtpReceive(new LogMessage(sender, message));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OnLogSmtpCompleted
|
||||
internal void OnLogSmtpCompleted(Object sender, String message)
|
||||
{
|
||||
if (LogSmtpCompleted!=null)
|
||||
{
|
||||
LogSmtpCompleted(new LogMessage(sender, message));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hostname
|
||||
/// <summary>
|
||||
/// The server hostname
|
||||
/// </summary>
|
||||
public String Hostname
|
||||
{
|
||||
get {return _hostname;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Port
|
||||
/// <summary>
|
||||
/// The server port
|
||||
/// </summary>
|
||||
public int Port
|
||||
{
|
||||
get {return _port;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Return the host name, a colon, and a port number.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Hostname+":"+Port;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the hostname used by the HELO
|
||||
/// command.
|
||||
/// </summary>
|
||||
public String HeloHost
|
||||
{
|
||||
get
|
||||
{
|
||||
return _helohost;
|
||||
}
|
||||
set
|
||||
{
|
||||
_helohost=value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using DotNetOpenMail.Encoding;
|
||||
using DotNetOpenMail.Utils;
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A mime representation of plain-text content.
|
||||
/// </summary>
|
||||
public class TextAttachment : AbstractEmailAttachment
|
||||
{
|
||||
|
||||
//private IEncoder _encoder=null;
|
||||
//private String _mimetype="text/plain";
|
||||
/// <summary>
|
||||
/// Create a new plain-text Attachment. It flags the content/type
|
||||
/// as "text/plain", uses Quoted Printable encoding by
|
||||
/// default, and uses the default character set, which is
|
||||
/// ISO-8859-1 unless otherwise specified in the .config file.
|
||||
/// </summary>
|
||||
/// <param name="contents"></param>
|
||||
public TextAttachment(String contents)
|
||||
{
|
||||
this.ContentType="text/plain";
|
||||
this.Contents=contents;
|
||||
this.CharSet=System.Text.Encoding.GetEncoding(Configuration.GetInstance().GetDefaultEncoding("iso-8859-1"));
|
||||
//this.Encoder=EncoderFactory.GetEncoder(EncodingType.QuotedPrintable);
|
||||
this.Encoding=EncodingType.QuotedPrintable;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Something take a binary reader's data into a byte array.
|
||||
/// </summary>
|
||||
public class BinaryReaderUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for BinaryReaderUtil
|
||||
/// </summary>
|
||||
public BinaryReaderUtil()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a binary stream into a byte array
|
||||
/// (Cribbed from posting by Jon Skeet:
|
||||
/// http://www.developerfusion.co.uk/show/4696/)
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">An open Binary Reader</param>
|
||||
/// <returns>A byte array with the bytes from the disk</returns>
|
||||
public static byte[] ReadIntoByteArray (BinaryReader binaryreader)
|
||||
{
|
||||
int initialLength = 32768;
|
||||
|
||||
byte[] buffer = new byte[initialLength];
|
||||
int read=0;
|
||||
|
||||
int chunk;
|
||||
while ( (chunk = binaryreader.Read(buffer, read, buffer.Length-read)) > 0)
|
||||
{
|
||||
read += chunk;
|
||||
if (read == buffer.Length)
|
||||
{
|
||||
int nextByte = binaryreader.ReadByte();
|
||||
|
||||
if (nextByte==-1)
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
byte[] newBuffer = new byte[buffer.Length*2];
|
||||
Array.Copy(buffer, newBuffer, buffer.Length);
|
||||
newBuffer[read]=(byte)nextByte;
|
||||
buffer = newBuffer;
|
||||
read++;
|
||||
}
|
||||
}
|
||||
byte[] ret = new byte[read];
|
||||
Array.Copy(buffer, ret, read);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface to the configuration settings for the library.
|
||||
/// This includes an interface to the .config file.
|
||||
/// This is a singleton.
|
||||
/// </summary>
|
||||
public class Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// The singleton
|
||||
/// </summary>
|
||||
private static Configuration _theinstance=new Configuration();
|
||||
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
private Configuration()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate the instance of the object (if not created)
|
||||
/// and return it.
|
||||
/// </summary>
|
||||
/// <returns>the Configuration singleton object</returns>
|
||||
public static Configuration GetInstance()
|
||||
{
|
||||
return _theinstance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the X-Sender header, if any is specified in the .config
|
||||
/// file with the key dnom.headers.xsender.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String GetXSender()
|
||||
{
|
||||
return System.Configuration.ConfigurationSettings.AppSettings["dnom.headers.xsender"];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default encoding, if any is specified in the .config
|
||||
/// file with the key dnom.encoding.
|
||||
/// </summary>
|
||||
public String GetDefaultEncoding(String def)
|
||||
{
|
||||
return GetAppSetting("dnom.encoding", def);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default charset, if any is specified in the .config
|
||||
/// file with the key dnom.charset.
|
||||
/// </summary>
|
||||
public System.Text.Encoding GetDefaultCharset()
|
||||
{
|
||||
String encodingstr=GetAppSetting("dnom.encoding", "iso-8859-1");
|
||||
return System.Text.Encoding.GetEncoding(encodingstr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an app setting from the .config file. If none is found
|
||||
/// or it is empty or only whitespace, use the defaultvalue.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to search for in the .config file</param>
|
||||
/// <param name="defaultvalue">The default value if the value
|
||||
/// is null or only whitespace.</param>
|
||||
private String GetAppSetting(String key, String defaultvalue)
|
||||
{
|
||||
String tmp=System.Configuration.ConfigurationSettings.AppSettings[key];
|
||||
if (tmp==null || tmp.Trim()=="")
|
||||
{
|
||||
return defaultvalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace DotNetOpenMail.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse a email address string into an EmailAddress.
|
||||
/// * This isn't very mature yet! *
|
||||
/// </summary>
|
||||
public class EmailAddressParser
|
||||
{
|
||||
private String _lastError=null;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public EmailAddressParser()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the last conversion was unsuccessful, this
|
||||
/// contains the error message. If it was successful,
|
||||
/// it will be null.
|
||||
/// </summary>
|
||||
public String LastError
|
||||
{
|
||||
get {return _lastError;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a raw email address into an EmailAddress object.
|
||||
/// If it can't be parsed, return null and set LastError
|
||||
/// to the error message.
|
||||
/// </summary>
|
||||
/// <param name="rawemailaddress"></param>
|
||||
/// <returns></returns>
|
||||
public EmailAddress ParseRawEmailAddress(String rawemailaddress)
|
||||
{
|
||||
// see: http://www.twilightsoul.com/Default.aspx?PageContentID=10&tabid=134
|
||||
String regex=@"^((?<DisplayName>([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+[\t\x20]*|"""+
|
||||
@"[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*"")+)?[\t\x20]*"+
|
||||
@"<(?<LocalPart>([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+"+
|
||||
@"(\.[!#-'\*\+\-/-9=\?A-Z\^-~]+)*|""[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*""))"+
|
||||
@"@(?<Domain>(([a-zA-Z0-9][-a-zA-Z0-9]*[a-zA-Z0-9]\.)+[a-zA-Z]{2,}|"+
|
||||
@"\[(([0-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}"+
|
||||
@"([0-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\]"+
|
||||
@"|[a-zA-Z0-9_-]+"+ // added to allow domains w/o dot, e.g. "localhost"
|
||||
@"))>[\t\x20]*|"+
|
||||
@"(?<LocalPart>([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+(\.[!#-'\*\+\"+
|
||||
@"-/-9=\?A-Z\^-~]+)*|"+
|
||||
@"""[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*""))"+
|
||||
@"@(?<Domain>(([a-zA-Z0-9][-a-zA-Z0-9]*[a-zA-Z0-9]\.)+[a-zA-Z]{2,}|"+
|
||||
@"\[(([0-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}"+ // IP line 1
|
||||
@"([0-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\]"+ // IP line 2
|
||||
@")))$";
|
||||
|
||||
Regex re = new Regex(regex, RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
|
||||
Match m = re.Match(rawemailaddress);
|
||||
|
||||
String email="";
|
||||
String name="";
|
||||
|
||||
if (!m.Success)
|
||||
{
|
||||
_lastError="Could not parse the email address: "+rawemailaddress;
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastError=null;
|
||||
name=m.Groups["DisplayName"].Value.Trim();
|
||||
email=m.Groups["LocalPart"].Value;
|
||||
String domain=m.Groups["Domain"].Value;
|
||||
if (!domain.Equals(""))
|
||||
{
|
||||
email+="@"+domain;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new EmailAddress(email, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// The DotNetOpenMail Version.
|
||||
/// </summary>
|
||||
public class VersionInfo
|
||||
{
|
||||
private static VersionInfo _theobject=new VersionInfo();
|
||||
private int majorid=0;
|
||||
private int minorid=5;
|
||||
private int incidentalid=8;
|
||||
private String status="b"; // "a" is for alpha, "b" for beta, "rcX" for release candidate,
|
||||
//"" for release
|
||||
|
||||
/// <summary>
|
||||
/// Empty Constructor
|
||||
/// </summary>
|
||||
private VersionInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the singleton of this class
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static VersionInfo GetInstance()
|
||||
{
|
||||
return new VersionInfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current version info as a printable string.
|
||||
/// This will be of the form A.B.CD, where A is the
|
||||
/// majorid, B is the minor id, C is the incidental revision,
|
||||
/// and D is either "a", "b", "rcX" for "alpha", "beta" and
|
||||
/// "release candidate X", respectively. If it is the
|
||||
/// release version, D is blank.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
return String.Format("{0}.{1}.{2}{3}", majorid, minorid, incidentalid, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: log4net.Config.DOMConfigurator(ConfigFileExtension="log4net", Watch=true)]
|
||||
[assembly: log4net.Config.Domain()]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
@@ -0,0 +1,251 @@
|
||||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.10.3077"
|
||||
SchemaVersion = "2.0"
|
||||
ProjectGuid = "{74F3DCD7-1325-4968-B466-38618A380CE9}"
|
||||
>
|
||||
<Build>
|
||||
<Settings
|
||||
ApplicationIcon = ""
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "DotNetOpenMailTests"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "Library"
|
||||
PreBuildEvent = ""
|
||||
PostBuildEvent = 'copy "$(SolutionDir)DotNetOpenMailTests.dll.*" "$(ProjectDir)$(OutDir)"'
|
||||
RootNamespace = "DotNetOpenMailTests"
|
||||
RunPostBuildEvent = "OnBuildSuccess"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
Name = "Debug"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
NoStdLib = "false"
|
||||
NoWarn = ""
|
||||
Optimize = "false"
|
||||
OutputPath = "bin\Debug\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "false"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
NoStdLib = "false"
|
||||
NoWarn = ""
|
||||
Optimize = "true"
|
||||
OutputPath = "bin\Release\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
</Settings>
|
||||
<References>
|
||||
<Reference
|
||||
Name = "System"
|
||||
AssemblyName = "System"
|
||||
HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Data"
|
||||
AssemblyName = "System.Data"
|
||||
HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.XML"
|
||||
AssemblyName = "System.Xml"
|
||||
HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "log4net"
|
||||
AssemblyName = "log4net"
|
||||
HintPath = "..\lib\log4net.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "nunit.framework"
|
||||
AssemblyName = "nunit.framework"
|
||||
HintPath = "..\lib\nunit.framework.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "DotNetOpenMail"
|
||||
Project = "{6FBB299F-81A1-49EA-B00A-E916F8F797B3}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Web"
|
||||
AssemblyName = "System.Web"
|
||||
HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Web.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "nmock"
|
||||
AssemblyName = "nmock"
|
||||
HintPath = "..\lib\nmock.dll"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
<Include>
|
||||
<File
|
||||
RelPath = "AssemblyInfo.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "EmailAddressTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "EmailMessageInAlternateEncodings.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "EmailMessageTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "ExampleTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "FileAttachmentTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "FileAttachmentTests2.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Log4netLogger.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "QuickTest.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "RawEmailMessageTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "RFC2822DateTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "RussianTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpProxyTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestAddressHelper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\Base64EncoderTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\EightBitEncoderTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\QPEncoderTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Encoding\SevenBitEncoderTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Resources\ARMTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpAuth\LocalAuthTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpAuth\MockedSlowProxy.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpAuth\MockedSmtpProxy.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SmtpServerTests\SmtpServerTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestFiles\grover.jpg"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestFiles\grover.tif"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestFiles\groverUpsideDown.jpg"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestFiles\ImportedEmail.txt"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Utils\EmailAddressParserTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
</Include>
|
||||
</Files>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<VisualStudioProject>
|
||||
<CSHARP LastOpenVersion = "7.10.3077" >
|
||||
<Build>
|
||||
<Settings ReferencePath = "C:\Visual Studio Projects\DotNetOpenMail\lib\" >
|
||||
<Config
|
||||
Name = "Debug"
|
||||
EnableASPDebugging = "false"
|
||||
EnableASPXDebugging = "false"
|
||||
EnableUnmanagedDebugging = "false"
|
||||
EnableSQLServerDebugging = "false"
|
||||
RemoteDebugEnabled = "false"
|
||||
RemoteDebugMachine = ""
|
||||
StartAction = "Project"
|
||||
StartArguments = ""
|
||||
StartPage = ""
|
||||
StartProgram = ""
|
||||
StartURL = ""
|
||||
StartWorkingDirectory = ""
|
||||
StartWithIE = "false"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
EnableASPDebugging = "false"
|
||||
EnableASPXDebugging = "false"
|
||||
EnableUnmanagedDebugging = "false"
|
||||
EnableSQLServerDebugging = "false"
|
||||
RemoteDebugEnabled = "false"
|
||||
RemoteDebugMachine = ""
|
||||
StartAction = "Project"
|
||||
StartArguments = ""
|
||||
StartPage = ""
|
||||
StartProgram = ""
|
||||
StartURL = ""
|
||||
StartWorkingDirectory = ""
|
||||
StartWithIE = "true"
|
||||
/>
|
||||
</Settings>
|
||||
</Build>
|
||||
<OtherProjectSettings
|
||||
CopyProjectDestinationFolder = ""
|
||||
CopyProjectUncPath = ""
|
||||
CopyProjectOption = "0"
|
||||
ProjectView = "ShowAllFiles"
|
||||
ProjectTrust = "0"
|
||||
/>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
using DotNetOpenMail;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests {
|
||||
|
||||
[TestFixture]
|
||||
public class EmailAddressTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(EmailAddressTests));
|
||||
|
||||
public EmailAddressTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
[Test]
|
||||
public void TestSerialization()
|
||||
{
|
||||
EmailAddress emailaddress=new EmailAddress("test@test.com", "My Name");
|
||||
Assert.AreEqual("My Name <test@test.com>",emailaddress.ToString());
|
||||
|
||||
emailaddress=new EmailAddress("test@test.com", "Last, First");
|
||||
Assert.AreEqual("\"Last, First\" <test@test.com>",emailaddress.ToString());
|
||||
|
||||
emailaddress=new EmailAddress("test@test.com", "<First Last>");
|
||||
Assert.AreEqual("\"<First Last>\" <test@test.com>",emailaddress.ToString());
|
||||
|
||||
emailaddress=new EmailAddress("test@test.com", "[First Last]");
|
||||
Assert.AreEqual("\"[First Last]\" <test@test.com>",emailaddress.ToString());
|
||||
|
||||
emailaddress=new EmailAddress("test@test.com", "(First Last)");
|
||||
Assert.AreEqual("\"(First Last)\" <test@test.com>",emailaddress.ToString());
|
||||
emailaddress=new EmailAddress("test@test.com", "First \"NickName\" Last");
|
||||
Assert.AreEqual("\"First \\\"NickName\\\" Last\" <test@test.com>",emailaddress.ToString());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Utils;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class EmailMessageInAlternateEncodings
|
||||
{
|
||||
|
||||
SmtpServer _smtpserver=null;
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(EmailMessageInAlternateEncodings));
|
||||
|
||||
public EmailMessageInAlternateEncodings()
|
||||
{
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
#region TestJapaneseHtmlAndTextQPEncoding
|
||||
[Test]
|
||||
public void TestJapaneseHtmlAndTextQPEncoding()
|
||||
{
|
||||
//SmtpServer smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
System.Text.Encoding encoding=System.Text.Encoding.GetEncoding("Shift_JIS");
|
||||
|
||||
EmailAddress japanesefromaddress=new EmailAddress(TestAddressHelper.GetFromAddress().Email, "日本語", EncodingType.QuotedPrintable, encoding);
|
||||
EmailAddress japanesetoaddress=new EmailAddress(TestAddressHelper.GetToAddress().Email, "日本語", EncodingType.QuotedPrintable, encoding);
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.HeaderEncoding=DotNetOpenMail.Encoding.EncodingType.QuotedPrintable;
|
||||
System.Text.Encoding jencoding=System.Text.Encoding.GetEncoding("iso-2022-jp");
|
||||
//emailmessage.HeaderCharSet=System.Text.Encoding.GetEncoding("Shift_JIS");
|
||||
emailmessage.HeaderCharSet=jencoding;
|
||||
|
||||
log.Debug("ENCODING IS "+jencoding.EncodingName);
|
||||
log.Debug("IN HEADER:"+jencoding.HeaderName);
|
||||
log.Debug("IN BODY:"+jencoding.BodyName);
|
||||
log.Debug("CODE PAGE:"+jencoding.CodePage);
|
||||
log.Debug("WebName:"+jencoding.WebName);
|
||||
log.Debug("WINDOWS CODE PAGE:"+jencoding.WindowsCodePage);
|
||||
emailmessage.FromAddress=japanesefromaddress;
|
||||
emailmessage.AddToAddress(japanesetoaddress);
|
||||
emailmessage.Subject="日本語 - Quoted Printable";
|
||||
emailmessage.TextPart=new TextAttachment("東京、日本語");
|
||||
//emailmessage.TextPart.CharSet+AD0AIg-Shift_JIS+ACIAOw-
|
||||
emailmessage.TextPart.CharSet=jencoding;
|
||||
emailmessage.TextPart.Encoding=DotNetOpenMail.Encoding.EncodingType.QuotedPrintable;
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>東京、日本語</body></html>");
|
||||
//emailmessage.HtmlPart.CharSet+AD0AIg-Shift_JIS+ACIAOw-
|
||||
emailmessage.HtmlPart.CharSet=jencoding;
|
||||
emailmessage.HtmlPart.Encoding=DotNetOpenMail.Encoding.EncodingType.QuotedPrintable;
|
||||
|
||||
emailmessage.Send(_smtpserver);
|
||||
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
log.Debug(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
|
||||
|
||||
bool toHeaderEncoded=false;
|
||||
bool fromHeaderEncoded=false;
|
||||
bool subjectHeaderEncoded=false;
|
||||
bool htmlEncoded=false;
|
||||
bool textEncoded=false;
|
||||
bool hasPlainText=false;
|
||||
bool hasHtmlText=false;
|
||||
|
||||
|
||||
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
//log.Debug("FOUND +ACIAKw-line);
|
||||
if (line.IndexOf("To: =?iso-2022-jp?Q?=93=FA=96{=8C=EA?= <"+japanesetoaddress.Email+">")==0)
|
||||
{
|
||||
toHeaderEncoded=true;
|
||||
}
|
||||
if (line.IndexOf("From") == 0)
|
||||
{
|
||||
String expectedfrom="From: =?iso-2022-jp?Q?=93=FA=96{=8C=EA?= <"+japanesefromaddress.Email+">";
|
||||
|
||||
if (line.IndexOf(expectedfrom)== 0)
|
||||
{
|
||||
fromHeaderEncoded=true;
|
||||
}
|
||||
}
|
||||
if (line.IndexOf("Subject: =?iso-2022-jp?Q?=1B$BF|K\\8l=1B(B=20-=20Quoted=20Printable?=")==0)
|
||||
{
|
||||
subjectHeaderEncoded=true;
|
||||
}
|
||||
if (line.IndexOf("<html><body>=1B$BEl5~!\"F|K\\8l=1B(B</body></html>")==0)
|
||||
{
|
||||
//<html><body>=67=71=4E=AC=30=01=65=E5=67=2C=8A=9E</body></html>
|
||||
|
||||
htmlEncoded=true;
|
||||
}
|
||||
if (line.IndexOf("=1B$BEl5~!\"F|K\\8l=1B(B")==0)
|
||||
{
|
||||
textEncoded=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/plain")==0)
|
||||
{
|
||||
hasPlainText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/html")==0)
|
||||
{
|
||||
hasHtmlText=true;
|
||||
}
|
||||
if (line.IndexOf("X-Mailer: DotNetOpenMail " + VersionInfo.GetInstance().ToString())==0)
|
||||
{
|
||||
//hasDefaultXMailerHeader=true;
|
||||
}
|
||||
if (line.IndexOf("X-MyHeader1: my header number one") == 0)
|
||||
{
|
||||
//hasCustomHeader1=true;
|
||||
}
|
||||
if (line.IndexOf("X-MyHeader2: my header number two") == 0)
|
||||
{
|
||||
//hasCustomHeader2=true;
|
||||
}
|
||||
|
||||
// log.Debug("Line +ACIAKw-i+-": +ACIAKw-line);
|
||||
}
|
||||
Assert.IsTrue(toHeaderEncoded, "To Header not encoded");
|
||||
Assert.IsTrue(fromHeaderEncoded, "From Header not encoded");
|
||||
Assert.IsTrue(subjectHeaderEncoded, "Subject Header not encoded");
|
||||
//Assert.IsTrue(hasSubjectHeader, "Missing Subject Header");
|
||||
//Assert.IsTrue(hasMimeVersion, "Missing Mime Version header");
|
||||
//Assert.IsTrue(hasMultipartAlternative, "Missing Mime Multipart/Alternative setting");
|
||||
Assert.IsTrue(hasPlainText, "Missing Plain Text");
|
||||
Assert.IsTrue(hasHtmlText, "Missing HTML");
|
||||
Assert.IsTrue(htmlEncoded, "HTML Not encoded");
|
||||
Assert.IsTrue(textEncoded, "Text Not encoded");
|
||||
//Assert.IsTrue(hasDefaultXMailerHeader, "Missing X-Mailer Header");
|
||||
//Assert.IsTrue(hasCustomHeader1, "Missing Custom Header 1");
|
||||
//Assert.IsTrue(hasCustomHeader2, "Missing Custom Header 2");
|
||||
//Assert.AreEqual(2, quotedPrintableParts, "Expected 2 quoted printable declarations, found +ACIAKw-quotedPrintableParts);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestJapaneseHtmlAndTextB64Encoding
|
||||
[Test]
|
||||
public void TestJapaneseHtmlAndTextB64Encoding()
|
||||
{
|
||||
//SmtpServer smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
System.Text.Encoding encoding=System.Text.Encoding.GetEncoding("Shift_JIS");
|
||||
|
||||
EmailAddress japanesefromaddress=new EmailAddress(TestAddressHelper.GetFromAddress().Email, "日本語", EncodingType.Base64, encoding);
|
||||
EmailAddress japanesetoaddress=new EmailAddress(TestAddressHelper.GetToAddress().Email, "日本語", EncodingType.Base64, encoding);
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.HeaderEncoding=DotNetOpenMail.Encoding.EncodingType.Base64;
|
||||
emailmessage.HeaderCharSet=System.Text.Encoding.GetEncoding("Shift_JIS");
|
||||
|
||||
emailmessage.FromAddress=japanesefromaddress;
|
||||
emailmessage.AddToAddress(japanesetoaddress);
|
||||
emailmessage.Subject="日本語 - Base 64";
|
||||
emailmessage.TextPart=new TextAttachment("東京、日本語");
|
||||
|
||||
emailmessage.TextPart.CharSet=System.Text.Encoding.GetEncoding("Shift_JIS");
|
||||
emailmessage.TextPart.Encoding=DotNetOpenMail.Encoding.EncodingType.Base64;
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>東京、日本語</body></html>");
|
||||
|
||||
emailmessage.HtmlPart.CharSet=System.Text.Encoding.GetEncoding("Shift_JIS");
|
||||
emailmessage.HtmlPart.Encoding=DotNetOpenMail.Encoding.EncodingType.Base64;
|
||||
|
||||
emailmessage.Send(_smtpserver);
|
||||
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
log.Debug(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
|
||||
|
||||
bool toHeaderEncoded=false;
|
||||
bool fromHeaderEncoded=false;
|
||||
bool subjectHeaderEncoded=false;
|
||||
//bool htmlEncoded=false;
|
||||
//bool textEncoded=false;
|
||||
bool hasPlainText=false;
|
||||
bool hasHtmlText=false;
|
||||
|
||||
|
||||
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
//log.Debug("FOUND +ACIAKw-line);
|
||||
if (line.IndexOf("To: =?iso-2022-jp?B?k/qWe4zq?= <"+japanesetoaddress.Email+">")==0)
|
||||
{
|
||||
toHeaderEncoded=true;
|
||||
}
|
||||
if (line.IndexOf("From") == 0)
|
||||
{
|
||||
String expectedfrom="From: =?iso-2022-jp?B?k/qWe4zq?= <"+japanesefromaddress.Email+">";
|
||||
if (line.IndexOf(expectedfrom)== 0)
|
||||
{
|
||||
fromHeaderEncoded=true;
|
||||
}
|
||||
}
|
||||
if (line.IndexOf("Subject: =?iso-2022-jp?B?k/qWe4zqIC0gQmFzZSA2NA==?=")==0)
|
||||
{
|
||||
subjectHeaderEncoded=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: multipart/alternative")==0)
|
||||
{
|
||||
//htmlEncoded=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/html")==0)
|
||||
{
|
||||
hasHtmlText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/plain")==0)
|
||||
{
|
||||
hasPlainText=true;
|
||||
}
|
||||
if (line.IndexOf("X-Mailer: DotNetOpenMail " + VersionInfo.GetInstance().ToString())==0)
|
||||
{
|
||||
//hasDefaultXMailerHeader=true;
|
||||
}
|
||||
if (line.IndexOf("X-MyHeader1: my header number one") == 0)
|
||||
{
|
||||
//hasCustomHeader1=true;
|
||||
}
|
||||
if (line.IndexOf("X-MyHeader2: my header number two") == 0)
|
||||
{
|
||||
//hasCustomHeader2=true;
|
||||
}
|
||||
|
||||
// log.Debug("Line +ACIAKw-i+-": +ACIAKw-line);
|
||||
}
|
||||
Assert.IsTrue(toHeaderEncoded, "To Header not encoded");
|
||||
Assert.IsTrue(fromHeaderEncoded, "From Header not encoded");
|
||||
Assert.IsTrue(subjectHeaderEncoded, "Subject Header not encoded");
|
||||
//Assert.IsTrue(hasSubjectHeader, "Missing Subject Header");
|
||||
//Assert.IsTrue(hasMimeVersion, "Missing Mime Version header");
|
||||
//Assert.IsTrue(hasMultipartAlternative, "Missing Mime Multipart/Alternative setting");
|
||||
Assert.IsTrue(hasPlainText, "Missing Plain Text");
|
||||
Assert.IsTrue(hasHtmlText, "Missing HTML");
|
||||
//Assert.IsTrue(htmlEncoded, "HTML Not encoded");
|
||||
//Assert.IsTrue(textEncoded, "Text Not encoded");
|
||||
//Assert.IsTrue(hasDefaultXMailerHeader, "Missing X-Mailer Header");
|
||||
//Assert.IsTrue(hasCustomHeader1, "Missing Custom Header 1");
|
||||
//Assert.IsTrue(hasCustomHeader2, "Missing Custom Header 2");
|
||||
//Assert.AreEqual(2, quotedPrintableParts, "Expected 2 quoted printable declarations, found +ACIAKw-quotedPrintableParts);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,590 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Utils;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests {
|
||||
|
||||
[TestFixture]
|
||||
public class EmailMessageTests {
|
||||
|
||||
SmtpServer _smtpserver=null;
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(EmailMessageTests));
|
||||
|
||||
public EmailMessageTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
#region TestHtmlAndText
|
||||
[Test]
|
||||
public void TestHtmlAndText()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test HTML and Text";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
|
||||
emailmessage.AddCustomHeader("X-MyHeader1", "my header number one");
|
||||
emailmessage.AddCustomHeader("X-MyHeader2", "my header number two");
|
||||
|
||||
emailmessage.Send(_smtpserver);
|
||||
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
log.Debug(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
bool hasToHeader=false;
|
||||
bool hasFromHeader=false;
|
||||
bool hasSubjectHeader=false;
|
||||
bool hasMimeVersion=false;
|
||||
bool hasMultipartAlternative=false;
|
||||
bool hasPlainText=false;
|
||||
bool hasHtmlText=false;
|
||||
bool hasDefaultXMailerHeader=false;
|
||||
bool hasCustomHeader1=false;
|
||||
bool hasCustomHeader2=false;
|
||||
int quotedPrintableParts=0;
|
||||
|
||||
String expectedToAddress=TestAddressHelper.GetToAddress().Name+" <"+TestAddressHelper.GetToAddress().Email+">";
|
||||
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
if (line.IndexOf("To: "+expectedToAddress)==0)
|
||||
{
|
||||
hasToHeader=true;
|
||||
}
|
||||
if (line.IndexOf("From: "+emailmessage.FromAddress.ToString())==0)
|
||||
{
|
||||
hasFromHeader=true;
|
||||
}
|
||||
if (line.IndexOf("Subject: "+emailmessage.Subject)==0)
|
||||
{
|
||||
hasSubjectHeader=true;
|
||||
}
|
||||
if (line.IndexOf("MIME-Version: 1.0")==0)
|
||||
{
|
||||
hasMimeVersion=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: multipart/alternative;")==0)
|
||||
{
|
||||
hasMultipartAlternative=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/html")==0)
|
||||
{
|
||||
hasHtmlText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/plain")==0)
|
||||
{
|
||||
hasPlainText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Transfer-Encoding: quoted-printable")==0)
|
||||
{
|
||||
quotedPrintableParts++;
|
||||
}
|
||||
if (line.IndexOf("X-Mailer: DotNetOpenMail") == 0)
|
||||
{
|
||||
hasDefaultXMailerHeader=true;
|
||||
}
|
||||
if (line.IndexOf("X-MyHeader1: my header number one") == 0)
|
||||
{
|
||||
hasCustomHeader1=true;
|
||||
}
|
||||
if (line.IndexOf("X-MyHeader2: my header number two") == 0)
|
||||
{
|
||||
hasCustomHeader2=true;
|
||||
}
|
||||
|
||||
// log.Debug("Line "+i+": "+line);
|
||||
}
|
||||
Assert.IsTrue(hasToHeader, "Missing TO Header");
|
||||
Assert.IsTrue(hasFromHeader, "Missing FROM Header");
|
||||
Assert.IsTrue(hasSubjectHeader, "Missing Subject Header");
|
||||
Assert.IsTrue(hasMimeVersion, "Missing Mime Version header");
|
||||
Assert.IsTrue(hasMultipartAlternative, "Missing Mime Multipart/Alternative setting");
|
||||
Assert.IsTrue(hasPlainText, "Missing Plain Text");
|
||||
Assert.IsTrue(hasHtmlText, "Missing HTML");
|
||||
Assert.IsTrue(hasDefaultXMailerHeader, "Missing X-Mailer Header");
|
||||
Assert.IsTrue(hasCustomHeader1, "Missing Custom Header 1");
|
||||
Assert.IsTrue(hasCustomHeader2, "Missing Custom Header 2");
|
||||
Assert.AreEqual(2, quotedPrintableParts, "Expected 2 quoted printable declarations, found "+quotedPrintableParts);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestGraphicAttachment
|
||||
[Test]
|
||||
public void TestGraphicAttachment()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test HTML+Text+Graphic";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
FileInfo fileinfo=new FileInfo(@"..\..\TestFiles\grover.jpg");
|
||||
Assert.IsTrue(fileinfo.Exists);
|
||||
FileAttachment fileattachment=new FileAttachment(fileinfo);
|
||||
|
||||
fileattachment.ContentType="image/jpeg";
|
||||
emailmessage.AddMixedAttachment(fileattachment);
|
||||
//emailmessage.Send(_smtpserver);
|
||||
//log.Debug("MESSAGE: "+emailmessage.ToDataString());
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
bool hasMimeVersion=false;
|
||||
bool hasMixedHeader=false;
|
||||
bool mixedHeaderComesFirst=false;
|
||||
bool hasMultipartAlternative=false;
|
||||
bool hasPlainText=false;
|
||||
bool hasHtmlText=false;
|
||||
bool hasAttachment=false;
|
||||
bool hasRelatedHeader=false;
|
||||
int quotedPrintableParts=0;
|
||||
|
||||
String expectedToAddress=TestAddressHelper.GetToAddress().Name+" <"+TestAddressHelper.GetToAddress().Email+">";
|
||||
//log.Debug("To Address is "+expectedToAddress);
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
if (line.IndexOf("Content-Type: multipart/mixed")==0)
|
||||
{
|
||||
hasMixedHeader=true;
|
||||
if (!hasMultipartAlternative)
|
||||
{
|
||||
mixedHeaderComesFirst=true;
|
||||
}
|
||||
}
|
||||
if (line.IndexOf("MIME-Version: 1.0")==0)
|
||||
{
|
||||
hasMimeVersion=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: multipart/alternative;")==0)
|
||||
{
|
||||
hasMultipartAlternative=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/html")==0)
|
||||
{
|
||||
hasHtmlText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/plain")==0)
|
||||
{
|
||||
hasPlainText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: image/jpeg")==0)
|
||||
{
|
||||
hasAttachment=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Transfer-Encoding: quoted-printable")==0)
|
||||
{
|
||||
quotedPrintableParts++;
|
||||
}
|
||||
if (line.IndexOf("/9j/4AAQSkZJRgABAQEASABIAAD/")==0)
|
||||
{
|
||||
hasAttachment=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: multipart/related")>=0)
|
||||
{
|
||||
hasRelatedHeader=true;
|
||||
}
|
||||
//log.Debug("Line "+i+": "+line);
|
||||
}
|
||||
Assert.IsTrue(hasMixedHeader, "Missing multipart/mixed header");
|
||||
Assert.IsTrue(hasMimeVersion, "Missing Mime Version header");
|
||||
Assert.IsTrue(mixedHeaderComesFirst, "The mixed header should come first");
|
||||
Assert.IsTrue(hasMultipartAlternative, "Missing Mime Multipart/Alternative setting");
|
||||
Assert.IsTrue(hasPlainText, "Missing Plain Text");
|
||||
Assert.IsTrue(hasHtmlText, "Missing HTML");
|
||||
Assert.IsTrue(hasAttachment, "Missing the base64 Attachment");
|
||||
Assert.IsFalse(hasRelatedHeader, "Should not have a related header.");
|
||||
Assert.AreEqual(2, quotedPrintableParts, "Expected 2 quoted printable declarations, found "+quotedPrintableParts);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestRelatedAndMixedAttachments
|
||||
[Test]
|
||||
public void TestRelatedAndMixedAttachments()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test HTML+Text+Graphic";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br> \r\nis the<br><img src=\"cid:mycontentid@rhombus\"> \r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
FileInfo relatedfileinfo=new FileInfo(@"..\..\TestFiles\grover.jpg");
|
||||
FileInfo mixedfileinfo=new FileInfo(@"..\..\TestFiles\groverUpsideDown.jpg");
|
||||
Assert.IsTrue(relatedfileinfo.Exists);
|
||||
Assert.IsTrue(mixedfileinfo.Exists);
|
||||
FileAttachment relatedfileattachment=new FileAttachment(relatedfileinfo,"mycontentid@rhombus");
|
||||
relatedfileattachment.ContentType="image/jpeg";
|
||||
FileAttachment mixedfileattachment=new FileAttachment(mixedfileinfo);
|
||||
mixedfileattachment.ContentType="image/jpeg";
|
||||
emailmessage.AddRelatedAttachment(relatedfileattachment);
|
||||
emailmessage.AddMixedAttachment(mixedfileattachment);
|
||||
//emailmessage.Send(_smtpserver);
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
bool hasMimeVersion=false;
|
||||
bool hasMixedHeader=false;
|
||||
bool mixedHeaderComesFirst=false;
|
||||
bool hasMultipartAlternative=false;
|
||||
bool hasPlainText=false;
|
||||
bool hasHtmlText=false;
|
||||
bool hasAttachment=false;
|
||||
bool hasRelatedHeader=false;
|
||||
int quotedPrintableParts=0;
|
||||
|
||||
String expectedToAddress=TestAddressHelper.GetToAddress().Name+" <"+TestAddressHelper.GetToAddress().Email+">";
|
||||
//log.Debug("To Address is "+expectedToAddress);
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
if (line.IndexOf("Content-Type: multipart/mixed")==0)
|
||||
{
|
||||
hasMixedHeader=true;
|
||||
if (!hasMultipartAlternative && !hasRelatedHeader)
|
||||
{
|
||||
mixedHeaderComesFirst=true;
|
||||
}
|
||||
}
|
||||
if (line.IndexOf("MIME-Version: 1.0")==0)
|
||||
{
|
||||
hasMimeVersion=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: multipart/alternative;")==0)
|
||||
{
|
||||
hasMultipartAlternative=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/html")==0)
|
||||
{
|
||||
hasHtmlText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/plain")==0)
|
||||
{
|
||||
hasPlainText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: image/jpeg")==0)
|
||||
{
|
||||
hasAttachment=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Transfer-Encoding: quoted-printable")==0)
|
||||
{
|
||||
quotedPrintableParts++;
|
||||
}
|
||||
if (line.IndexOf("/9j/4AAQSkZJRgABAQEASABIAAD/")==0)
|
||||
{
|
||||
hasAttachment=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: multipart/related")>=0)
|
||||
{
|
||||
hasRelatedHeader=true;
|
||||
}
|
||||
//log.Debug("Line "+i+": "+line);
|
||||
}
|
||||
Assert.IsTrue(hasMixedHeader, "Missing multipart/mixed header");
|
||||
Assert.IsTrue(hasMimeVersion, "Missing Mime Version header");
|
||||
Assert.IsTrue(mixedHeaderComesFirst, "The mixed header should come first");
|
||||
Assert.IsTrue(hasMultipartAlternative, "Missing Mime Multipart/Alternative setting");
|
||||
Assert.IsTrue(hasPlainText, "Missing Plain Text");
|
||||
Assert.IsTrue(hasHtmlText, "Missing HTML");
|
||||
Assert.IsTrue(hasAttachment, "Missing the base64 Attachment");
|
||||
Assert.IsTrue(hasRelatedHeader, "Missing the related header.");
|
||||
Assert.AreEqual(2, quotedPrintableParts, "Expected 2 quoted printable declarations, found "+quotedPrintableParts);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestRelatedAttachments
|
||||
[Test]
|
||||
public void TestRelatedAttachments()
|
||||
{
|
||||
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test Related Graphic";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br><img src=\"cid:mycontentid\">\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
FileInfo relatedfileinfo=new FileInfo(@"..\..\TestFiles\grover.jpg");
|
||||
Assert.IsTrue(relatedfileinfo.Exists);
|
||||
FileAttachment relatedfileattachment=new FileAttachment(relatedfileinfo,"mycontentid");
|
||||
relatedfileattachment.ContentType="image/jpeg";
|
||||
emailmessage.AddRelatedAttachment(relatedfileattachment);
|
||||
//emailmessage.Send(_smtpserver);
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
bool hasMimeVersion=false;
|
||||
bool hasMixedHeader=false;
|
||||
bool relatedHeaderComesFirst=false;
|
||||
bool hasMultipartAlternative=false;
|
||||
bool hasPlainText=false;
|
||||
bool hasHtmlText=false;
|
||||
bool hasAttachment=false;
|
||||
bool hasRelatedHeader=false;
|
||||
int quotedPrintableParts=0;
|
||||
|
||||
String expectedToAddress=TestAddressHelper.GetToAddress().Name+" <"+TestAddressHelper.GetToAddress().Email+">";
|
||||
//log.Debug("To Address is "+expectedToAddress);
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
if (line.IndexOf("Content-Type: multipart/mixed")==0)
|
||||
{
|
||||
hasMixedHeader=true;
|
||||
|
||||
}
|
||||
|
||||
if (line.IndexOf("MIME-Version: 1.0")==0)
|
||||
{
|
||||
hasMimeVersion=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: multipart/alternative;")==0)
|
||||
{
|
||||
hasMultipartAlternative=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/html")==0)
|
||||
{
|
||||
hasHtmlText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: text/plain")==0)
|
||||
{
|
||||
hasPlainText=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: image/jpeg")==0)
|
||||
{
|
||||
hasAttachment=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Transfer-Encoding: quoted-printable")==0)
|
||||
{
|
||||
quotedPrintableParts++;
|
||||
}
|
||||
if (line.IndexOf("/9j/4AAQSkZJRgABAQEASABIAAD/")==0)
|
||||
{
|
||||
hasAttachment=true;
|
||||
}
|
||||
if (line.IndexOf("Content-Type: multipart/related")>=0)
|
||||
{
|
||||
hasRelatedHeader=true;
|
||||
if (!hasMultipartAlternative && !hasMixedHeader)
|
||||
{
|
||||
relatedHeaderComesFirst=true;
|
||||
}
|
||||
}
|
||||
//log.Debug("Line "+i+": "+line);
|
||||
}
|
||||
Assert.IsFalse(hasMixedHeader, "Should not have a multipart/mixed header");
|
||||
Assert.IsTrue(hasMimeVersion, "Missing Mime Version header");
|
||||
Assert.IsTrue(relatedHeaderComesFirst, "The related header should come first");
|
||||
Assert.IsTrue(hasMultipartAlternative, "Missing Mime Multipart/Alternative setting");
|
||||
Assert.IsTrue(hasPlainText, "Missing Plain Text");
|
||||
Assert.IsTrue(hasHtmlText, "Missing HTML");
|
||||
Assert.IsTrue(hasAttachment, "Missing the base64 Attachment");
|
||||
Assert.IsTrue(hasRelatedHeader, "Missing the related header.");
|
||||
Assert.AreEqual(2, quotedPrintableParts, "Expected 2 quoted printable declarations, found "+quotedPrintableParts);
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestHeaders
|
||||
[Test]
|
||||
public void TestHeaders()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddCcAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddCcAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddBccAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddBccAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="Test Headers";
|
||||
emailmessage.XMailer="NUnit Test Mailer";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
bool hasToHeader=false;
|
||||
bool hasFromHeader=false;
|
||||
bool hasSubjectHeader=false;
|
||||
bool hasBccHeader=false;
|
||||
bool hasCcHeader=false;
|
||||
bool hasXMailerHeader=false;
|
||||
|
||||
String expectedToAddress=TestAddressHelper.GetToAddress().Name+" <"+TestAddressHelper.GetToAddress().Email+">";
|
||||
|
||||
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
if (line.IndexOf("To: "+expectedToAddress+", "+expectedToAddress)==0)
|
||||
{
|
||||
hasToHeader=true;
|
||||
}
|
||||
if (line.IndexOf("Cc: "+expectedToAddress+", "+expectedToAddress)==0)
|
||||
{
|
||||
hasCcHeader=true;
|
||||
}
|
||||
if (line.IndexOf("Bcc: "+expectedToAddress+", "+expectedToAddress)==0)
|
||||
{
|
||||
hasBccHeader=true;
|
||||
}
|
||||
|
||||
if (line.IndexOf("From: "+emailmessage.FromAddress.ToString())==0)
|
||||
{
|
||||
hasFromHeader=true;
|
||||
}
|
||||
if (line.IndexOf("Subject: "+emailmessage.Subject)==0)
|
||||
{
|
||||
hasSubjectHeader=true;
|
||||
}
|
||||
if (line.IndexOf("X-Mailer: NUnit Test Mailer")==0)
|
||||
{
|
||||
hasXMailerHeader=true;
|
||||
}
|
||||
|
||||
}
|
||||
Assert.IsTrue(hasToHeader, "Missing TO Header");
|
||||
Assert.IsTrue(hasFromHeader, "Missing FROM Header");
|
||||
Assert.IsTrue(hasSubjectHeader, "Missing Subject Header");
|
||||
Assert.IsTrue(hasCcHeader, "Missing Cc Header");
|
||||
Assert.IsFalse(hasBccHeader, "Bcc Header Shouldn't appear");
|
||||
Assert.IsTrue(hasXMailerHeader, "Missing XMailer Header");
|
||||
//emailmessage.Send(_smtpserver);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestLongSubjectEncoded
|
||||
[Test]
|
||||
public void TestLongSubjectEncoded()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddCcAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddBccAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="Join our Group's Fundraising Efforts é test test test Gulf Little League";
|
||||
emailmessage.HeaderEncoding=DotNetOpenMail.Encoding.EncodingType.QuotedPrintable;
|
||||
emailmessage.XMailer="NUnit Test Mailer";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
|
||||
String content=emailmessage.ToDataString();
|
||||
emailmessage.Send(_smtpserver);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestExtraHeader
|
||||
[Test]
|
||||
public void TestExtraHeader()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddCcAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.AddBccAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="Extra Header";
|
||||
emailmessage.HeaderEncoding=DotNetOpenMail.Encoding.EncodingType.QuotedPrintable;
|
||||
emailmessage.XMailer="NUnit Test Mailer";
|
||||
emailmessage.AddCustomHeader("MyHeader", "Value");
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
|
||||
String content=emailmessage.ToDataString();
|
||||
emailmessage.Send(_smtpserver);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestMissingFrom
|
||||
[Test]
|
||||
public void TestMissingFrom()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
try
|
||||
{
|
||||
emailmessage.Send(_smtpserver);
|
||||
Assert.Fail("This should throw an error if no from address");
|
||||
}
|
||||
catch (MailException ex)
|
||||
{
|
||||
log.Debug("Ignoring exception "+ex.Message);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
using log4net;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace DotNetOpenMailTests.Encoding
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class Base64EncoderTests
|
||||
{
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Base64EncoderTests));
|
||||
|
||||
public Base64EncoderTests()
|
||||
{
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SimpleTest()
|
||||
{
|
||||
String setofchars=""+(char)0x01 +(char)0x02+(char)0x03;
|
||||
Base64Encoder base64encoder=Base64Encoder.GetInstance();
|
||||
StringReader sr=new StringReader(setofchars);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
StringWriter sw=new StringWriter(sb);
|
||||
|
||||
base64encoder.Encode(sr, sw, System.Text.Encoding.GetEncoding("iso-8859-1"));
|
||||
log.Debug(sb.ToString());
|
||||
Assert.AreEqual("AQID", sb.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LineLengthTest()
|
||||
{
|
||||
String line="12345678901234567890123456789012345678901234567890123456789012345678901234567890";
|
||||
String expectedresult="MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3\r\nODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTA=";
|
||||
Base64Encoder base64=Base64Encoder.GetInstance();
|
||||
StringReader sr=new StringReader(line);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
StringWriter sw=new StringWriter(sb);
|
||||
base64.Encode(sr, sw, System.Text.Encoding.GetEncoding("iso-8859-1"));
|
||||
log.Debug(sb.ToString());
|
||||
Assert.AreEqual(expectedresult, sb.ToString());
|
||||
|
||||
Assert.AreEqual(expectedresult, base64.EncodeString(line, System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HeaderEncodingTest()
|
||||
{
|
||||
Base64Encoder base64=Base64Encoder.GetInstance();
|
||||
String result=base64.EncodeHeaderString("Test", "helloøæô", System.Text.Encoding.GetEncoding("iso-8859-1"), false);
|
||||
log.Debug("RESULT IS "+result);
|
||||
Assert.AreEqual("=?iso-8859-1?B?aGVsbG/45vQ=?=", result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests.Encoding {
|
||||
|
||||
[TestFixture]
|
||||
public class EightBitEncoderTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(EightBitEncoderTests));
|
||||
|
||||
public EightBitEncoderTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
[Test]
|
||||
public void SimpleTest()
|
||||
{
|
||||
// this tests that the 8bit encoder does nothing
|
||||
String setofchars=Get256Chars();
|
||||
EightBitEncoder eightbitencoder=EightBitEncoder.GetInstance();
|
||||
StringReader sr=new StringReader(setofchars);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
StringWriter sw=new StringWriter(sb);
|
||||
|
||||
eightbitencoder.Encode(sr, sw, System.Text.Encoding.GetEncoding("iso-8859-1"));
|
||||
Assert.AreEqual(setofchars, sb.ToString());
|
||||
}
|
||||
|
||||
private String Get256Chars()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
for (int i=0; i<256; i++)
|
||||
{
|
||||
sb.Append((char) i);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#region TestFor8BitHeader
|
||||
[Test]
|
||||
public void TestFor8BitHeader()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
emailmessage.HeaderCharSet=System.Text.ASCIIEncoding.ASCII;
|
||||
emailmessage.HeaderEncoding=DotNetOpenMail.Encoding.EncodingType.EightBit;
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test HTML and Text";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.TextPart.CharSet=System.Text.ASCIIEncoding.ASCII;
|
||||
emailmessage.TextPart.Encoding=DotNetOpenMail.Encoding.EncodingType.EightBit;
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
emailmessage.HtmlPart.CharSet=System.Text.ASCIIEncoding.ASCII;
|
||||
emailmessage.HtmlPart.Encoding=DotNetOpenMail.Encoding.EncodingType.EightBit;
|
||||
|
||||
//emailmessage.Send(_smtpserver);
|
||||
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
log.Debug(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
|
||||
String expectedToAddress=TestAddressHelper.GetToAddress().Name+" <"+TestAddressHelper.GetToAddress().Email+">";
|
||||
int has8Bit=0;
|
||||
int hasUSASCII=0;
|
||||
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
if (line.IndexOf("Content-Transfer-Encoding: 8bit")==0)
|
||||
{
|
||||
has8Bit++;
|
||||
}
|
||||
if (line.IndexOf("charset=\"us-ascii\"")>0)
|
||||
{
|
||||
hasUSASCII++;
|
||||
}
|
||||
log.Debug("Line "+i+": "+line);
|
||||
}
|
||||
Assert.AreEqual(2, has8Bit, "Not enough 8bit lines");
|
||||
Assert.AreEqual(2, hasUSASCII, "Not enough us-ascii lines");
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests.Encoding {
|
||||
|
||||
[TestFixture]
|
||||
public class QPEncoderTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(QPEncoderTests));
|
||||
|
||||
public QPEncoderTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
[Test]
|
||||
public void SimpleTest() {
|
||||
//String setofchars=Get256Chars();
|
||||
String setofchars=""+(char)0x01 +(char)0x02;
|
||||
QPEncoder qpencoder=QPEncoder.GetInstance();
|
||||
StringReader sr=new StringReader(setofchars);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
StringWriter sw=new StringWriter(sb);
|
||||
|
||||
qpencoder.Encode(sr, sw, System.Text.Encoding.GetEncoding("iso-8859-1"));
|
||||
Assert.AreEqual("=01=02", sb.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LineLengthTest()
|
||||
{
|
||||
String line="12345678901234567890123456789012345678901234567890123456789012345678901234567890";
|
||||
String expectedresult="1234567890123456789012345678901234567890123456789012345678901234567890123456=\r\n7890";
|
||||
|
||||
QPEncoder qpencoder=QPEncoder.GetInstance();
|
||||
StringReader sr=new StringReader(line);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
StringWriter sw=new StringWriter(sb);
|
||||
qpencoder.Encode(sr, sw, System.Text.Encoding.GetEncoding("iso-8859-1"));
|
||||
Assert.AreEqual(expectedresult, sb.ToString());
|
||||
|
||||
Assert.AreEqual(expectedresult, qpencoder.EncodeString(line, System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EndOfLineSpacesTest()
|
||||
{
|
||||
QPEncoder qpencoder=QPEncoder.GetInstance();
|
||||
|
||||
Assert.AreEqual("123 456 7890=20=20=20=20=20",qpencoder.EncodeString("123 456 7890 ", System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
Assert.AreEqual("=20=20=20=20=20",qpencoder.EncodeString(" ", System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
Assert.AreEqual("123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456=\r\n7890=20=20=20",qpencoder.EncodeString("123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234567890 ", System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
Assert.AreEqual("123456789 123456789 123456789 123456789 123456789 123456789 123456789=\r\n=20=20=20=20=20=20=20=20=20=20=20",qpencoder.EncodeString("123456789 123456789 123456789 123456789 123456789 123456789 123456789 ", System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
Assert.AreEqual("123456789 123456789 123456789 123456789 123456789 123456789 123456789=\r\n=09=09=09=09=09=09=09=09=09=09=09",qpencoder.EncodeString("123456789 123456789 123456789 123456789 123456789 123456789 123456789 ", System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnixAndMacCRLF()
|
||||
{
|
||||
QPEncoder qpencoder=QPEncoder.GetInstance();
|
||||
|
||||
Assert.AreEqual("123\r\n456\r\n789",qpencoder.EncodeString("123\r456\r789\r", System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
Assert.AreEqual("123\r\n456\r\n789",qpencoder.EncodeString("123\n456\n789\n", System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test256Chars()
|
||||
{
|
||||
QPEncoder qpencoder=QPEncoder.GetInstance();
|
||||
|
||||
String expected="=00=01=02=03=04=05=06=07=08=09\r\n"+
|
||||
"=0B=0C\r\n"+
|
||||
"=0E=0F=10=11=12=13=14=15=16=17=18=19=1A=1B=1C=1D=1E=1F !\"#$%&'()*+,-./012345=\r\n"+
|
||||
"6789:;<=3D>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~=\r\n"+
|
||||
"=7F=80=81=82=83=84=85=86=87=88=89=8A=8B=8C=8D=8E=8F=90=91=92=93=94=95=96=97=98=\r\n"+
|
||||
"=99=9A=9B=9C=9D=9E=9F=A0=A1=A2=A3=A4=A5=A6=A7=A8=A9=AA=AB=AC=AD=AE=AF=B0=B1=B2=\r\n"+
|
||||
"=B3=B4=B5=B6=B7=B8=B9=BA=BB=BC=BD=BE=BF=C0=C1=C2=C3=C4=C5=C6=C7=C8=C9=CA=CB=CC=\r\n"+
|
||||
"=CD=CE=CF=D0=D1=D2=D3=D4=D5=D6=D7=D8=D9=DA=DB=DC=DD=DE=DF=E0=E1=E2=E3=E4=E5=E6=\r\n"+
|
||||
"=E7=E8=E9=EA=EB=EC=ED=EE=EF=F0=F1=F2=F3=F4=F5=F6=F7=F8=F9=FA=FB=FC=FD=FE=FF";
|
||||
|
||||
Assert.AreEqual(256,Get256Chars().Length);
|
||||
Assert.AreEqual(expected, qpencoder.EncodeString(Get256Chars(), System.Text.Encoding.GetEncoding("iso-8859-1")));
|
||||
|
||||
}
|
||||
|
||||
private String Get256Chars()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
for (int i=0; i<256; i++)
|
||||
{
|
||||
sb.Append((char) i);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HeaderEncodingTest()
|
||||
{
|
||||
QPEncoder qpencoder=QPEncoder.GetInstance();
|
||||
|
||||
Assert.AreEqual("=?iso-8859-1?Q?hello=F8=E6=F4?=", qpencoder.EncodeHeaderString("Test", "helloøæô", System.Text.Encoding.GetEncoding("iso-8859-1"), false));
|
||||
Assert.AreEqual("=?iso-8859-1?Q?hello=20there=20=F8=E6=F4?=", qpencoder.EncodeHeaderString("Test", "hello there øæô", System.Text.Encoding.GetEncoding("iso-8859-1"), false));
|
||||
Assert.AreEqual("hello there", qpencoder.EncodeHeaderString("Test", "hello there", System.Text.Encoding.GetEncoding("iso-8859-1"), false));
|
||||
Assert.AreEqual("=?iso-8859-1?Q?hello=20there?=", qpencoder.EncodeHeaderString("Test", "hello there", System.Text.Encoding.GetEncoding("iso-8859-1"), true));
|
||||
Assert.AreEqual("=?iso-8859-1?Q?TSpecials=20Equals=20=3D=20QuestionMark=3FEnd?=", qpencoder.EncodeHeaderString("Test", "TSpecials Equals = QuestionMark?End", System.Text.Encoding.GetEncoding("iso-8859-1"), true));
|
||||
Assert.AreEqual("=?iso-8859-1?Q?en=20to,=20sn=F8r=20min=20sko,=20tre=20fire=20kom=20E?=\r\n\t=?iso-8859-1?Q?lvire,=20fem=20seks=20tegn=20en=20heks,=20sju=20=E5tte?=\r\n\t=?iso-8859-1?Q?=20ris=20til=20en=20rotte?=", qpencoder.EncodeHeaderString("Test", "en to, snør min sko, tre fire kom Elvire, fem seks tegn en heks, sju åtte ris til en rotte",
|
||||
System.Text.Encoding.GetEncoding("iso-8859-1"), true));
|
||||
|
||||
Assert.AreEqual("=?koi8-r?Q?n=CE=C5=D3=CB=CF=CC=D8=CB=CF=20=D3=D4=D2=CF=CB=20=D0=CF?=\r\n\t=?koi8-r?Q?=20=D2=D5=D3=D3=CB=C9=3F?=", qpencoder.EncodeHeaderString("Test", "nнесколько строк по русски?", System.Text.Encoding.GetEncoding("koi8-r"), true));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
[Test]
|
||||
public void KOI8_QP_Tests()
|
||||
{
|
||||
EmailMessage msg = new EmailMessage();
|
||||
msg.FromAddress = new EmailAddress("pietrovich@talk.test","pietrovich");
|
||||
msg.ToAddresses.Add(new EmailAddress("pietrovich@talk.test","pietrovich"));
|
||||
msg.Subject = "ошибочка?";
|
||||
msg.HeaderCharSet = Encoding.GetEncoding("windows-1251");
|
||||
TextAttachment ta = new TextAttachment("\r\nнесколько строк по русски");
|
||||
ta.CharSet = Encoding.GetEncoding("windows-1251");
|
||||
msg.TextPart = ta;
|
||||
Console.WriteLine(msg.ToDataString());
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests.Encoding {
|
||||
|
||||
[TestFixture]
|
||||
public class SevenBitEncoderTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SevenBitEncoderTests));
|
||||
|
||||
public SevenBitEncoderTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
[Test]
|
||||
public void SimpleTest()
|
||||
{
|
||||
// this tests that the 8bit encoder does nothing
|
||||
String setofchars=Get256Chars();
|
||||
SevenBitEncoder sevenbitencoder=SevenBitEncoder.GetInstance();
|
||||
StringReader sr=new StringReader(setofchars);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
StringWriter sw=new StringWriter(sb);
|
||||
|
||||
sevenbitencoder.Encode(sr, sw, System.Text.Encoding.GetEncoding("iso-8859-1"));
|
||||
Assert.AreEqual(setofchars, sb.ToString());
|
||||
}
|
||||
|
||||
private String Get256Chars()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
for (int i=0; i<256; i++)
|
||||
{
|
||||
sb.Append((char) i);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#region TestFor7BitHeader
|
||||
[Test]
|
||||
public void TestFor7BitHeader()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
emailmessage.HeaderCharSet=System.Text.ASCIIEncoding.ASCII;
|
||||
emailmessage.HeaderEncoding=DotNetOpenMail.Encoding.EncodingType.SevenBit;
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test HTML and Text";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.TextPart.CharSet=System.Text.ASCIIEncoding.ASCII;
|
||||
emailmessage.TextPart.Encoding=DotNetOpenMail.Encoding.EncodingType.SevenBit;
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
emailmessage.HtmlPart.CharSet=System.Text.ASCIIEncoding.ASCII;
|
||||
emailmessage.HtmlPart.Encoding=DotNetOpenMail.Encoding.EncodingType.SevenBit;
|
||||
|
||||
//emailmessage.Send(_smtpserver);
|
||||
|
||||
String content=emailmessage.ToDataString();
|
||||
StringReader sr=new StringReader(content);
|
||||
//log.Debug(content);
|
||||
|
||||
int i=0;
|
||||
String line=null;
|
||||
|
||||
String expectedToAddress=TestAddressHelper.GetToAddress().Name+" <"+TestAddressHelper.GetToAddress().Email+">";
|
||||
int has7Bit=0;
|
||||
int hasUSASCII=0;
|
||||
|
||||
while ((line=sr.ReadLine())!=null)
|
||||
{
|
||||
i++;
|
||||
if (line.IndexOf("Content-Transfer-Encoding: 7bit")==0)
|
||||
{
|
||||
has7Bit++;
|
||||
}
|
||||
if (line.IndexOf("charset=\"us-ascii\"")>0)
|
||||
{
|
||||
hasUSASCII++;
|
||||
}
|
||||
//log.Debug("Line "+i+": "+line);
|
||||
}
|
||||
Assert.AreEqual(2, has7Bit, "Not enough 7bit lines");
|
||||
Assert.AreEqual(2, hasUSASCII, "Not enough us-ascii lines");
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using DotNetOpenMail; // change to tested dir
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests {
|
||||
|
||||
[TestFixture]
|
||||
public class ExampleTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ExampleTests));
|
||||
|
||||
public ExampleTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
[Test]
|
||||
public void TestOne()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject="Missed you";
|
||||
|
||||
emailmessage.TextPart=new TextAttachment("Just checking where "+
|
||||
"you were last night.\r\nSend me a note!\r\n\r\n-Charles");
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>"+
|
||||
"<p>Just checking up on where you were last night.</p>\r\n"+
|
||||
"<p>Send me a note!</p>\r\n\r\n"+
|
||||
"<p>-Charles</p></body></html>");
|
||||
|
||||
SmtpServer smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
//smtpserver.CaptureSmtpConversation=true;
|
||||
|
||||
try
|
||||
{
|
||||
emailmessage.Send(smtpserver);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
//log.Debug(smtpserver.GetSmtpConversation());
|
||||
//Assert.IsNotNull(smtpserver.GetSmtpConversation());
|
||||
//smtpserver.CaptureSmtpConversation=false;
|
||||
}
|
||||
}
|
||||
[Test]
|
||||
public void TestTwo()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject="A photo of hawthornes";
|
||||
|
||||
emailmessage.TextPart=new TextAttachment("This photo requires a better email reader.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>"+
|
||||
"<p>Note to self: look at this photo again in 30 years.</p>"+
|
||||
"<p><img src=\"cid:hawthornes\" alt=\"Hawthorne bush\"/></p>"+
|
||||
"<p>-Marcel</p>");
|
||||
|
||||
FileInfo relatedfileinfo=new FileInfo(@"..\..\TestFiles\grover.jpg");
|
||||
|
||||
FileAttachment relatedfileattachment=new FileAttachment(relatedfileinfo,"hawthornes");
|
||||
|
||||
relatedfileattachment.ContentType="image/jpeg";
|
||||
|
||||
emailmessage.AddRelatedAttachment(relatedfileattachment);
|
||||
|
||||
SmtpServer smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
emailmessage.Send(smtpserver);
|
||||
//Assert.IsNull(smtpserver.GetSmtpConversation());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestThree()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject="Something has come up";
|
||||
|
||||
emailmessage.TextPart=new TextAttachment("I regret that something has "+
|
||||
"come up unexpectedly,\r\n"+
|
||||
"and I must postpone our meeting.\r\n\r\n"+
|
||||
"Please read the 20 pages of my thoughts on this in the attached\r\n"+
|
||||
"PDF file.\r\n\r\n-Marcel");
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<p>I regret that something "+
|
||||
"has come up unexpectedly,\r\n"+
|
||||
"and I must postpone our meeting.</p>\r\n"+
|
||||
"<p>Please read the 20 pages of my thoughts on this in the attached\r\n"+
|
||||
"PDF file.</p>\r\n<p>-Marcel</p>");
|
||||
|
||||
FileAttachment fileattachment=new FileAttachment(new FileInfo(@"..\..\TestFiles\grover.jpg"));
|
||||
|
||||
fileattachment.ContentType="image/jpeg";
|
||||
|
||||
emailmessage.AddMixedAttachment(fileattachment);
|
||||
|
||||
emailmessage.Send(TestAddressHelper.GetSmtpServer());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Utils;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class FileAttachmentTests
|
||||
{
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(FileAttachmentTests));
|
||||
|
||||
public FileAttachmentTests()
|
||||
{
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestFileFromStream()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject="Here's your license";
|
||||
|
||||
emailmessage.TextPart=new TextAttachment("This is a license.\r\n\r\n"+
|
||||
"We will spend your money on a new plasma TV.");
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>"+
|
||||
"<p>This is a license.</p>\r\n"+
|
||||
"<p>We will spend your money on a new <i>plasma TV</i>.</p>\r\n"+
|
||||
"</body></html>");
|
||||
|
||||
MemoryStream stream=new MemoryStream();
|
||||
StreamWriter sw=new StreamWriter(stream);
|
||||
sw.WriteLine("this is some test data 1");
|
||||
sw.WriteLine("this is some test data 2");
|
||||
sw.WriteLine("this is some test data 3");
|
||||
sw.WriteLine("this is some test data 4");
|
||||
sw.Flush();
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
//BinaryReader br=new BinaryReader(stream);
|
||||
|
||||
FileAttachment fileAttachment=new FileAttachment(new StreamReader(stream));
|
||||
|
||||
//fileAttachment.ContentType
|
||||
fileAttachment.FileName="License.txt";
|
||||
fileAttachment.CharSet=System.Text.Encoding.ASCII;
|
||||
fileAttachment.ContentType="text/plain";
|
||||
emailmessage.AddMixedAttachment(fileAttachment);
|
||||
|
||||
//emailmessage.Send(TestAddressHelper.GetSmtpServer());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBinaryFileFromStream()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject="Here's your file";
|
||||
|
||||
emailmessage.TextPart=new TextAttachment("This a jpeg.");
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>"+
|
||||
"<p>This a jpeg.</p>\r\n");
|
||||
|
||||
FileInfo fileinfo=new FileInfo(@"..\..\TestFiles\grover.jpg");
|
||||
//FileInfo fileinfo=new FileInfo(@"..\..\TestFiles\casingTheJoint.jpg");
|
||||
FileStream filestream = fileinfo.OpenRead();
|
||||
|
||||
MemoryStream stream=new MemoryStream();
|
||||
|
||||
StreamWriter sw=new StreamWriter(stream);
|
||||
|
||||
sw.Flush();
|
||||
|
||||
//BinaryReader br=new BinaryReader(stream);
|
||||
|
||||
BinaryReader br=new BinaryReader(filestream);
|
||||
byte[] bytes=br.ReadBytes((int) fileinfo.Length);
|
||||
br.Close();
|
||||
|
||||
FileAttachment fileAttachment=new FileAttachment(bytes);
|
||||
|
||||
//fileAttachment.ContentType
|
||||
fileAttachment.FileName="grover.jpg";
|
||||
fileAttachment.ContentType="image/jpeg";
|
||||
emailmessage.AddMixedAttachment(fileAttachment);
|
||||
|
||||
emailmessage.Send(TestAddressHelper.GetSmtpServer());
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestFileFromString()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject="Here's your license";
|
||||
|
||||
emailmessage.TextPart=new TextAttachment("This is a license.\r\n\r\n"+
|
||||
"We will spend your money on a new plasma TV.");
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>"+
|
||||
"<p>This is a license.</p>\r\n"+
|
||||
"<p>We will spend your money on a new <i>plasma TV</i>.</p>\r\n"+
|
||||
"</body></html>");
|
||||
|
||||
String content="This is String Line 1\r\nThis is String Line 2";
|
||||
|
||||
FileAttachment fileAttachment=new FileAttachment(content);
|
||||
|
||||
//fileAttachment.ContentType
|
||||
fileAttachment.FileName="License.txt";
|
||||
fileAttachment.CharSet=System.Text.Encoding.ASCII;
|
||||
fileAttachment.ContentType="text/plain";
|
||||
fileAttachment.Encoding=DotNetOpenMail.Encoding.EncodingType.SevenBit;
|
||||
emailmessage.AddMixedAttachment(fileAttachment);
|
||||
|
||||
//emailmessage.Send(TestAddressHelper.GetSmtpServer());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLargerBinaryFileFromStream()
|
||||
{
|
||||
|
||||
String filename="casingTheJoint.jpg";
|
||||
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject="Here's your file";
|
||||
|
||||
emailmessage.TextPart=new TextAttachment("This a zip file.");
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>"+
|
||||
"<p>This a zip file.</p>\r\n");
|
||||
|
||||
FileInfo fileinfo=new FileInfo(@"..\..\TestFiles\"+filename);
|
||||
FileStream filestream = fileinfo.OpenRead();
|
||||
|
||||
MemoryStream stream=new MemoryStream();
|
||||
|
||||
StreamWriter sw=new StreamWriter(stream);
|
||||
|
||||
sw.Flush();
|
||||
|
||||
//BinaryReader br=new BinaryReader(stream);
|
||||
|
||||
BinaryReader br=new BinaryReader(filestream);
|
||||
byte[] bytes=br.ReadBytes((int) fileinfo.Length);
|
||||
br.Close();
|
||||
|
||||
FileAttachment fileAttachment=new FileAttachment(bytes);
|
||||
|
||||
//fileAttachment.ContentType
|
||||
fileAttachment.FileName=filename;
|
||||
fileAttachment.ContentType="application/zip";
|
||||
emailmessage.AddMixedAttachment(fileAttachment);
|
||||
|
||||
emailmessage.Send(TestAddressHelper.GetSmtpServer());
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestDocFile()
|
||||
{
|
||||
EmailMessage mail = new EmailMessage();
|
||||
|
||||
FileInfo fileinfo=new FileInfo(@"..\..\TestFiles\TestWord.doc");
|
||||
Assert.IsTrue(fileinfo.Exists);
|
||||
|
||||
FileAttachment fileAttachment = new FileAttachment(fileinfo);
|
||||
fileAttachment.ContentType = "application/msword";
|
||||
|
||||
//EmailAddress emailAddress = new EmailAddress(emailAddressParam);
|
||||
mail.TextPart=new TextAttachment("Here is your file");
|
||||
mail.AddMixedAttachment(fileAttachment);
|
||||
|
||||
mail.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
mail.AddToAddress("outlook@mymailout.com");
|
||||
|
||||
SmtpServer smtpServer = TestAddressHelper.GetSmtpServer();
|
||||
|
||||
mail.Send(smtpServer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Utils;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class FileAttachmentTests2
|
||||
{
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(FileAttachmentTests2));
|
||||
|
||||
public FileAttachmentTests2()
|
||||
{
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
#region TestVariousAttachments
|
||||
[Test]
|
||||
public void TestVariousAttachments()
|
||||
{
|
||||
// Read from the file
|
||||
FileAttachment fromfile=GetAttachmentFromFile(new FileInfo(@"..\..\TestFiles\acrobattestpage.pdf"));
|
||||
Assert.IsNotNull(fromfile);
|
||||
|
||||
// Create from a stream reader (this won't work with binary attachments)
|
||||
FileAttachment fromstreamreader=GetAttachmentFromStreamReader(new FileInfo(@"..\..\TestFiles\acrobattestpage.pdf"));
|
||||
Assert.IsNotNull(fromstreamreader);
|
||||
|
||||
// Create from byte array
|
||||
FileAttachment frombytearray=GetAttachmentFromByteArray(new FileInfo(@"..\..\TestFiles\acrobattestpage.pdf"));
|
||||
Assert.IsNotNull(frombytearray);
|
||||
|
||||
// Create from a stream reader (this won't work with binary attachments)
|
||||
FileAttachment frombinaryreader=GetAttachmentFromBinaryReader(new FileInfo(@"..\..\TestFiles\acrobattestpage.pdf"));
|
||||
Assert.IsNotNull(frombinaryreader);
|
||||
|
||||
String fromFileStr=fromfile.ToDataString();
|
||||
String fromByteArrayStr=frombytearray.ToDataString();
|
||||
String fromStreamReaderStr=fromstreamreader.ToDataString();
|
||||
String fromBinaryReaderStr=frombinaryreader.ToDataString();
|
||||
|
||||
log.Debug("FROM FILE: "+fromFileStr.Length+" bytes");
|
||||
log.Debug("FROM BYTE ARRAY: "+fromByteArrayStr.Length+" bytes");
|
||||
log.Debug("FROM STREAM READER: "+fromStreamReaderStr.Length+" bytes");
|
||||
log.Debug("FROM BINARY READER: "+fromBinaryReaderStr.Length+" bytes");
|
||||
|
||||
Assert.AreEqual(fromFileStr, fromBinaryReaderStr);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetBasicMessage
|
||||
private EmailMessage GetBasicMessage()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject="PDF Test";
|
||||
|
||||
emailmessage.TextPart=new TextAttachment("This a PDF File");
|
||||
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<p>This is a PDF File</p>\r\n");
|
||||
|
||||
return emailmessage;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetAttachmentFromByteArray
|
||||
private FileAttachment GetAttachmentFromByteArray(FileInfo fileinfo)
|
||||
{
|
||||
FileStream filestream = fileinfo.OpenRead();
|
||||
|
||||
BinaryReader br=new BinaryReader(filestream);
|
||||
byte[] bytes=br.ReadBytes((int) fileinfo.Length);
|
||||
br.Close();
|
||||
|
||||
FileAttachment fileAttachment=new FileAttachment(bytes);
|
||||
fileAttachment.Encoding=DotNetOpenMail.Encoding.EncodingType.Base64;
|
||||
fileAttachment.FileName="acrobattestpage.pdf";
|
||||
fileAttachment.ContentType="application/pdf";
|
||||
return fileAttachment;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetAttachmentFromFile
|
||||
private FileAttachment GetAttachmentFromFile(FileInfo fileinfo)
|
||||
{
|
||||
FileStream filestream = fileinfo.OpenRead();
|
||||
|
||||
FileAttachment fileAttachment=new FileAttachment(fileinfo);
|
||||
fileAttachment.Encoding=DotNetOpenMail.Encoding.EncodingType.Base64;
|
||||
fileAttachment.FileName="acrobattestpage.pdf";
|
||||
fileAttachment.ContentType="application/pdf";
|
||||
return fileAttachment;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetAttachmentFromStreamReader
|
||||
private FileAttachment GetAttachmentFromStreamReader(FileInfo fileinfo)
|
||||
{
|
||||
FileStream filestream = fileinfo.OpenRead();
|
||||
|
||||
StreamReader streamreader=new StreamReader(filestream);
|
||||
|
||||
|
||||
FileAttachment fileAttachment=new FileAttachment(streamreader);
|
||||
|
||||
//fileAttachment.ContentType
|
||||
fileAttachment.Encoding=DotNetOpenMail.Encoding.EncodingType.Base64;
|
||||
fileAttachment.FileName="acrobattestpage.pdf";
|
||||
fileAttachment.ContentType="application/pdf";
|
||||
return fileAttachment;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetAttachmentFromBinaryReader
|
||||
private FileAttachment GetAttachmentFromBinaryReader(FileInfo fileinfo)
|
||||
{
|
||||
FileStream filestream = fileinfo.OpenRead();
|
||||
|
||||
BinaryReader binaryreader=new BinaryReader(filestream);
|
||||
|
||||
|
||||
FileAttachment fileAttachment=new FileAttachment(binaryreader);
|
||||
|
||||
//fileAttachment.ContentType
|
||||
fileAttachment.Encoding=DotNetOpenMail.Encoding.EncodingType.Base64;
|
||||
fileAttachment.FileName="acrobattestpage.pdf";
|
||||
fileAttachment.ContentType="application/pdf";
|
||||
return fileAttachment;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
using DotNetOpenMail.Logging;
|
||||
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Log4netLogger.
|
||||
/// </summary>
|
||||
public class Log4netLogger
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Log4netLogger));
|
||||
|
||||
public Log4netLogger()
|
||||
{
|
||||
}
|
||||
|
||||
public void Log(LogMessage message)
|
||||
{
|
||||
log.Debug(message.Sender.GetType().Name+" ["+DateTime.Now.ToShortTimeString()+"]: "+message.Message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Utils;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class QuickTest
|
||||
{
|
||||
|
||||
|
||||
SmtpServer _smtpserver=null;
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(QuickTest));
|
||||
|
||||
public QuickTest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSend()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
//emailmessage.FromAddress=new EmailAddress("mike@bridgecanada.com", "Bridge, Mike");
|
||||
//emailmessage.FromAddress=new EmailAddress("mike@bridgecanada.com", "<Mike Bridge>");
|
||||
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test HTML and Text";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
|
||||
emailmessage.BodyText="This is a test";
|
||||
|
||||
emailmessage.AddCustomHeader("X-MyHeader1", "my header number one");
|
||||
//emailmessage.AddCustomHeader("Sender", TestAddressHelper.GetToAddress().ToString());
|
||||
|
||||
Log4netLogger logger=new Log4netLogger();
|
||||
_smtpserver.LogSmtpWrite+=(new SmtpServer.LogHandler(logger.Log));
|
||||
_smtpserver.LogSmtpReceive+=(new SmtpServer.LogHandler(logger.Log));
|
||||
_smtpserver.LogSmtpCompleted+=(new SmtpServer.LogHandler(logger.Log));
|
||||
|
||||
emailmessage.Send(_smtpserver);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using log4net;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class RFC2822DateTests
|
||||
{
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(RFC2822DateTests));
|
||||
|
||||
public RFC2822DateTests()
|
||||
{
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSMTPDate()
|
||||
{
|
||||
TimeZone timezone=TimeZone.CurrentTimeZone;
|
||||
|
||||
DateTime datetime=new DateTime(2005, 2, 8, 9, 34,56);
|
||||
String tzhours=String.Format("{0:00}", timezone.GetUtcOffset(datetime).Hours);
|
||||
String tzminutes=String.Format("{0:00}", timezone.GetUtcOffset(datetime).Minutes);
|
||||
String tzstring=tzhours+tzminutes;
|
||||
if (timezone.GetUtcOffset(datetime).Hours >= 0)
|
||||
{
|
||||
tzstring="+"+tzstring;
|
||||
}
|
||||
RFC2822Date rfcdate=new RFC2822Date(datetime, timezone);
|
||||
Assert.AreEqual("Tue, 8 Feb 2005 09:34:56 "+tzstring, rfcdate.ToString());
|
||||
|
||||
datetime=new DateTime(2005, 2, 8, 19, 34,56);
|
||||
rfcdate=new RFC2822Date(datetime, timezone);
|
||||
Assert.AreEqual("Tue, 8 Feb 2005 19:34:56 "+tzstring, rfcdate.ToString());
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNonEnglishSMTPDate()
|
||||
{
|
||||
CultureInfo japanese=new CultureInfo("ja-JP");
|
||||
System.Threading.Thread.CurrentThread.CurrentCulture=japanese;
|
||||
|
||||
TimeZone timezone=TimeZone.CurrentTimeZone;
|
||||
|
||||
DateTime datetime=new DateTime(2005, 2, 8, 9, 34,56);
|
||||
String tzhours=String.Format("{0:00}", timezone.GetUtcOffset(datetime).Hours);
|
||||
String tzminutes=String.Format("{0:00}", timezone.GetUtcOffset(datetime).Minutes);
|
||||
String tzstring=tzhours+tzminutes;
|
||||
if (timezone.GetUtcOffset(datetime).Hours >= 0)
|
||||
{
|
||||
tzstring="+"+tzstring;
|
||||
}
|
||||
RFC2822Date rfcdate=new RFC2822Date(datetime, timezone);
|
||||
Assert.AreEqual("Tue, 8 Feb 2005 09:34:56 "+tzstring, rfcdate.ToString());
|
||||
|
||||
datetime=new DateTime(2005, 2, 8, 19, 34,56);
|
||||
rfcdate=new RFC2822Date(datetime, timezone);
|
||||
Assert.AreEqual("Tue, 8 Feb 2005 19:34:56 "+tzstring, rfcdate.ToString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using DotNetOpenMail;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for RawEmailMessageTests.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class RawEmailMessageTests
|
||||
{
|
||||
|
||||
SmtpServer _smtpserver=null;
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(RawEmailMessageTests));
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
public RawEmailMessageTests()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRawEmail()
|
||||
{
|
||||
FileInfo contentfile=new FileInfo(@"..\..\TestFiles\ImportedEmail.txt");
|
||||
Assert.IsTrue(contentfile.Exists);
|
||||
StreamReader sr=new StreamReader(contentfile.OpenRead());
|
||||
|
||||
RawEmailMessage message=new RawEmailMessage();
|
||||
message.Content=sr.ReadToEnd();
|
||||
message.AddRcptToAddress(TestAddressHelper.GetToAddress());
|
||||
message.MailFrom=TestAddressHelper.GetFromAddress();
|
||||
message.Send(_smtpserver);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
using DotNetOpenMailTests.Resources; // change to tested dir
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests.Resources {
|
||||
|
||||
[TestFixture]
|
||||
public class ARMTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ARMTests));
|
||||
|
||||
public ARMTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
[Test]
|
||||
public void Test() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Utils;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class RussianTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(RussianTests));
|
||||
|
||||
public RussianTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
[Test]
|
||||
public void TestWindows1251() {
|
||||
|
||||
EmailMessage emailmessage = new EmailMessage();
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject = "ошибочка?";
|
||||
emailmessage.HeaderCharSet = System.Text.Encoding.GetEncoding("windows-1251");
|
||||
|
||||
TextAttachment ta = new TextAttachment("\r\nнесколько строк по русски");
|
||||
ta.CharSet = System.Text.Encoding.GetEncoding("windows-1251");
|
||||
emailmessage.TextPart = ta;
|
||||
emailmessage.Send(TestAddressHelper.GetSmtpServer());
|
||||
Assert.IsTrue(emailmessage.ToDataString().IndexOf("Subject: =?windows-1251") > 0, "Missing windows-1251 in subject");
|
||||
Assert.IsTrue(emailmessage.ToDataString().IndexOf("koi8-r") < 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestKOI8R()
|
||||
{
|
||||
|
||||
EmailMessage emailmessage = new EmailMessage();
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
|
||||
emailmessage.Subject = "ошибочка?";
|
||||
emailmessage.HeaderCharSet = System.Text.Encoding.GetEncoding("koi8-r");
|
||||
|
||||
TextAttachment ta = new TextAttachment("\r\nнесколько строк по русски");
|
||||
ta.CharSet = System.Text.Encoding.GetEncoding("koi8-r");
|
||||
emailmessage.TextPart = ta;
|
||||
//log.Debug("1251");
|
||||
//log.Debug(emailmessage.ToDataString());
|
||||
emailmessage.Send(TestAddressHelper.GetSmtpServer());
|
||||
Assert.IsTrue(emailmessage.ToDataString().IndexOf("Subject: =?koi8-r") > 0, "Missing koi8-r in subject");
|
||||
Assert.IsTrue(emailmessage.ToDataString().IndexOf("windows-1251") < 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.SmtpAuth;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
using NMock;
|
||||
|
||||
namespace DotNetOpenMailTests.SmtpAuth {
|
||||
|
||||
[TestFixture]
|
||||
public class LocalAuthTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(LocalAuthTests));
|
||||
|
||||
public LocalAuthTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
#region GetTestHtmlAndTextMessage
|
||||
private EmailMessage GetTestHtmlAndTextMessage()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test HTML and Text";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
|
||||
emailmessage.AddCustomHeader("X-MyHeader1", "my header number one");
|
||||
emailmessage.AddCustomHeader("X-MyHeader2", "my header number two");
|
||||
|
||||
return emailmessage;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/*
|
||||
* Test for this exchange:
|
||||
* S: 220 esmtp.example.com ESMTP
|
||||
* C: ehlo client.example.com
|
||||
* S: 250-esmtp.example.com
|
||||
* S: 250-PIPELINING
|
||||
* S: 250-8BITMIME
|
||||
* S: 250-SIZE 255555555
|
||||
* S: 250 AUTH LOGIN PLAIN CRAM-MD5
|
||||
* C: auth login
|
||||
* S: 334 VXNlcm5hbWU6
|
||||
* C: avlsdkfj
|
||||
* S: 334 UGFzc3dvcmQ6
|
||||
* C: lkajsdfvlj
|
||||
* S: 535 authentication failed (#5.7.1)
|
||||
*/
|
||||
|
||||
#region TestSimpleSmtpNegotiationWithAuth
|
||||
[Test]
|
||||
public void TestSimpleSmtpNegotiationWithAuth()
|
||||
{
|
||||
|
||||
|
||||
SmtpServer smtpserver=new SmtpServer("localhost");
|
||||
smtpserver.SmtpAuthToken=new SmtpAuthToken("test", "test");
|
||||
|
||||
|
||||
Base64Encoder encoder=Base64Encoder.GetInstance();
|
||||
String base64Username=encoder.EncodeString(smtpserver.SmtpAuthToken.UserName, System.Text.Encoding.ASCII );
|
||||
String base64Password=encoder.EncodeString(smtpserver.SmtpAuthToken.Password, System.Text.Encoding.ASCII );
|
||||
|
||||
EmailMessage emailMessage=GetTestHtmlAndTextMessage();
|
||||
|
||||
IMock mockSmtpProxy = new DynamicMock(typeof(ISmtpProxy));
|
||||
mockSmtpProxy.ExpectAndReturn("Open", new SmtpResponse(220, "welcome to the mock object server"), null);
|
||||
|
||||
EhloSmtpResponse ehloResponse=new EhloSmtpResponse();
|
||||
ehloResponse.AddAvailableAuthType("login");
|
||||
|
||||
ehloResponse.Message="OK";
|
||||
ehloResponse.ResponseCode=250;
|
||||
mockSmtpProxy.ExpectAndReturn("Ehlo",ehloResponse , Dns.GetHostName());
|
||||
mockSmtpProxy.ExpectAndReturn("Auth", new SmtpResponse(334, encoder.EncodeString("Username:", System.Text.Encoding.ASCII)), "login");
|
||||
mockSmtpProxy.ExpectAndReturn("SendString", new SmtpResponse(334, encoder.EncodeString("Password:",System.Text.Encoding.ASCII)), base64Username);
|
||||
mockSmtpProxy.ExpectAndReturn("SendString", new SmtpResponse(235, "Hooray, Authenticated"), base64Password);
|
||||
mockSmtpProxy.ExpectAndReturn("MailFrom", new SmtpResponse(250, "mail from"), emailMessage.FromAddress);
|
||||
foreach (EmailAddress rcpttoaddr in emailMessage.ToAddresses)
|
||||
{
|
||||
mockSmtpProxy.ExpectAndReturn("RcptTo", new SmtpResponse(250, "receipt to"), rcpttoaddr);
|
||||
}
|
||||
mockSmtpProxy.ExpectAndReturn("Data", new SmtpResponse(354, "data open"), null);
|
||||
mockSmtpProxy.ExpectAndReturn("WriteData", new SmtpResponse(250, "data"), emailMessage.ToDataString());
|
||||
|
||||
mockSmtpProxy.ExpectAndReturn("Quit", new SmtpResponse(221, "quit"), null);
|
||||
mockSmtpProxy.Expect("Close", null);
|
||||
|
||||
ISmtpProxy smtpProxy= (ISmtpProxy) mockSmtpProxy.MockInstance;
|
||||
|
||||
|
||||
smtpserver.OverrideSmtpProxy(smtpProxy);
|
||||
|
||||
try
|
||||
{
|
||||
emailMessage.Send(smtpserver);
|
||||
}
|
||||
catch (SmtpException ex)
|
||||
{
|
||||
log.Debug("Exception was "+ex.Message);
|
||||
log.Debug(ex.StackTrace);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestForcedLoginSmtpNegotiationWithAuth
|
||||
[Test]
|
||||
public void TestForcedLoginSmtpNegotiationWithAuth()
|
||||
{
|
||||
|
||||
|
||||
SmtpServer smtpserver=new SmtpServer("localhost");
|
||||
smtpserver.SmtpAuthToken=new LoginAuthToken("test", "testtest");
|
||||
|
||||
|
||||
Base64Encoder encoder=Base64Encoder.GetInstance();
|
||||
String base64Username=encoder.EncodeString(smtpserver.SmtpAuthToken.UserName, System.Text.Encoding.ASCII );
|
||||
String base64Password=encoder.EncodeString(smtpserver.SmtpAuthToken.Password, System.Text.Encoding.ASCII );
|
||||
|
||||
EmailMessage emailMessage=GetTestHtmlAndTextMessage();
|
||||
|
||||
IMock mockSmtpProxy = new DynamicMock(typeof(ISmtpProxy));
|
||||
mockSmtpProxy.ExpectAndReturn("Open", new SmtpResponse(220, "welcome to the mock object server"), null);
|
||||
|
||||
EhloSmtpResponse ehloResponse=new EhloSmtpResponse();
|
||||
ehloResponse.AddAvailableAuthType("login");
|
||||
|
||||
ehloResponse.Message="OK";
|
||||
ehloResponse.ResponseCode=250;
|
||||
mockSmtpProxy.ExpectAndReturn("Ehlo",ehloResponse , Dns.GetHostName());
|
||||
|
||||
mockSmtpProxy.ExpectAndReturn("Auth", new SmtpResponse(334, encoder.EncodeString("Username:", System.Text.Encoding.ASCII)), "login");
|
||||
mockSmtpProxy.ExpectAndReturn("SendString", new SmtpResponse(334, encoder.EncodeString("Password:",System.Text.Encoding.ASCII)), base64Username);
|
||||
mockSmtpProxy.ExpectAndReturn("SendString", new SmtpResponse(235, "Hooray, Authenticated"), base64Password);
|
||||
mockSmtpProxy.ExpectAndReturn("MailFrom", new SmtpResponse(250, "mail from"), emailMessage.FromAddress);
|
||||
foreach (EmailAddress rcpttoaddr in emailMessage.ToAddresses)
|
||||
{
|
||||
mockSmtpProxy.ExpectAndReturn("RcptTo", new SmtpResponse(250, "receipt to"), rcpttoaddr);
|
||||
}
|
||||
mockSmtpProxy.ExpectAndReturn("Data", new SmtpResponse(354, "data open"), null);
|
||||
mockSmtpProxy.ExpectAndReturn("WriteData", new SmtpResponse(250, "data"), emailMessage.ToDataString());
|
||||
|
||||
mockSmtpProxy.ExpectAndReturn("Quit", new SmtpResponse(221, "quit"), null);
|
||||
mockSmtpProxy.Expect("Close", null);
|
||||
|
||||
ISmtpProxy smtpProxy= (ISmtpProxy) mockSmtpProxy.MockInstance;
|
||||
|
||||
|
||||
smtpserver.OverrideSmtpProxy(smtpProxy);
|
||||
|
||||
try
|
||||
{
|
||||
emailMessage.Send(smtpserver);
|
||||
}
|
||||
catch (SmtpException ex)
|
||||
{
|
||||
log.Debug("Exception was "+ex.Message);
|
||||
log.Debug(ex.StackTrace);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestFailedSmtpNegotiationWithAuth
|
||||
[Test]
|
||||
public void TestFailedSmtpNegotiationWithAuth()
|
||||
{
|
||||
|
||||
|
||||
SmtpServer smtpserver=new SmtpServer("localhost");
|
||||
smtpserver.SmtpAuthToken=new SmtpAuthToken("test", "test");
|
||||
|
||||
|
||||
Base64Encoder encoder=Base64Encoder.GetInstance();
|
||||
String base64Username=encoder.EncodeString(smtpserver.SmtpAuthToken.UserName, System.Text.Encoding.ASCII );
|
||||
String base64Password=encoder.EncodeString(smtpserver.SmtpAuthToken.Password, System.Text.Encoding.ASCII );
|
||||
|
||||
EmailMessage emailMessage=GetTestHtmlAndTextMessage();
|
||||
|
||||
IMock mockSmtpProxy = new DynamicMock(typeof(ISmtpProxy));
|
||||
mockSmtpProxy.ExpectAndReturn("Open", new SmtpResponse(220, "welcome to the mock object server"), null);
|
||||
|
||||
EhloSmtpResponse ehloResponse=new EhloSmtpResponse();
|
||||
ehloResponse.AddAvailableAuthType("login");
|
||||
|
||||
ehloResponse.Message="OK";
|
||||
ehloResponse.ResponseCode=250;
|
||||
mockSmtpProxy.ExpectAndReturn("Ehlo", ehloResponse , Dns.GetHostName());
|
||||
mockSmtpProxy.ExpectAndReturn("Auth", new SmtpResponse(554, "Unrecognized auth type"), "login");
|
||||
|
||||
ISmtpProxy smtpProxy= (ISmtpProxy) mockSmtpProxy.MockInstance;
|
||||
|
||||
smtpserver.OverrideSmtpProxy(smtpProxy);
|
||||
|
||||
/*
|
||||
mockSmtpProxy.ExpectAndReturn("SendString", new SmtpResponse(554, "Invalid UserName"), base64Username);
|
||||
mockSmtpProxy.ExpectAndReturn("SendString", new SmtpResponse(554, "Invalid Password"), base64Password);
|
||||
mockSmtpProxy.ExpectAndReturn("MailFrom", new SmtpResponse(250, "mail from"), emailMessage.FromAddress);
|
||||
foreach (EmailAddress rcpttoaddr in emailMessage.ToAddresses)
|
||||
{
|
||||
mockSmtpProxy.ExpectAndReturn("RcptTo", new SmtpResponse(250, "receipt to"), rcpttoaddr);
|
||||
}
|
||||
mockSmtpProxy.ExpectAndReturn("Data", new SmtpResponse(354, "data open"), null);
|
||||
mockSmtpProxy.ExpectAndReturn("WriteData", new SmtpResponse(250, "data"), emailMessage.ToDataString());
|
||||
|
||||
mockSmtpProxy.ExpectAndReturn("Quit", new SmtpResponse(221, "quit"), null);
|
||||
mockSmtpProxy.Expect("Close", null);
|
||||
*/
|
||||
|
||||
try
|
||||
{
|
||||
emailMessage.Send(smtpserver);
|
||||
Assert.Fail("The auth type is wrong");
|
||||
}
|
||||
catch (SmtpException ex)
|
||||
{
|
||||
log.Debug("ERROR CODE IS "+554);
|
||||
Assert.AreEqual(554,ex.ErrorCode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TestSmtpNegotiationWithAuthTimeout
|
||||
[Test]
|
||||
[Ignore("Not completed yet")]
|
||||
public void TestSmtpNegotiationWithAuthTimeout()
|
||||
{
|
||||
|
||||
|
||||
SmtpServer smtpserver=new SmtpServer("localhost");
|
||||
smtpserver.SmtpAuthToken=new LoginAuthToken("test", "test");
|
||||
|
||||
|
||||
Base64Encoder encoder=Base64Encoder.GetInstance();
|
||||
String base64Username=encoder.EncodeString(smtpserver.SmtpAuthToken.UserName, System.Text.Encoding.ASCII );
|
||||
String base64Password=encoder.EncodeString(smtpserver.SmtpAuthToken.Password, System.Text.Encoding.ASCII );
|
||||
|
||||
EmailMessage emailMessage=GetTestHtmlAndTextMessage();
|
||||
|
||||
/*
|
||||
IMock mockSmtpProxy = new DynamicMock(typeof(ISmtpProxy));
|
||||
|
||||
mockSmtpProxy.ExpectAndReturn("Open", new SmtpResponse(220, "welcome to the mock object server"), null);
|
||||
|
||||
EhloSmtpResponse ehloResponse=new EhloSmtpResponse();
|
||||
ehloResponse.AddAvailableAuthType("login");
|
||||
|
||||
ehloResponse.Message="OK";
|
||||
ehloResponse.ResponseCode=250;
|
||||
mockSmtpProxy.ExpectAndReturn("Ehlo",ehloResponse , Dns.GetHostName());
|
||||
|
||||
mockSmtpProxy.ExpectAndReturn("Auth", new SmtpResponse(334, encoder.EncodeString("Username:", System.Text.Encoding.ASCII)), "login");
|
||||
mockSmtpProxy.ExpectAndReturn("SendString", new SmtpResponse(334, encoder.EncodeString("Password:",System.Text.Encoding.ASCII)), base64Username);
|
||||
mockSmtpProxy.ExpectAndReturn("SendString", new SmtpResponse(235, "Hooray, Authenticated"), base64Password);
|
||||
mockSmtpProxy.ExpectAndReturn("MailFrom", new SmtpResponse(250, "mail from"), emailMessage.FromAddress);
|
||||
|
||||
foreach (EmailAddress rcpttoaddr in emailMessage.ToAddresses)
|
||||
{
|
||||
mockSmtpProxy.ExpectAndReturn("RcptTo", new SmtpResponse(250, "receipt to"), rcpttoaddr);
|
||||
}
|
||||
mockSmtpProxy.ExpectAndReturn("Data", new SmtpResponse(354, "data open"), null);
|
||||
mockSmtpProxy.ExpectAndReturn("WriteData", new SmtpResponse(250, "data"), emailMessage.ToDataString());
|
||||
|
||||
mockSmtpProxy.ExpectAndReturn("Quit", new SmtpResponse(221, "quit"), null);
|
||||
mockSmtpProxy.Expect("Close", null);
|
||||
|
||||
ISmtpProxy smtpProxy= (ISmtpProxy) mockSmtpProxy.MockInstance;
|
||||
*/
|
||||
|
||||
smtpserver.OverrideSmtpProxy(new MockedSlowProxy());
|
||||
try
|
||||
{
|
||||
emailMessage.Send(smtpserver);
|
||||
Assert.Fail("This should have thrown an SmtpException indicating a timeout.");
|
||||
}
|
||||
catch (SmtpException ex)
|
||||
{
|
||||
log.Debug("Exception was "+ex.Message);
|
||||
log.Debug(ex.StackTrace);
|
||||
//throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.SmtpAuth;
|
||||
|
||||
namespace DotNetOpenMailTests.SmtpAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for MockedSlowServer.
|
||||
/// </summary>
|
||||
public class MockedSlowProxy : MockedSmtpProxy
|
||||
{
|
||||
public MockedSlowProxy()
|
||||
{
|
||||
}
|
||||
|
||||
public override SmtpResponse Open()
|
||||
{
|
||||
return new SmtpResponse(220, "Welcome to the Slow Server");
|
||||
}
|
||||
|
||||
public override SmtpResponse Auth(String localHostName)
|
||||
{
|
||||
//int timeout=10000;
|
||||
//System.Threading.Thread.Sleep(timeout);
|
||||
throw new SocketException(10060);
|
||||
//throw new ApplicationException("Waited "+timeout+" millisseconds");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.SmtpAuth;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMailTests.SmtpAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for MockedSmtpProxy.
|
||||
/// </summary>
|
||||
public abstract class MockedSmtpProxy : ISmtpProxy
|
||||
{
|
||||
public MockedSmtpProxy()
|
||||
{
|
||||
//
|
||||
// TODO: Add constructor logic here
|
||||
//
|
||||
}
|
||||
|
||||
public virtual SmtpResponse Open()
|
||||
{
|
||||
throw new ApplicationException("Open Not implemented yet");
|
||||
}
|
||||
|
||||
public SmtpResponse Helo(String localHostName)
|
||||
{
|
||||
throw new ApplicationException("Helo Not implemented yet");
|
||||
}
|
||||
|
||||
|
||||
public virtual SmtpResponse Auth(String localHostName)
|
||||
{
|
||||
Base64Encoder encoder=Base64Encoder.GetInstance();
|
||||
return new SmtpResponse(334, encoder.EncodeString("Username:", System.Text.Encoding.ASCII));
|
||||
}
|
||||
|
||||
public virtual EhloSmtpResponse Ehlo(String localHostName)
|
||||
{
|
||||
EhloSmtpResponse ehloResponse=new EhloSmtpResponse();
|
||||
ehloResponse.AddAvailableAuthType("login");
|
||||
ehloResponse.Message="OK";
|
||||
ehloResponse.ResponseCode=250;
|
||||
return ehloResponse;
|
||||
}
|
||||
|
||||
public SmtpResponse MailFrom(EmailAddress rcptto)
|
||||
{
|
||||
throw new ApplicationException("MailFrom Not implemented yet");
|
||||
}
|
||||
|
||||
public SmtpResponse RcptTo(EmailAddress rcptto)
|
||||
{
|
||||
throw new ApplicationException("RcptTo Not implemented yet");
|
||||
}
|
||||
|
||||
public SmtpResponse Data()
|
||||
{
|
||||
throw new ApplicationException("Data Not implemented yet");
|
||||
}
|
||||
|
||||
public SmtpResponse WriteData(String str)
|
||||
{
|
||||
throw new ApplicationException("WriteData Not implemented yet");
|
||||
}
|
||||
|
||||
public SmtpResponse Quit()
|
||||
{
|
||||
throw new ApplicationException("Quit Not implemented yet");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public SmtpResponse SendString(String str)
|
||||
{
|
||||
throw new ApplicationException("SendString Not implemented yet");
|
||||
}
|
||||
|
||||
public bool CaptureSmtpConversation {
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
// IGNORE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
using DotNetOpenMail;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMailTests {
|
||||
|
||||
[TestFixture]
|
||||
public class SmtpProxyTests {
|
||||
|
||||
SmtpServer _smtpserver=null;
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SmtpProxyTests));
|
||||
|
||||
public SmtpProxyTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
}
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
[Test]
|
||||
|
||||
public void TestBasicSend()
|
||||
{
|
||||
|
||||
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests TestBasicSend";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
emailmessage.EnvelopeFromAddress=new EmailAddress("test@bridgecanada.com");
|
||||
emailmessage.Send(_smtpserver);
|
||||
// this doesn't test anything yet
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmailWithDot()
|
||||
{
|
||||
//SmtpServer smtpserver=TestAddressHelper.GetSmtpServer();
|
||||
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test Dot";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\n.is the\r\n..text\r\n...part.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\n..is the<br>\r\n..<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
emailmessage.Send(_smtpserver);
|
||||
|
||||
// this doesn't test anything yet
|
||||
//log.Debug("MESSAGE: "+emailmessage.ToDataString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
using DotNetOpenMail;
|
||||
|
||||
using NUnit.Framework;
|
||||
using log4net;
|
||||
using NMock;
|
||||
|
||||
namespace DotNetOpenMailTests.SmtpServerTests {
|
||||
|
||||
[TestFixture]
|
||||
public class SmtpServerTests {
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SmtpServerTests));
|
||||
|
||||
public SmtpServerTests() {
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() {}
|
||||
|
||||
private EmailMessage GetTestHtmlAndTextMessage()
|
||||
{
|
||||
EmailMessage emailmessage=new EmailMessage();
|
||||
|
||||
emailmessage.FromAddress=TestAddressHelper.GetFromAddress();
|
||||
emailmessage.AddToAddress(TestAddressHelper.GetToAddress());
|
||||
emailmessage.Subject="EmailMessageTests Test HTML and Text";
|
||||
emailmessage.TextPart=new TextAttachment("This\r\nis the\r\ntext\r\npart.");
|
||||
emailmessage.HtmlPart=new HtmlAttachment("<html><body>This<br>\r\nis the<br>\r\n<strong>HTML</strong><br>\r\npart.</body></html>");
|
||||
|
||||
emailmessage.AddCustomHeader("X-MyHeader1", "my header number one");
|
||||
emailmessage.AddCustomHeader("X-MyHeader2", "my header number two");
|
||||
|
||||
return emailmessage;
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestSimpleSmtpNegotiation()
|
||||
{
|
||||
SmtpServer smtpserver=new SmtpServer("localhost");
|
||||
EmailMessage emailMessage=GetTestHtmlAndTextMessage();
|
||||
|
||||
IMock mockSmtpProxy = new DynamicMock(typeof(ISmtpProxy));
|
||||
mockSmtpProxy.ExpectAndReturn("Open", new SmtpResponse(220, "welcome to the mock object server"), null);
|
||||
mockSmtpProxy.ExpectAndReturn("Helo", new SmtpResponse(250, "helo"), Dns.GetHostName());
|
||||
mockSmtpProxy.ExpectAndReturn("MailFrom", new SmtpResponse(250, "mail from"), emailMessage.FromAddress);
|
||||
foreach (EmailAddress rcpttoaddr in emailMessage.ToAddresses)
|
||||
{
|
||||
mockSmtpProxy.ExpectAndReturn("RcptTo", new SmtpResponse(250, "receipt to"), rcpttoaddr);
|
||||
}
|
||||
mockSmtpProxy.ExpectAndReturn("Data", new SmtpResponse(354, "data open"), null);
|
||||
mockSmtpProxy.ExpectAndReturn("WriteData", new SmtpResponse(250, "data"), emailMessage.ToDataString());
|
||||
|
||||
mockSmtpProxy.ExpectAndReturn("Quit", new SmtpResponse(221, "quit"), null);
|
||||
mockSmtpProxy.Expect("Close", null);
|
||||
|
||||
ISmtpProxy smtpProxy= (ISmtpProxy) mockSmtpProxy.MockInstance;
|
||||
|
||||
|
||||
smtpserver.OverrideSmtpProxy(smtpProxy);
|
||||
|
||||
|
||||
emailMessage.Send(smtpserver);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using DotNetOpenMail;
|
||||
|
||||
namespace DotNetOpenMailTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestAddressHelper.
|
||||
/// </summary>
|
||||
public class TestAddressHelper
|
||||
{
|
||||
public TestAddressHelper()
|
||||
{
|
||||
}
|
||||
|
||||
public static EmailAddress GetFromAddress()
|
||||
{
|
||||
//return new EmailAddress("mike@bridgecanada.com", "Test Sender");
|
||||
|
||||
String email=System.Configuration.ConfigurationSettings.AppSettings["dnom.test.fromaddress"];
|
||||
if (email==null)
|
||||
{
|
||||
throw new ApplicationException("Please add the key \"dnom.test.fromaddress\" to your .config file");
|
||||
}
|
||||
return new EmailAddress(email, "NUnit Test Sender");
|
||||
|
||||
}
|
||||
|
||||
public static EmailAddress GetToAddress()
|
||||
{
|
||||
String email=System.Configuration.ConfigurationSettings.AppSettings["dnom.test.toaddress"];
|
||||
if (email==null)
|
||||
{
|
||||
throw new ApplicationException("Please add the key \"dnom.test.toaddress\" to your .config file");
|
||||
}
|
||||
return new EmailAddress(email, "NUnit Test Recipient");
|
||||
}
|
||||
|
||||
public static SmtpServer GetSmtpServer()
|
||||
{
|
||||
String smtpserver=System.Configuration.ConfigurationSettings.AppSettings["dnom.test.smtp.server"];
|
||||
if (smtpserver==null)
|
||||
{
|
||||
throw new ApplicationException("Please add the key \"dnom.test.smtp.server\" to your .config file");
|
||||
}
|
||||
|
||||
return new SmtpServer(smtpserver);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Subject: This is a test
|
||||
To: mike@bridgecanada.com
|
||||
|
||||
This is a test.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
|
||||
using DotNetOpenMail;
|
||||
using DotNetOpenMail.Utils;
|
||||
|
||||
using log4net;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace DotNetOpenMailTests.Utils
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class EmailAddressParserTests
|
||||
{
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(EmailAddressParserTests));
|
||||
|
||||
public EmailAddressParserTests()
|
||||
{
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestParser()
|
||||
{
|
||||
EmailAddressParser emailaddressparser=new EmailAddressParser();
|
||||
String name1="Test Tester";
|
||||
String email1="test@domain.com";
|
||||
|
||||
EmailAddress emailaddress=emailaddressparser.ParseRawEmailAddress(String.Format("{0} <{1}>", name1, email1));
|
||||
Assert.IsNull(emailaddressparser.LastError);
|
||||
Assert.IsNotNull(emailaddress, emailaddressparser.LastError);
|
||||
Assert.AreEqual(name1, emailaddress.Name);
|
||||
Assert.AreEqual(email1, emailaddress.Email);
|
||||
|
||||
emailaddress=emailaddressparser.ParseRawEmailAddress(email1);
|
||||
Assert.IsNull(emailaddressparser.LastError);
|
||||
Assert.IsNotNull(emailaddress, emailaddressparser.LastError);
|
||||
Assert.AreEqual("", emailaddress.Name);
|
||||
Assert.AreEqual(email1, emailaddress.Email);
|
||||
|
||||
emailaddress=emailaddressparser.ParseRawEmailAddress(String.Format("\"{0}\" <{1}>", name1, email1));
|
||||
Assert.IsNotNull(emailaddress, emailaddressparser.LastError);
|
||||
Assert.IsNull(emailaddressparser.LastError, emailaddressparser.LastError);
|
||||
Assert.AreEqual("\""+name1+"\"", emailaddress.Name);
|
||||
Assert.AreEqual(email1, emailaddress.Email);
|
||||
|
||||
emailaddress=emailaddressparser.ParseRawEmailAddress(String.Format("{0} <{1}>", name1, "test@localhost"));
|
||||
Assert.IsNotNull(emailaddress, emailaddressparser.LastError);
|
||||
Assert.IsNull(emailaddressparser.LastError, emailaddressparser.LastError);
|
||||
Assert.AreEqual(name1, emailaddress.Name);
|
||||
Assert.AreEqual("test@localhost", emailaddress.Email);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
Version 0.5.8 beta: 24-May-2006
|
||||
|
||||
- Fixed buffering problem while doing base64-encoding
|
||||
- Fixed missing ContentID in FileAttachment
|
||||
- Added BinaryReader support for FileAttachment.
|
||||
|
||||
Version 0.5.7 beta: 17-Dec-2005
|
||||
|
||||
- Added event delegates to SmtpServer to listen to the SMTP conversation
|
||||
- Deprecated the use of CaptureSmtpConversation
|
||||
- Added simple version of email address string parser.
|
||||
- Added a potential patch for piping a file attachment from memory
|
||||
|
||||
Version 0.5.6 beta: 16-Sep-2005
|
||||
|
||||
- Fixed SMTP AUTH LOCAL negotiation where the server returns multiple types
|
||||
- SmtpProxy loops through multiline EHLO response correctly.
|
||||
|
||||
Version 0.5.5 beta: 25-Aug-2005
|
||||
|
||||
- Fixed handling of RFC-2822 "special" characters in email name.
|
||||
- Added nicer error message when "From" name is missing.
|
||||
|
||||
Version 0.5.4 beta: 19-Aug-2005
|
||||
|
||||
- Replaced incorrect call to BodyName in QPEncoder and Base64Encoder with call
|
||||
to HeaderName
|
||||
- Added workaround for incorrect value returned by the .net framework for
|
||||
Russian Windows-1251 (Encoding.GetEncoding("windows-1251").BodyName)
|
||||
- Added error checking for truncated server responses of less than 3
|
||||
characters.
|
||||
- Fixed various incorrect numerical references to RFCs.
|
||||
- Fixed QP-encoding of the question mark in message headers.
|
||||
|
||||
Version 0.5.3 beta: 3-Aug-2005
|
||||
|
||||
- Fixed RFC2822Date class to be independent of the deployment system default.
|
||||
- Added ability to view the SMTP conversation in the SmtpServer class.
|
||||
|
||||
Version 0.5.2 beta: 30-May-2005
|
||||
|
||||
- Added check for empty charset for Header in both EmailAddress and
|
||||
QPEncoder (default is iso-8859-1)
|
||||
- Fixed the QPEncoder wrapping algorithm for long headers.
|
||||
- An extra line was removed after a mimeheader which was pushing
|
||||
custom headers into the mail body.
|
||||
|
||||
|
||||
Version 0.5.1 beta: 26-Apr-2005
|
||||
|
||||
- Added ability to create FileAttachment from an in-memory byte array
|
||||
- Fixed suppression of SMTP error on rejected RCPT TO address.
|
||||
- Added NMock 1.1 to the source distribution.
|
||||
- Added LOGIN protocol for SMTP AUTH.
|
||||
- Refactored the SmtpProxy and SmtpServer to allow for Mocking
|
||||
up various SMTP servers and SMTP protocol exchanges.
|
||||
|
||||
Version 0.5.0 beta: 1-Apr-2005
|
||||
|
||||
- Added NDoc documentation
|
||||
- Added ability to create FileAttachment from a string
|
||||
|
||||
Version 0.4.0 beta: 1-Apr-2005
|
||||
|
||||
- Botched the Subversion tag
|
||||
|
||||
Version 0.3.1: 3-Mar-2005
|
||||
|
||||
- Added 7bit and 8bit options to encoder
|
||||
- Fixed Camel Casing on web site, added example for next point
|
||||
- Added ability to create FileAttachment from a reader
|
||||
|
||||
Version 0.3: 18-Feb-2005
|
||||
|
||||
- Added French localization
|
||||
- Added modified examples from the web site as NUnit tests
|
||||
to ensure they work
|
||||
- Added ability to change Encoding and character set for
|
||||
something other than latin-1. The API for specifying
|
||||
the encoding changed.
|
||||
- Fixed quoted printable to work with multibyte characters.
|
||||
|
||||
Version 0.2.1: 9-Feb-2005
|
||||
|
||||
- Initial Release
|
||||
@@ -0,0 +1,40 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.106
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenMail", "DotNetOpenMail\DotNetOpenMail.csproj", "{6FBB299F-81A1-49EA-B00A-E916F8F797B3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenMailTests", "DotNetOpenMailTests\DotNetOpenMailTests.csproj", "{74F3DCD7-1325-4968-B466-38618A380CE9}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{643C301A-B110-41E7-B0F7-FA2CA4AE335D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
CHANGES.txt = CHANGES.txt
|
||||
DotNetOpenMailTests.dll.config = DotNetOpenMailTests.dll.config
|
||||
DotNetOpenMailTests.dll.config.demo = DotNetOpenMailTests.dll.config.demo
|
||||
DotNetOpenMailTests.dll.log4net = DotNetOpenMailTests.dll.log4net
|
||||
LICENSE.txt = LICENSE.txt
|
||||
README.txt = README.txt
|
||||
README_NUNIT.txt = README_NUNIT.txt
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6FBB299F-81A1-49EA-B00A-E916F8F797B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6FBB299F-81A1-49EA-B00A-E916F8F797B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6FBB299F-81A1-49EA-B00A-E916F8F797B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6FBB299F-81A1-49EA-B00A-E916F8F797B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{74F3DCD7-1325-4968-B466-38618A380CE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{74F3DCD7-1325-4968-B466-38618A380CE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{74F3DCD7-1325-4968-B466-38618A380CE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {31BC050A-2A12-4377-B072-BA9302262B6A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// This is an abstract version of the email attachment. It may or
|
||||
/// may not contain content, a character encoding method, a
|
||||
/// mime-encoding method, a content-type designation, a content-id
|
||||
/// designation, among other things
|
||||
/// </summary>
|
||||
public abstract class AbstractEmailAttachment : IEmailStringable
|
||||
{
|
||||
internal static readonly String CONTENTTYPE="Content-Type";
|
||||
internal static readonly String CONTENTTRANSFERENCODING="Content-Transfer-Encoding";
|
||||
internal static readonly String CONTENTDIPOSITION="Content-Disposition";
|
||||
internal static readonly String CONTENTID="Content-ID";
|
||||
internal static readonly String CONTENTDESCRIPTION="Content-Description";
|
||||
internal static readonly String CHARSET="charset";
|
||||
|
||||
/// <summary>
|
||||
/// The mail encoding type (e.g. quoted-printable, etc)
|
||||
/// </summary>
|
||||
protected EncodingType _encodingtype;
|
||||
|
||||
/// <summary>
|
||||
/// The "content type" of the attachment
|
||||
/// </summary>
|
||||
protected String _contenttype;
|
||||
|
||||
/// <summary>
|
||||
/// The content-transfer encoding of the attachment
|
||||
/// </summary>
|
||||
protected String _contenttransferencoding;
|
||||
|
||||
/// <summary>
|
||||
/// The content disposition of the attachment
|
||||
/// </summary>
|
||||
protected String _contentdisposition;
|
||||
|
||||
/// <summary>
|
||||
/// The content description of the attachment
|
||||
/// </summary>
|
||||
protected String _contentdescription;
|
||||
|
||||
/// <summary>
|
||||
/// The character set of the encoded text
|
||||
/// </summary>
|
||||
protected System.Text.Encoding _charset=null;
|
||||
|
||||
/// <summary>
|
||||
/// The unencoded contents, as a string (optional)
|
||||
/// </summary>
|
||||
protected String _contents=null;
|
||||
|
||||
/// <summary>
|
||||
/// An optional content id
|
||||
/// </summary>
|
||||
protected String _contentid=null;
|
||||
|
||||
/// <summary>
|
||||
/// The file name to identify the content.
|
||||
/// (This can be different from the actual file name,
|
||||
/// if there was one.)
|
||||
/// </summary>
|
||||
protected String _filename=null;
|
||||
|
||||
/// <summary>
|
||||
/// The file source to read from
|
||||
/// </summary>
|
||||
protected FileInfo _fileinfo=null;
|
||||
|
||||
/// <summary>
|
||||
/// The binary source of the file
|
||||
/// </summary>
|
||||
protected Byte[] _contentbytes=null;
|
||||
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
public AbstractEmailAttachment()
|
||||
{
|
||||
}
|
||||
|
||||
#region GetEncodedContents
|
||||
/// <summary>
|
||||
/// Get the contents, encoded for shipping via SMTP
|
||||
/// </summary>
|
||||
/// <param name="encoder">The encoder to encode the contents</param>
|
||||
/// <returns>returns the encoded string, ready for SMTP transfer</returns>
|
||||
internal virtual String GetEncodedContents(IEncoder encoder)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
System.Text.Encoding charset=null;
|
||||
if (_charset==null)
|
||||
{
|
||||
charset=System.Text.Encoding.UTF8;
|
||||
}
|
||||
else
|
||||
{
|
||||
charset=this._charset;
|
||||
}
|
||||
|
||||
if (_contents!=null)
|
||||
{
|
||||
encoder.Encode(new StringReader(_contents), new StringWriter(sb), charset);
|
||||
}
|
||||
else if (_fileinfo!=null)
|
||||
{
|
||||
encoder.Encode(_fileinfo.OpenRead(), new StringWriter(sb), charset);
|
||||
}
|
||||
else if (_contentbytes!=null)
|
||||
{
|
||||
encoder.Encode(new BinaryReader(new MemoryStream(_contentbytes)), new StringWriter(sb));
|
||||
}
|
||||
String encodedcontents=sb.ToString();
|
||||
|
||||
if (encodedcontents.Length!=0 && encodedcontents[encodedcontents.Length-1]!='\n')
|
||||
{
|
||||
return encodedcontents+SmtpProxy.ENDOFLINE+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return encodedcontents+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Return the encoded contents, including mime
|
||||
/// header.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
IEncoder encoder=EncoderFactory.GetEncoder(Encoding);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
sb.Append(GetInternalMimeHeader(encoder));
|
||||
sb.Append(GetEncodedContents(encoder));
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encoding
|
||||
/// <summary>
|
||||
/// The encoding type for this attachment.
|
||||
/// </summary>
|
||||
public EncodingType Encoding
|
||||
{
|
||||
get {return _encodingtype;}
|
||||
set {_encodingtype=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentType
|
||||
/// <summary>
|
||||
/// The "content type" of the attachment
|
||||
/// </summary>
|
||||
public String ContentType
|
||||
{
|
||||
get {return _contenttype;}
|
||||
set {_contenttype=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CharSet
|
||||
/// <summary>
|
||||
/// The character set of the encoded text
|
||||
/// </summary>
|
||||
public System.Text.Encoding CharSet
|
||||
{
|
||||
get {return _charset;}
|
||||
set {_charset=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentId
|
||||
/// <summary>
|
||||
/// An optional content id that is used to refer to
|
||||
/// the attachment from elsewhere within a multipart/related
|
||||
/// email.
|
||||
/// </summary>
|
||||
public String ContentId
|
||||
{
|
||||
get {return _contentid;}
|
||||
set {_contentid=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileName
|
||||
/// <summary>
|
||||
/// The file name to attach to the attachment.
|
||||
/// </summary>
|
||||
public String FileName
|
||||
{
|
||||
get {return _filename;}
|
||||
set {_filename=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Contents
|
||||
/// <summary>
|
||||
/// The unencoded contents, as a string (optional)
|
||||
/// </summary>
|
||||
public String Contents
|
||||
{
|
||||
get {return _contents;}
|
||||
set {_contents=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentBytes
|
||||
/// <summary>
|
||||
/// The raw bytes of the content (if this is the way
|
||||
/// it was set.)
|
||||
/// </summary>
|
||||
public byte[] ContentBytes
|
||||
{
|
||||
get {return _contentbytes;}
|
||||
set {_contentbytes=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInternalMimeHeader
|
||||
/// <summary>
|
||||
/// Create the internal mime header, as found on the
|
||||
/// mime-attachment itself.
|
||||
/// </summary>
|
||||
/// <param name="encoder"></param>
|
||||
/// <returns></returns>
|
||||
protected String GetInternalMimeHeader(IEncoder encoder)
|
||||
{
|
||||
return MakeContentType()+
|
||||
MakeTransferEncoding(encoder)+
|
||||
MakeContentId()+
|
||||
MakeContentDisposition()+
|
||||
MakeContentDescription()+
|
||||
SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeContentType
|
||||
private String MakeContentType()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder(AbstractEmailAttachment.CONTENTTYPE+": "+ContentType+";"+SmtpProxy.ENDOFLINE);
|
||||
if (_charset!=null)
|
||||
{
|
||||
// changed by Pietrovich to fix
|
||||
// windows-1251 .NET encoding bug.
|
||||
// windows-1251 BodyName returns "koi8-r"
|
||||
// instead of "windows-1251"
|
||||
// but still encodes string as windows-1251
|
||||
string bodyName = _charset.BodyName;
|
||||
|
||||
//#if (FORCEWIN1251)
|
||||
if ("koi8-r" == _charset.BodyName && "windows-1251" == _charset.HeaderName)
|
||||
{
|
||||
bodyName = _charset.HeaderName;
|
||||
}
|
||||
//#endif
|
||||
|
||||
sb.Append(" "+AbstractEmailAttachment.CHARSET + "=\"" +
|
||||
bodyName + "\""+SmtpProxy.ENDOFLINE);
|
||||
// _charset.BodyName + "\""+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
if (FileName!=null)
|
||||
{
|
||||
sb.Append(" name=\""+FileName+"\""+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
return sb.ToString();
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeTransferEncoding
|
||||
private String MakeTransferEncoding(IEncoder encoder)
|
||||
{
|
||||
return AbstractEmailAttachment.CONTENTTRANSFERENCODING+": "+encoder.ContentTransferEncodingString+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeContentId
|
||||
private String MakeContentId()
|
||||
{
|
||||
if (ContentId!=null)
|
||||
{
|
||||
return AbstractEmailAttachment.CONTENTID+": <" + ContentId + ">" + SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
return "";
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeContentDisposition
|
||||
private String MakeContentDisposition()
|
||||
{
|
||||
if (ContentId!=null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
if (ContentType!=null && FileName !=null)
|
||||
{
|
||||
return AbstractEmailAttachment.CONTENTDIPOSITION+": attachment;"+SmtpProxy.ENDOFLINE+
|
||||
" filename=\""+FileName+"\""+SmtpProxy.ENDOFLINE;
|
||||
}
|
||||
return "";
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MakeContentDescription
|
||||
private String MakeContentDescription()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
@@ -0,0 +1,220 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>7.10.3077</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{6FBB299F-81A1-49EA-B00A-E916F8F797B3}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ApplicationIcon />
|
||||
<AssemblyKeyContainerName />
|
||||
<AssemblyName>DotNetOpenMail</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile />
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
<DelaySign>false</DelaySign>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>DotNetOpenMail</RootNamespace>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
<StartupObject />
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>0.0</OldToolsVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile />
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DocumentationFile>DotNetOpenMail.xml</DocumentationFile>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn />
|
||||
<Optimize>false</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile />
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DocumentationFile>DotNetOpenMail.xml</DocumentationFile>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn />
|
||||
<Optimize>true</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Data">
|
||||
<Name>System.Data</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml">
|
||||
<Name>System.XML</Name>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AbstractEmailAttachment.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="EhloSmtpResponse.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="EmailAddress.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="EmailAddressCollection.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="EmailMessage.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Encoding\Base64Encoder.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Encoding\DoNothingEncoder.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Encoding\EightBitEncoder.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Encoding\EncoderFactory.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Encoding\EncodingType.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Encoding\IEncoder.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Encoding\QPEncoder.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Encoding\SevenBitEncoder.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FileAttachment.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="HtmlAttachment.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="IEmailStringable.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ISendableMessage.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ISmtpProxy.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Logging\Logger.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Logging\LogMessage.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MailException.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MessageHeader.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MessageHeaderCollection.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MimeBoundary.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MimeContainer.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="RawEmailMessage.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Resources\ARM.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="RFC2822Date.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpAuth\ISmtpAuthToken.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpAuth\LoginAuthToken.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpAuth\SmtpAuthFactory.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpAuth\SmtpAuthToken.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpException.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpProxy.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpResponse.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpResponseCode.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SmtpServer.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TextAttachment.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Utils\BinaryStreamUtil.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Utils\Configuration.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Utils\EmailAddressParser.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Utils\VersionInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Resources\DotNetOpenMail.resx" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent />
|
||||
<PostBuildEvent />
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<LastOpenVersion>7.10.3077</LastOpenVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ReferencePath>C:\Visual Studio Projects\DotNetOpenMail\lib\</ReferencePath>
|
||||
<CopyProjectDestinationFolder />
|
||||
<CopyProjectUncPath />
|
||||
<CopyProjectOption>0</CopyProjectOption>
|
||||
<ProjectView>ShowAllFiles</ProjectView>
|
||||
<ProjectTrust>0</ProjectTrust>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<EnableASPDebugging>false</EnableASPDebugging>
|
||||
<EnableASPXDebugging>false</EnableASPXDebugging>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
|
||||
<RemoteDebugEnabled>false</RemoteDebugEnabled>
|
||||
<RemoteDebugMachine />
|
||||
<StartAction>Project</StartAction>
|
||||
<StartArguments />
|
||||
<StartPage />
|
||||
<StartProgram />
|
||||
<StartURL />
|
||||
<StartWorkingDirectory />
|
||||
<StartWithIE>true</StartWithIE>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<EnableASPDebugging>false</EnableASPDebugging>
|
||||
<EnableASPXDebugging>false</EnableASPXDebugging>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
|
||||
<RemoteDebugEnabled>false</RemoteDebugEnabled>
|
||||
<RemoteDebugMachine />
|
||||
<StartAction>Project</StartAction>
|
||||
<StartArguments />
|
||||
<StartPage />
|
||||
<StartProgram />
|
||||
<StartURL />
|
||||
<StartWorkingDirectory />
|
||||
<StartWithIE>true</StartWithIE>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using DotNetOpenMail.SmtpAuth;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// The server response from EHLO
|
||||
/// </summary>
|
||||
public class EhloSmtpResponse
|
||||
{
|
||||
private int _responseCode=0;
|
||||
private String _message;
|
||||
|
||||
ArrayList smtpAuthTypes=new ArrayList();
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the EhloSmtpResponse class
|
||||
/// </summary>
|
||||
public EhloSmtpResponse()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the available Auth Types strings
|
||||
/// as reported by the server.
|
||||
/// (e.g. "login", etc.)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String[] GetAvailableAuthTypes()
|
||||
{
|
||||
String[] stringArray=new String[smtpAuthTypes.Count];
|
||||
smtpAuthTypes.CopyTo(stringArray);
|
||||
|
||||
return stringArray;
|
||||
//return (SmtpAuthType[]) smtpAuthTypes.ToArray(typeof (SmtpAuthType[]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an Auth type (by string as contained in the
|
||||
/// EHLO authentication. These are converted to lower
|
||||
/// case.
|
||||
/// </summary>
|
||||
/// <param name="authType">The auth type from EHLO</param>
|
||||
public void AddAvailableAuthType(String authType)
|
||||
{
|
||||
smtpAuthTypes.Add(authType.Trim().ToLower());
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Add an Auth type
|
||||
/// </summary>
|
||||
/// <param name="smtpAuthType"></param>
|
||||
public void AddAvailableAuthType(SmtpAuthType smtpAuthType)
|
||||
{
|
||||
smtpAuthTypes.Add(smtpAuthType);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// The SMTP Reponse code
|
||||
/// </summary>
|
||||
public int ResponseCode
|
||||
{
|
||||
get { return _responseCode; }
|
||||
set { _responseCode=value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The SMTP Message. This will be "OK" if successful,
|
||||
/// otherwise it will be the part that failed.
|
||||
/// </summary>
|
||||
public String Message
|
||||
{
|
||||
get { return _message; }
|
||||
set { _message=value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// An email address.
|
||||
/// The two parts of the email address object
|
||||
/// are the email address itself and the
|
||||
/// name. The name may be encoded if desired.
|
||||
/// </summary>
|
||||
public class EmailAddress : IEmailStringable
|
||||
{
|
||||
private String _email=null;
|
||||
private String _name=null;
|
||||
private System.Text.Encoding _charset;
|
||||
private Encoding.EncodingType _encodingtype=Encoding.EncodingType.QuotedPrintable;
|
||||
|
||||
#region EmailAddress
|
||||
/// <summary>
|
||||
/// Create an instance of an email address object.
|
||||
/// </summary>
|
||||
/// <param name="email">The address portion of the email</param>
|
||||
/// <param name="name">The name portion of the email.</param>
|
||||
public EmailAddress(String email, String name)
|
||||
{
|
||||
if (email!=null)
|
||||
{
|
||||
email=email.Trim();
|
||||
}
|
||||
this._email=email;
|
||||
this._name=name;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EmailAddress
|
||||
/// <summary>
|
||||
/// Create an instance of an email address object.
|
||||
/// </summary>
|
||||
/// <param name="email">The address portion of the email</param>
|
||||
public EmailAddress(String email)
|
||||
{
|
||||
if (email!=null)
|
||||
{
|
||||
email=email.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
email="";
|
||||
}
|
||||
this._email=email;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EmailAddress
|
||||
/// <summary>
|
||||
/// Create an character-encoded instance of an email address object.
|
||||
/// </summary>
|
||||
/// <param name="email">The address portion of the email</param>
|
||||
/// <param name="name">The name portion of the email.</param>
|
||||
/// <param name="charset">The character set to encode the name portion of the email address.</param>
|
||||
/// <param name="encodingtype">The encoding type to use to encode the name portion of the mail address.</param>
|
||||
public EmailAddress(String email, String name, Encoding.EncodingType encodingtype, System.Text.Encoding charset)
|
||||
{
|
||||
|
||||
if (email!=null)
|
||||
{
|
||||
email=email.Trim();
|
||||
}
|
||||
this._email=email;
|
||||
this._name=name;
|
||||
this._charset=charset;
|
||||
this._encodingtype=encodingtype;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Email
|
||||
/// <summary>
|
||||
/// The email address portion of the email address object
|
||||
/// </summary>
|
||||
public String Email
|
||||
{
|
||||
get {return _email;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Name
|
||||
/// <summary>
|
||||
/// The name portion of the email address object
|
||||
/// </summary>
|
||||
public String Name
|
||||
{
|
||||
get {return _name;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region QuoteSpecials
|
||||
private String QuoteSpecials(String str)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
bool needsQuotes=false;
|
||||
for (int i=0; i< str.Length; i++)
|
||||
{
|
||||
char ch=str[i];
|
||||
if (ch=='\"')
|
||||
{
|
||||
needsQuotes=true;
|
||||
sb.Append('\\');
|
||||
}
|
||||
else if (ch=='(' || ch==')' ||
|
||||
ch=='<' || ch=='>' ||
|
||||
ch==']' || ch=='[' ||
|
||||
ch==':' || ch==';' ||
|
||||
ch=='@' || ch=='\\' ||
|
||||
ch==',' || ch=='.')
|
||||
{
|
||||
needsQuotes=true;
|
||||
|
||||
}
|
||||
sb.Append(ch);
|
||||
|
||||
}
|
||||
if (needsQuotes)
|
||||
{
|
||||
return "\""+sb.ToString()+"\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Create the string representation of this email address
|
||||
/// (encoded or otherwise) as it will appear in the email
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
if (_name!=null && _name.Trim()!="")
|
||||
{
|
||||
|
||||
IEncoder encoder=Encoding.EncoderFactory.GetEncoder(_encodingtype);
|
||||
System.Text.Encoding thecharset=_charset;
|
||||
if (thecharset==null)
|
||||
{
|
||||
thecharset=Utils.Configuration.GetInstance().GetDefaultCharset();
|
||||
}
|
||||
String encodedname=encoder.EncodeHeaderString("", QuoteSpecials(Name.Trim()), thecharset, false);
|
||||
|
||||
return encodedname+" <"+Email+">";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<"+Email+">";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString
|
||||
/// <summary>
|
||||
/// Calls ToDataString.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
return ToDataString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of EmailAddress objects. Implements
|
||||
/// CollectionBase
|
||||
/// </summary>
|
||||
public class EmailAddressCollection : CollectionBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new instance of the EmailAddressCollection
|
||||
/// </summary>
|
||||
public EmailAddressCollection()
|
||||
{
|
||||
}
|
||||
|
||||
#region Add
|
||||
/// <summary>
|
||||
/// Add an object to the collection
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">The EmailAddress object to add</param>
|
||||
/// <returns></returns>
|
||||
public int Add( EmailAddress emailaddress )
|
||||
{
|
||||
return( List.Add( emailaddress ) );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add
|
||||
/// <summary>
|
||||
/// Append a collection of objects to the existing collection
|
||||
/// </summary>
|
||||
/// <param name="emailaddresses">The EmailAddressCollection to append to the existing collection.</param>
|
||||
public void AddCollection( EmailAddressCollection emailaddresses )
|
||||
{
|
||||
foreach (EmailAddress emailaddress in emailaddresses)
|
||||
{
|
||||
List.Add(emailaddress);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IndexOf
|
||||
/// <summary>
|
||||
/// Find the index of the EmailAddress in the collection
|
||||
/// </summary>
|
||||
/// <param name="value">The object to find.</param>
|
||||
/// <returns>The index, from 0, or -1 if not found.</returns>
|
||||
public int IndexOf( EmailAddress value )
|
||||
{
|
||||
return( List.IndexOf( value ) );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
/// <summary>
|
||||
/// Insert an EmailAddress into the collection at the
|
||||
/// specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index, starting at zero.</param>
|
||||
/// <param name="emailaddress">The email address to add to the collection</param>
|
||||
public void Insert( int index, EmailAddress emailaddress )
|
||||
{
|
||||
List.Insert( index, emailaddress );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Remove
|
||||
/// <summary>
|
||||
/// Remove an address, if found, from the collection.
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">The EmailAddress to remove</param>
|
||||
public void Remove( EmailAddress emailaddress )
|
||||
{
|
||||
List.Remove( emailaddress );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Render the email addresses in a comma-separated list,
|
||||
/// suitable for being rendered in an email.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
bool doneone=false;
|
||||
foreach (EmailAddress emailaddress in List)
|
||||
{
|
||||
if (!doneone)
|
||||
{
|
||||
doneone=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(", ");
|
||||
}
|
||||
sb.Append(emailaddress.ToDataString());
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString
|
||||
/// <summary>
|
||||
/// Calls ToDataString().
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
return ToDataString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,675 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
using DotNetOpenMail.Resources;
|
||||
using DotNetOpenMail.Utils;
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
//using log4net;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// An Email Message
|
||||
/// </summary>
|
||||
public class EmailMessage : ISendableMessage
|
||||
{
|
||||
|
||||
#region variables
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(EmailMessage));
|
||||
|
||||
private String _subject=null;
|
||||
private String _organization=null;
|
||||
private String _bodytext=null;
|
||||
|
||||
private EmailAddress _fromaddress=null;
|
||||
private EmailAddressCollection _toaddresses=new EmailAddressCollection();
|
||||
private EmailAddressCollection _ccaddresses=new EmailAddressCollection();
|
||||
private EmailAddressCollection _bccaddresses=new EmailAddressCollection();
|
||||
|
||||
private EmailAddress _envelopefromaddress=null;
|
||||
|
||||
private String _contenttype;
|
||||
private MimeBoundary _mimeboundary;
|
||||
|
||||
private TextAttachment _textpart=null;
|
||||
private HtmlAttachment _htmlpart=null;
|
||||
|
||||
private String _xmailer=null;
|
||||
|
||||
private ArrayList _mixedfileattachments=new ArrayList();
|
||||
private ArrayList _relatedfileattachments=new ArrayList();
|
||||
private MessageHeaderCollection _custommessageheaders=new MessageHeaderCollection();
|
||||
private System.Text.Encoding _charset;
|
||||
private Encoding.EncodingType _encodingtype=Encoding.EncodingType.QuotedPrintable;
|
||||
#endregion
|
||||
|
||||
#region EmailMessage
|
||||
/// <summary>
|
||||
/// Create a new instance of an EmailMessage.
|
||||
/// </summary>
|
||||
public EmailMessage()
|
||||
{
|
||||
_mimeboundary=new MimeBoundary();
|
||||
_charset=System.Text.Encoding.GetEncoding(Configuration.GetInstance().GetDefaultEncoding("iso-8859-1"));
|
||||
_bodytext=GetNoMimeMessage();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Subject
|
||||
/// <summary>
|
||||
/// The subject line or subject header of the
|
||||
/// email.
|
||||
/// </summary>
|
||||
public String Subject
|
||||
{
|
||||
get {return _subject;}
|
||||
set {_subject=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FromAddress
|
||||
/// <summary>
|
||||
/// The address that appears in the From header. It will
|
||||
/// also be used as the Envelope From address in the SMTP
|
||||
/// negotiation, unless it is overridden by the EnvelopeFromAddress
|
||||
/// setting.
|
||||
/// </summary>
|
||||
public EmailAddress FromAddress
|
||||
{
|
||||
get {return _fromaddress;}
|
||||
set {_fromaddress=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EnvelopeFromAddress
|
||||
/// <summary>
|
||||
/// Normally the FromAddress is used as the
|
||||
/// envelope-from address, but it can be
|
||||
/// overridden here, if it is not null.
|
||||
/// </summary>
|
||||
public EmailAddress EnvelopeFromAddress
|
||||
{
|
||||
get {return _envelopefromaddress;}
|
||||
set {_envelopefromaddress=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddToAddress
|
||||
/// <summary>
|
||||
/// Add a To address to the Headers. This will also
|
||||
/// be used during the "RCPT TO" SMTP negotiation
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">Email Address object of the recipient</param>
|
||||
public void AddToAddress(EmailAddress emailaddress)
|
||||
{
|
||||
_toaddresses.Add(emailaddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Add a To address to the Headers. This will also
|
||||
/// be used during the "RCPT TO" SMTP negotiation
|
||||
/// </summary>
|
||||
/// <param name="email">The plain email address (don't include the name)</param>
|
||||
public void AddToAddress(String email)
|
||||
{
|
||||
_toaddresses.Add(new EmailAddress(email));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToAddresses
|
||||
/// <summary>
|
||||
/// Retrieve the collection of recipients
|
||||
/// that will appear in the "To" header of the
|
||||
/// email.
|
||||
/// </summary>
|
||||
public EmailAddressCollection ToAddresses
|
||||
{
|
||||
get {return _toaddresses;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddCcAddress
|
||||
/// <summary>
|
||||
/// Add a Cc address to the Headers. This will also
|
||||
/// be used during the "RCPT TO" SMTP negotiation
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">Email Address object of the recipient</param>
|
||||
public void AddCcAddress(EmailAddress emailaddress)
|
||||
{
|
||||
_ccaddresses.Add(emailaddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Add a Cc address to the Headers. This will also
|
||||
/// be used during the "RCPT TO" SMTP negotiation
|
||||
/// </summary>
|
||||
/// <param name="email">The plain email address (don't include the name)</param>
|
||||
public void AddCcAddress(String email)
|
||||
{
|
||||
_ccaddresses.Add(new EmailAddress(email));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CcAddresses
|
||||
/// <summary>
|
||||
/// Retrieve the collection of recipients
|
||||
/// that will appear in the "Cc" header of the
|
||||
/// email.
|
||||
/// </summary>
|
||||
public EmailAddressCollection CcAddresses
|
||||
{
|
||||
get {return _ccaddresses;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddBccAddress
|
||||
/// <summary>
|
||||
/// Add a recipient who will be "Blind Carbon Copied"
|
||||
/// as a recipient of the email. BCC addresses are
|
||||
/// not added to the email headers, but only appear
|
||||
/// during the "RCPT TO" SMTP negotiation.
|
||||
/// </summary>
|
||||
/// <param name="emailaddress">The EmailAddress object</param>
|
||||
public void AddBccAddress(EmailAddress emailaddress)
|
||||
{
|
||||
_bccaddresses.Add(emailaddress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a recipient who will be "Blind Carbon Copied"
|
||||
/// as a recipient of the email. BCC addresses are
|
||||
/// not added to the email headers, but only appear
|
||||
/// during the "RCPT TO" SMTP negotiation.
|
||||
/// </summary>
|
||||
/// <param name="email">The plain email address (don't include the name)</param>
|
||||
public void AddBccAddress(String email)
|
||||
{
|
||||
_bccaddresses.Add(new EmailAddress(email));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BccAddresses
|
||||
/// <summary>
|
||||
/// Get the current EmailAddressCollection of BCC addresses
|
||||
/// </summary>
|
||||
public EmailAddressCollection BccAddresses
|
||||
{
|
||||
get {return _bccaddresses;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Organization
|
||||
/// <summary>
|
||||
/// Get/set the organization (as it will appear in the organization
|
||||
/// header
|
||||
/// </summary>
|
||||
public String Organization
|
||||
{
|
||||
get {return _organization;}
|
||||
set {_organization=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region XMailer
|
||||
/// <summary>
|
||||
/// Get the current XMailer setting for the X-Mailer header.
|
||||
/// </summary>
|
||||
public String XMailer
|
||||
{
|
||||
get {return this._xmailer;}
|
||||
set {this._xmailer=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddCustomHeader
|
||||
/// <summary>
|
||||
/// Add a custom mail header, e.g. "X-MyHeader".
|
||||
/// </summary>
|
||||
/// <param name="header">The header name (without a colon)</param>
|
||||
/// <param name="val">The value of the header. This value will not
|
||||
/// be encoded.</param>
|
||||
public void AddCustomHeader(String header, String val)
|
||||
{
|
||||
_custommessageheaders.Add(new MessageHeader(header, val));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HeaderCharSet
|
||||
/// <summary>
|
||||
/// The charset that is used for encoding the headers
|
||||
/// </summary>
|
||||
public System.Text.Encoding HeaderCharSet
|
||||
{
|
||||
get {return _charset;}
|
||||
set {_charset=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HeaderEncoding
|
||||
/// <summary>
|
||||
/// The mime encoding that is used for encoding the headers
|
||||
/// </summary>
|
||||
public Encoding.EncodingType HeaderEncoding
|
||||
{
|
||||
get {return this._encodingtype;}
|
||||
set {_encodingtype=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetStandardHeaders
|
||||
/// <summary>
|
||||
/// Get the minimal header set in the specified character,
|
||||
/// and using the mime encoder provided.
|
||||
/// </summary>
|
||||
private MessageHeaderCollection GetStandardHeaders(System.Text.Encoding charset, IEncoder encoder)
|
||||
{
|
||||
|
||||
MessageHeaderCollection standardheaders=new MessageHeaderCollection();
|
||||
|
||||
standardheaders.Add(new MessageHeader("From", _fromaddress.ToDataString()));
|
||||
standardheaders.Add(new MessageHeader("To", _toaddresses.ToDataString()));
|
||||
|
||||
if (_ccaddresses.Count>0)
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("Cc", _ccaddresses.ToString()));
|
||||
}
|
||||
//if (_bccaddresses.Count>0)
|
||||
//{
|
||||
//standardheaders.Add(new MessageHeader("Bcc", _bccaddresses.ToString()));
|
||||
//}
|
||||
|
||||
String subject=_subject;
|
||||
if (subject==null || subject.Trim()=="")
|
||||
{
|
||||
subject=EncodeHeaderValue("Subject", ARM.GetInstance().GetString("no_subject"));
|
||||
}
|
||||
standardheaders.Add(new MessageHeader("Subject", EncodeHeaderValue("Subject", subject)));
|
||||
standardheaders.Add(new MessageHeader("Date", new RFC2822Date(DateTime.Now, TimeZone.CurrentTimeZone).ToString()));
|
||||
if (!HasBodyTextOnly())
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("MIME-Version", "1.0"));
|
||||
}
|
||||
#region X-Mailer Header
|
||||
if (_xmailer!=null)
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("X-Mailer", _xmailer));
|
||||
}
|
||||
else
|
||||
{
|
||||
String xmailer=Configuration.GetInstance().GetXSender();
|
||||
if (xmailer!=null)
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("X-Mailer", xmailer));
|
||||
}
|
||||
else
|
||||
{
|
||||
standardheaders.Add(new MessageHeader("X-Mailer", "DotNetOpenMail "+VersionInfo.GetInstance().ToString()));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
String contentType=null;
|
||||
if (HasBodyTextOnly())
|
||||
{
|
||||
// ignore the mime stuff for now
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HasMixedContent())
|
||||
{
|
||||
contentType="multipart/mixed;"+SmtpProxy.ENDOFLINE+
|
||||
" boundary=\""+_mimeboundary.BoundaryString+"\"";
|
||||
}
|
||||
else if (HasRelatedContent())
|
||||
{
|
||||
contentType="multipart/related;"+SmtpProxy.ENDOFLINE+
|
||||
" boundary=\""+_mimeboundary.BoundaryString+"\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
contentType="multipart/alternative;"+SmtpProxy.ENDOFLINE+
|
||||
" boundary=\""+_mimeboundary.BoundaryString+"\"";
|
||||
}
|
||||
|
||||
// note: see http://www.faqs.org/rfcs/rfc2045.html , part 6.4
|
||||
//contentType+=" charset=\""+charset.BodyName+"\"";
|
||||
|
||||
standardheaders.Add(new MessageHeader("Content-Type", contentType));
|
||||
//standardheaders.Add(new MessageHeader("Content-Transfer-Encoding", encoder.ContentTransferEncodingString));
|
||||
}
|
||||
return standardheaders;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeHeaderValue
|
||||
/// <summary>
|
||||
/// Encode a header value using the current header encoder and charset.
|
||||
/// </summary>
|
||||
/// <param name="name">The header name</param>
|
||||
/// <param name="val">The header value</param>
|
||||
/// <returns></returns>
|
||||
private String EncodeHeaderValue(String name, String val)
|
||||
{
|
||||
IEncoder encoder=Encoding.EncoderFactory.GetEncoder(this.HeaderEncoding);
|
||||
return encoder.EncodeHeaderString(name, val, this.HeaderCharSet, false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HasMixedContent
|
||||
/// <summary>
|
||||
/// Returns true if there is content that should be "multipart/mixed"
|
||||
/// </summary>
|
||||
/// <returns>true if the content is multipart/mixed.</returns>
|
||||
private bool HasMixedContent()
|
||||
{
|
||||
return (_mixedfileattachments.Count > 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HasRelatedContent
|
||||
/// <summary>
|
||||
/// Returns true if there is content that should be "multipart/related"
|
||||
/// </summary>
|
||||
/// <returns>true if the content is multipart/related.</returns>
|
||||
private bool HasRelatedContent()
|
||||
{
|
||||
return (_relatedfileattachments.Count > 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataStringHeaders
|
||||
/// <summary>
|
||||
/// Encode the headers as they will appear in the email
|
||||
/// </summary>
|
||||
/// <param name="charset">the charset encoding for the string</param>
|
||||
/// <param name="encoder">the mime encoding</param>
|
||||
/// <returns>the encoded string</returns>
|
||||
internal String ToDataStringHeaders(System.Text.Encoding charset, IEncoder encoder)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
MessageHeaderCollection standardheaders=GetStandardHeaders(charset, encoder);
|
||||
sb.Append(standardheaders.ToDataString());
|
||||
|
||||
if (_custommessageheaders.Count > 0)
|
||||
{
|
||||
sb.Append(_custommessageheaders.ToDataString());
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HasBodyTextOnly
|
||||
private bool HasBodyTextOnly()
|
||||
{
|
||||
return (_textpart==null
|
||||
&& _htmlpart==null
|
||||
&& !HasMixedContent()
|
||||
&& !HasRelatedContent());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToDataStringBody
|
||||
/// <summary>
|
||||
/// Encode the email body as it will appear in the email
|
||||
/// </summary>
|
||||
/// <returns>the encoded body</returns>
|
||||
internal String ToDataStringBody()
|
||||
{
|
||||
bool mixedistop=false;
|
||||
bool relatedistop=false;
|
||||
bool alternativeistop=false;
|
||||
|
||||
if (HasBodyTextOnly())
|
||||
{
|
||||
return FormatBodyText(_bodytext);
|
||||
}
|
||||
|
||||
MimeBoundary relatedcontentmimeboundary=null;
|
||||
MimeBoundary mixedcontentmimeboundary=null;
|
||||
MimeBoundary altertnativecontentmimeboundary=null;
|
||||
|
||||
#region Determine which uses the top-level boundary
|
||||
if (HasMixedContent())
|
||||
{
|
||||
mixedistop=true;
|
||||
mixedcontentmimeboundary=_mimeboundary;
|
||||
relatedcontentmimeboundary=new MimeBoundary();
|
||||
altertnativecontentmimeboundary=new MimeBoundary();
|
||||
}
|
||||
else if (HasRelatedContent())
|
||||
{
|
||||
relatedistop=true;
|
||||
relatedcontentmimeboundary=_mimeboundary;
|
||||
altertnativecontentmimeboundary=new MimeBoundary();
|
||||
}
|
||||
else
|
||||
{
|
||||
alternativeistop=true;
|
||||
altertnativecontentmimeboundary=_mimeboundary;
|
||||
}
|
||||
#endregion
|
||||
|
||||
MimeContainer alternativemimecontainer=new MimeContainer(altertnativecontentmimeboundary, "multipart/alternative", alternativeistop);
|
||||
MimeContainer topcontainer=alternativemimecontainer;
|
||||
|
||||
#region Text & HTML Parts
|
||||
if (_textpart!=null)
|
||||
{
|
||||
alternativemimecontainer.AddAttachment(_textpart);
|
||||
}
|
||||
|
||||
if (_htmlpart!=null)
|
||||
{
|
||||
alternativemimecontainer.AddAttachment(_htmlpart);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Related Content
|
||||
if (HasRelatedContent())
|
||||
{
|
||||
//topcontainer=new MimeContainer(relatedcontentmimeboundary, "multipart/related", relatedistop);
|
||||
topcontainer=new MimeContainer(relatedcontentmimeboundary, "multipart/related;\r\n type=\"multipart/alternative\"", relatedistop);
|
||||
topcontainer.AddMimeContainer(alternativemimecontainer);
|
||||
foreach (FileAttachment attachment in _relatedfileattachments)
|
||||
{
|
||||
topcontainer.AddAttachment(attachment);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Mixed Content
|
||||
if (HasMixedContent())
|
||||
{
|
||||
|
||||
MimeContainer oldtopcontainer=topcontainer;
|
||||
topcontainer=new MimeContainer(mixedcontentmimeboundary, "multipart/mixed", mixedistop);
|
||||
topcontainer.AddMimeContainer(oldtopcontainer);
|
||||
|
||||
foreach (FileAttachment attachment in _mixedfileattachments)
|
||||
{
|
||||
topcontainer.AddAttachment(attachment);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
if (_bodytext==null)
|
||||
{
|
||||
return topcontainer.ToDataString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return FormatBodyText(_bodytext)+".\r\n\r\n"
|
||||
+topcontainer.ToDataString();
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FormatBodyText
|
||||
/// <summary>
|
||||
/// format the body text---not implemented yet.
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns></returns>
|
||||
private String FormatBodyText(String text)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetNoMimeMessage
|
||||
private String GetNoMimeMessage()
|
||||
{
|
||||
return ARM.GetInstance().GetString("this_is_mime");
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The text that occurs within the body. By default,
|
||||
/// it is a MIME notice, but it can be overridden here.
|
||||
/// NOTE: This is only useful for 7 bit us-ascii currently.
|
||||
/// </summary>
|
||||
public String BodyText
|
||||
{
|
||||
get { return _bodytext;}
|
||||
set { _bodytext=value;}
|
||||
}
|
||||
|
||||
#region ToDataString
|
||||
/// <summary>
|
||||
/// Render the encoded message for smtp "DATA" transmission.
|
||||
/// This is the final version that will get sent to the
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToDataString()
|
||||
{
|
||||
IEncoder encoder=EncoderFactory.GetEncoder(HeaderEncoding);
|
||||
return ToDataStringHeaders(this.HeaderCharSet, encoder)+SmtpProxy.ENDOFLINE+ToDataStringBody();
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
/// <summary>
|
||||
/// Send out the email via the smtp server given. If
|
||||
/// the SMTP server throws an error, an SmtpException will
|
||||
/// be thrown. All other exceptions will be MailExceptions
|
||||
/// </summary>
|
||||
/// <param name="smtpserver">The outgoing SMTP server.</param>
|
||||
/// <returns>true if sent successfully. (note that this
|
||||
/// will not currently return false, but in the future
|
||||
/// a false value may be used)</returns>
|
||||
public bool Send(SmtpServer smtpserver)
|
||||
{
|
||||
//SmtpProxy smtpproxy=smtpserver.GetSmtpProxy();
|
||||
if(_fromaddress == null)
|
||||
{
|
||||
throw new MailException(ARM.GetInstance().GetString("error_no_from"));
|
||||
}
|
||||
|
||||
EmailAddress envelopefrom=_envelopefromaddress;
|
||||
if (envelopefrom==null)
|
||||
{
|
||||
envelopefrom=_fromaddress;
|
||||
}
|
||||
EmailAddressCollection allrecipients=new EmailAddressCollection();
|
||||
allrecipients.AddCollection(_toaddresses);
|
||||
allrecipients.AddCollection(_ccaddresses);
|
||||
allrecipients.AddCollection(_bccaddresses);
|
||||
return smtpserver.Send(this, allrecipients, envelopefrom);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentType
|
||||
/// <summary>
|
||||
/// Set the content type string in the mime header
|
||||
/// </summary>
|
||||
public String ContentType
|
||||
{
|
||||
get {return _contenttype;}
|
||||
set {_contenttype=value;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TextPart
|
||||
/// <summary>
|
||||
/// Set the plain text part of the email. This is optional
|
||||
/// </summary>
|
||||
public TextAttachment TextPart
|
||||
{
|
||||
set {_textpart=value;}
|
||||
get {return _textpart;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HtmlPart
|
||||
/// <summary>
|
||||
/// Set the html part of the email. This is optional
|
||||
/// </summary>
|
||||
public HtmlAttachment HtmlPart
|
||||
{
|
||||
set {_htmlpart=value;}
|
||||
get {return _htmlpart;}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddMixedAttachment
|
||||
/// <summary>
|
||||
/// Add an attachment which will appear to the user as
|
||||
/// a separate file. (It is not referred to in the email itself.)
|
||||
/// </summary>
|
||||
/// <param name="fileattachment">The file attachment</param>
|
||||
public void AddMixedAttachment(FileAttachment fileattachment)
|
||||
{
|
||||
_mixedfileattachments.Add(fileattachment);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddRelatedAttachment
|
||||
/// <summary>
|
||||
/// Add an image which is referred to from another part of
|
||||
/// the email (probably the HTML attachment). You should
|
||||
/// set the ContentID of the file attachment before passing
|
||||
/// it in.
|
||||
/// </summary>
|
||||
/// <param name="fileattachment">The file attachment</param>
|
||||
public void AddRelatedAttachment(FileAttachment fileattachment)
|
||||
{
|
||||
_relatedfileattachments.Add(fileattachment);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Encode a file in Base64 Encoding.
|
||||
///
|
||||
/// See: http://www.freesoft.org/CIE/RFC/1521/7.htm
|
||||
/// </summary>
|
||||
public class Base64Encoder : IEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum chars per line before end of line char(s)
|
||||
/// </summary>
|
||||
public static readonly int MAX_CHARS_PER_LINE=76;
|
||||
|
||||
/// <summary>
|
||||
/// The end-of-line character(s) to use
|
||||
/// </summary>
|
||||
public static readonly String END_OF_LINE="\r\n";
|
||||
|
||||
#region Base64Encoder
|
||||
/// <summary>
|
||||
/// Empty Constructor
|
||||
/// </summary>
|
||||
private Base64Encoder()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInstance
|
||||
/// <summary>
|
||||
/// Create an instance of this class
|
||||
/// </summary>
|
||||
public static Base64Encoder GetInstance()
|
||||
{
|
||||
return new Base64Encoder();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the Stringreader's data in base64.
|
||||
///
|
||||
/// Note: This is not particularly efficient on memory.
|
||||
/// This method should probably be improved to
|
||||
/// take advantage of the Reader, rather than
|
||||
/// taking the whole string into memory.
|
||||
/// </summary>
|
||||
/// <param name="stringreader">Reader for incoming string</param>
|
||||
/// <param name="stringwriter">Writer for outgoing encoded string</param>
|
||||
/// <param name="encoding">The character encoding for the encoded string.</param>
|
||||
public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding encoding)
|
||||
{
|
||||
try
|
||||
{
|
||||
String sourceString=stringreader.ReadToEnd();
|
||||
stringwriter.Write(EncodeString(sourceString, encoding));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new Exception("Error in base64Encode" + e.Message);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the File's data in base64.
|
||||
/// </summary>
|
||||
/// <param name="filestream">Reader for incoming string</param>
|
||||
/// <param name="stringwriter">Writer for outgoing encoded string</param>
|
||||
/// <param name="charset">The character set for the encoded string</param>
|
||||
public void Encode(FileStream filestream, StringWriter stringwriter, System.Text.Encoding charset)
|
||||
{
|
||||
//fs = finfo.OpenRead();
|
||||
byte[] buffer = new byte[filestream.Length];
|
||||
filestream.Read(buffer, 0, buffer.Length);
|
||||
filestream.Close();
|
||||
stringwriter.Write(MakeLines(System.Convert.ToBase64String(buffer, 0, buffer.Length)));
|
||||
|
||||
//Encode(new StringReader(System.Text.Encoding.ASCII.GetString(buffer)), stringwriter);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the File's data in base64.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">Reader for incoming string</param>
|
||||
/// <param name="stringwriter">Writer for outgoing encoded string</param>
|
||||
public void Encode(BinaryReader binaryreader, StringWriter stringwriter)
|
||||
{
|
||||
//fs = finfo.OpenRead();
|
||||
byte[] b;
|
||||
int charstoread=Base64Encoder.MAX_CHARS_PER_LINE * 102;
|
||||
while (true)
|
||||
{
|
||||
b = binaryreader.ReadBytes(charstoread);
|
||||
if (b.Length > 0)
|
||||
{
|
||||
stringwriter.Write(MakeLines(Convert.ToBase64String(b)));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Encode(new StringReader(System.Text.Encoding.ASCII.GetString(buffer)), stringwriter);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeString
|
||||
/// <summary>
|
||||
/// Encode a string in Base64 in a particular characters set
|
||||
/// </summary>
|
||||
/// <param name="sourceString">The source text</param>
|
||||
/// <param name="charset">the charset for the encoded text</param>
|
||||
/// <returns>Returns an encoded string</returns>
|
||||
public String EncodeString(String sourceString, System.Text.Encoding charset)
|
||||
{
|
||||
byte[] sourceBytes = new byte[sourceString.Length];
|
||||
sourceBytes = charset.GetBytes(sourceString);
|
||||
//sourceBytes = System.Text.Encoding.UTF8.GetBytes(sourceString);
|
||||
String result=Convert.ToBase64String(sourceBytes);
|
||||
return (MakeLines(result));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeHeaderString
|
||||
/// <summary>
|
||||
/// Encode header as per RFC 2047:
|
||||
/// http://www.faqs.org/rfcs/rfc2047.html
|
||||
/// </summary>
|
||||
/// <param name="name">The header name</param>
|
||||
/// <param name="val">The header text to be encoded (data only)</param>
|
||||
/// <param name="charset">The charset for the encoded string</param>
|
||||
/// <param name="forceencoding">ignored for this class</param>
|
||||
/// <returns>Returns the encoded string</returns>
|
||||
public String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding)
|
||||
{
|
||||
String encodedtext=EncodeString(val, charset);
|
||||
String tmp="=?"+charset.HeaderName+"?B?"+encodedtext+"?=";
|
||||
return tmp;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region MakeLines
|
||||
/// <summary>
|
||||
/// Chop the text into lines that are smaller
|
||||
/// than MAX_CHARS_PER_LINE
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
private String MakeLines(String source)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
int pos=0;
|
||||
for (int i=0; i<source.Length; i++)
|
||||
{
|
||||
sb.Append(source[i]);
|
||||
pos++;
|
||||
if (pos>=Base64Encoder.MAX_CHARS_PER_LINE)
|
||||
{
|
||||
sb.Append(Base64Encoder.END_OF_LINE);
|
||||
pos=0;
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public String ContentTransferEncodingString
|
||||
{
|
||||
get {return "base64";}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// An encoder that does nothing. (This is essentially
|
||||
/// what the 7bit and 8bit encodings are; they are just
|
||||
/// markers, not actual encodings)
|
||||
/// </summary>
|
||||
public abstract class DoNothingEncoder : IEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
public DoNothingEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Echo the text back unchanged.
|
||||
/// </summary>
|
||||
/// <param name="stringreader">Reader for the incoming string</param>
|
||||
/// <param name="stringwriter">Writer for the outgoing string</param>
|
||||
/// <param name="encoding">The encodigng for the outgoing string (ignored)</param>
|
||||
public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding encoding)
|
||||
{
|
||||
try
|
||||
{
|
||||
stringwriter.Write(stringreader.ReadToEnd());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new Exception("Error writing during Encoding" + e.Message);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Echo the text back unchanged
|
||||
/// </summary>
|
||||
/// <param name="filestream">The incoming filestream</param>
|
||||
/// <param name="stringwriter">The outgoing filestream</param>
|
||||
/// <param name="charset">Charset (ignored)</param>
|
||||
public void Encode(FileStream filestream, StringWriter stringwriter, System.Text.Encoding charset)
|
||||
{
|
||||
byte[] buffer = new byte[filestream.Length];
|
||||
filestream.Read(buffer, 0, buffer.Length);
|
||||
filestream.Close();
|
||||
stringwriter.Write(buffer);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Echo the text back unchanged (good for 7bit text only).
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">The incoming binaryreader</param>
|
||||
/// <param name="stringwriter">The outgoing stream</param>
|
||||
public void Encode(BinaryReader binaryreader, StringWriter stringwriter)
|
||||
{
|
||||
throw new Exception("Binary reader doesn't do anything for this reader");
|
||||
//stringwriter.Write(binaryreader.ReadString());
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Do nothing to the header string
|
||||
/// </summary>
|
||||
/// <param name="name">The header key</param>
|
||||
/// <param name="val">The header value</param>
|
||||
/// <param name="charset">The charset to encode in (ignored)</param>
|
||||
/// <param name="forceencoding">(ignored)</param>
|
||||
/// <returns></returns>
|
||||
public String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public virtual String ContentTransferEncodingString
|
||||
{
|
||||
get {throw new ApplicationException("Implement this");}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Denotes 8bit encoding. Note that this doesn't really
|
||||
/// encode anything; it just specifies that this email is already
|
||||
/// in 8-bit encoding.
|
||||
/// </summary>
|
||||
public class EightBitEncoder : DoNothingEncoder
|
||||
{
|
||||
#region EightBitEncoder
|
||||
/// <summary>
|
||||
/// Empty Constructor
|
||||
/// </summary>
|
||||
private EightBitEncoder()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInstance
|
||||
/// <summary>
|
||||
/// Create the EightBitEncoder object.
|
||||
/// </summary>
|
||||
public static EightBitEncoder GetInstance()
|
||||
{
|
||||
return new EightBitEncoder();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public override String ContentTransferEncodingString
|
||||
{
|
||||
get {return "8bit";}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory for instantiating the right encoder class,
|
||||
/// given an encoding
|
||||
/// </summary>
|
||||
internal class EncoderFactory
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Empty Constructor.
|
||||
/// </summary>
|
||||
internal EncoderFactory()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method for determining the correct encoder for this
|
||||
/// encoding type.
|
||||
/// </summary>
|
||||
/// <param name="encodingtype">Enumerated encoding type</param>
|
||||
/// <returns>Returns the proper IEncoder implementation</returns>
|
||||
/// <exception cref="ApplicationException">Throws an ApplicationException if the specified encoding is unknown.</exception>
|
||||
public static IEncoder GetEncoder(EncodingType encodingtype)
|
||||
{
|
||||
if (encodingtype==EncodingType.Base64)
|
||||
{
|
||||
return Base64Encoder.GetInstance();
|
||||
}
|
||||
else if (encodingtype==EncodingType.QuotedPrintable)
|
||||
{
|
||||
return QPEncoder.GetInstance();
|
||||
}
|
||||
else if (encodingtype==EncodingType.SevenBit)
|
||||
{
|
||||
return SevenBitEncoder.GetInstance();
|
||||
}
|
||||
else if (encodingtype==EncodingType.EightBit)
|
||||
{
|
||||
return EightBitEncoder.GetInstance();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ApplicationException("This encoder type is not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration of encoding types.
|
||||
/// </summary>
|
||||
public enum EncodingType
|
||||
{
|
||||
/// <summary>
|
||||
/// The Quoted-Printable encoding
|
||||
/// </summary>
|
||||
QuotedPrintable,
|
||||
/// <summary>
|
||||
/// The Base-65 encoding
|
||||
/// </summary>
|
||||
Base64,
|
||||
/// <summary>
|
||||
/// The 7Bit encoding marker
|
||||
/// </summary>
|
||||
SevenBit,
|
||||
/// <summary>
|
||||
/// The 8Bit encoding marker
|
||||
/// </summary>
|
||||
EightBit
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface for a string encoder
|
||||
/// </summary>
|
||||
public interface IEncoder
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Encode from the stringreader to the stringwriter.
|
||||
/// </summary>
|
||||
/// <param name="source">an open stringreader to the source string</param>
|
||||
/// <param name="destination">where the output is written</param>
|
||||
/// <param name="charset">the outgoing charset</param>
|
||||
void Encode(StringReader source, StringWriter destination, System.Text.Encoding charset);
|
||||
|
||||
/// <summary>
|
||||
/// Encode the file stream into the stringwriter.
|
||||
/// </summary>
|
||||
/// <param name="filestream">an open stream to file to be read</param>
|
||||
/// <param name="destination">where the output is written</param>
|
||||
/// <param name="charset">the outgoing charset</param>
|
||||
void Encode(FileStream filestream, StringWriter destination, System.Text.Encoding charset);
|
||||
|
||||
/// <summary>
|
||||
/// Encode the binary reader into the stringwriter.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">an open binary reader for the data to be encoded.</param>
|
||||
/// <param name="destination">where the output is written</param>
|
||||
void Encode(BinaryReader binaryreader, StringWriter destination);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Encode the string according to rfc-2047 if some of it
|
||||
/// falls outside the 7bit ASCII charset.
|
||||
/// </summary>
|
||||
/// <param name="name">The header key</param>
|
||||
/// <param name="val">The header value string</param>
|
||||
/// <param name="charset">Charset for the encoded string</param>
|
||||
/// <param name="forceencoding">Force encoding, even if in ascii-only.</param>
|
||||
/// <returns>The encoded string</returns>
|
||||
String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding);
|
||||
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
String ContentTransferEncodingString {get;}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
//using log4net;
|
||||
|
||||
using DotNetOpenMail;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// See: http://www.freesoft.org/CIE/RFC/1521/6.htm
|
||||
/// </summary>
|
||||
public class QPEncoder : IEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Logger
|
||||
/// </summary>
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(QPEncoder));
|
||||
|
||||
/// <summary>
|
||||
/// Maximum characters per line, before the end-of-line character
|
||||
/// </summary>
|
||||
public static readonly int MAX_CHARS_PER_LINE=76;
|
||||
|
||||
/// <summary>
|
||||
/// The end-of-line character(s).
|
||||
/// </summary>
|
||||
public static readonly String END_OF_LINE="\r\n";
|
||||
|
||||
|
||||
#region QPEncoder
|
||||
/// <summary>
|
||||
/// Empty Constructor
|
||||
/// </summary>
|
||||
private QPEncoder()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInstance
|
||||
/// <summary>
|
||||
/// Create an instance of the encoder
|
||||
/// </summary>
|
||||
/// <returns>The instantiated Quoted-printable encoder</returns>
|
||||
public static QPEncoder GetInstance()
|
||||
{
|
||||
return new QPEncoder();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the incoming stream in quoted-printable encoding.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">The incoming binary reader</param>
|
||||
/// <param name="stringwriter">The outgoing string writer</param>
|
||||
public void Encode(BinaryReader binaryreader, StringWriter stringwriter)
|
||||
{
|
||||
throw new ApplicationException("Not Implemented Yet; use a base64 encoder instead.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the incoming stream in quoted-printable encoding.
|
||||
/// </summary>
|
||||
/// <param name="filestream">The incoming file stream</param>
|
||||
/// <param name="stringwriter">The outgoing string writer</param>
|
||||
/// <param name="charset">The charset to write the outgoing string in</param>
|
||||
public void Encode(FileStream filestream, StringWriter stringwriter, System.Text.Encoding charset)
|
||||
{
|
||||
throw new ApplicationException("Not Implemented Yet; use a base64 encoder instead.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the string read by the stringreader into the
|
||||
/// stringwriter. This implementation does not encode
|
||||
/// the characters where encoding is optional, and does
|
||||
/// not encode spaces or tabs (except at the end of a line).
|
||||
///
|
||||
/// Line breaks are converted to the RFC line break (CRLF).
|
||||
// The last linebreak is not included, if any, but this
|
||||
/// </summary>
|
||||
/// <param name="stringreader">The incoming string reader</param>
|
||||
/// <param name="stringwriter">The outgoing stringwriter</param>
|
||||
/// <param name="charset">The outgoing charset for the string</param>
|
||||
public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding charset)
|
||||
{
|
||||
Encode(stringreader, stringwriter, charset, false, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeString
|
||||
/// <summary>
|
||||
/// Encode the string in quoted printable format
|
||||
/// </summary>
|
||||
/// <param name="str">The source string</param>
|
||||
/// <param name="charset">The outgoing charset</param>
|
||||
/// <returns>the encoded string</returns>
|
||||
public String EncodeString(String str, System.Text.Encoding charset)
|
||||
{
|
||||
return EncodeString(str, charset, false, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeString
|
||||
/// <summary>
|
||||
/// Encode the string in quoted printable format
|
||||
/// </summary>
|
||||
/// <param name="sourceString">The source string</param>
|
||||
/// <param name="charset">The outgoing charset</param>
|
||||
/// <param name="forceRFC2047">Force encoding, even if not required by qp RFC</param>
|
||||
/// <param name="offset">The total characters outside the encoding. This is used to figure
|
||||
/// out how long the line will be after encoding.</param>
|
||||
/// <returns>the encoded string</returns>
|
||||
public String EncodeString(String sourceString, System.Text.Encoding charset, bool forceRFC2047, int offset)
|
||||
{
|
||||
|
||||
StringReader sr=new StringReader(sourceString);
|
||||
StringBuilder sb=new StringBuilder();
|
||||
StringWriter sw=new StringWriter(sb);
|
||||
Encode(sr, sw, charset, forceRFC2047, offset);
|
||||
return sb.ToString();
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeHeaderString
|
||||
/// <summary>
|
||||
/// Encode header as per RFC 2047:
|
||||
/// http://www.faqs.org/rfcs/rfc2047.html
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>This doesn't split long lines yet</remarks>
|
||||
/// <param name="name">the header name</param>
|
||||
/// <param name="val">the string to encode</param>
|
||||
/// <param name="charset">The charset to encode to</param>
|
||||
/// <param name="forceencoding">Force encoding, even if not required by qp RFC</param>
|
||||
/// <returns>the encoded string, suitable for use in a header</returns>
|
||||
public String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding)
|
||||
{
|
||||
if (forceencoding || IsNonAscii(val))
|
||||
{
|
||||
|
||||
String start="=?"+charset.HeaderName+"?Q?";
|
||||
String end="?=";
|
||||
|
||||
int offset=name.Length+start.Length+end.Length+2; // the 2 is for the colon and space
|
||||
|
||||
String encodedtext=EncodeString(val, charset, true, offset);
|
||||
//log.Debug("LINE BEFORE SPLIT IS "+encodedtext);
|
||||
if (encodedtext.Length + offset > QPEncoder.MAX_CHARS_PER_LINE)
|
||||
{
|
||||
StringBuilder sb=new StringBuilder("");
|
||||
foreach (String line in encodedtext.Split('\n'))
|
||||
{
|
||||
String tmp=line;
|
||||
if (sb.Length>0)
|
||||
{
|
||||
sb.Append(QPEncoder.END_OF_LINE+" ");
|
||||
}
|
||||
tmp=line.TrimEnd(new char[] {'\r', '='});
|
||||
//if (line.LastIndexOf("\r") == line.Length-1)
|
||||
//{
|
||||
//tmp=line.Substring(0, line.Length-1);
|
||||
//}
|
||||
sb.Append(start+tmp+end);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return start+encodedtext+end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return val;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeChar
|
||||
/// <summary>
|
||||
/// Encode a char according to quoted-printable
|
||||
/// standard
|
||||
/// </summary>
|
||||
/// <param name="ch">the char to encode</param>
|
||||
/// <returns>the encoded char representation</returns>
|
||||
private String EncodeChar(char ch)
|
||||
{
|
||||
int intch=(int) ch;
|
||||
if (intch > 255)
|
||||
{
|
||||
//log.Debug("encoding qp: "+String.Format("0x{0:X4}", intch));
|
||||
int ch1=intch >> 8;
|
||||
int ch2=intch & 0xff;
|
||||
return String.Format("={0:X2}={1:X2}", ch1, ch2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return String.Format("={0:X2}",(int) ch);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeByte
|
||||
/// <summary>
|
||||
/// Encode a byte according to quoted-printable
|
||||
/// standard
|
||||
/// </summary>
|
||||
/// <param name="ch">the byte to encode</param>
|
||||
/// <returns>the encoded byte representation</returns>
|
||||
private String EncodeByte(byte ch)
|
||||
{
|
||||
return String.Format("={0:X2}",(int) ch);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public String ContentTransferEncodingString
|
||||
{
|
||||
get {return "quoted-printable";}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NeedsEncoding
|
||||
/// <summary>
|
||||
/// Return true if the char needs to be encoded.
|
||||
/// </summary>
|
||||
/// <param name="ch"></param>
|
||||
/// <param name="forceRFC2047"></param>
|
||||
/// <returns></returns>
|
||||
internal bool NeedsEncoding(char ch, bool forceRFC2047)
|
||||
{
|
||||
if ((ch <= 0x1f && ch != 0x09) || // less than space (except tab)
|
||||
ch == 0x3d || // equal sign
|
||||
ch>= 0x7f // above 7bit
|
||||
|| (forceRFC2047 && (ch==0x20 || ch==0x09 || ch==0x3f))
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NeedsEncoding
|
||||
/// <summary>
|
||||
/// Return true if the byte needs to be encoded.
|
||||
/// </summary>
|
||||
/// <param name="ch"></param>
|
||||
/// <param name="forceRFC2047"></param>
|
||||
/// <returns></returns>
|
||||
internal bool NeedsEncoding(byte ch, bool forceRFC2047)
|
||||
{
|
||||
if ((ch <= 0x1f && ch != 0x09) || // less than space (except tab)
|
||||
ch == 0x3d || // equal sign
|
||||
ch>= 0x7f // above 7bit
|
||||
|| (forceRFC2047 && (ch==0x20 || ch==0x09 || ch==0x3f))
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsNonAscii
|
||||
/// <summary>
|
||||
/// Return true if the string needs to be encoded.
|
||||
/// </summary>
|
||||
/// <param name="str">The string to check</param>
|
||||
/// <returns>true if outside 127-bit, or one of the
|
||||
/// quoted-printable special characters.</returns>
|
||||
internal bool IsNonAscii(String str)
|
||||
{
|
||||
for (int i=0; i<str.Length; i++)
|
||||
{
|
||||
if (IsNonAscii(str[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsNonAscii
|
||||
/// <summary>
|
||||
/// Check if the character is one of the non-qp
|
||||
/// characters
|
||||
/// </summary>
|
||||
/// <param name="ch">the character to check</param>
|
||||
/// <returns>true if outside the acceptable qp range</returns>
|
||||
internal bool IsNonAscii(char ch)
|
||||
{
|
||||
if ((ch <= 0x1f && ch != 0x09) || // less than space (except tab)
|
||||
ch == 0x3d || // equal sign
|
||||
ch>= 0x7f // above 7bit
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// Encode the string read by the stringreader into the
|
||||
/// stringwriter. This implementation does not encode
|
||||
/// the characters where encoding is optional, and does
|
||||
/// not encode spaces or tabs (except at the end of a line).
|
||||
///
|
||||
/// Line breaks are converted to the RFC line break (CRLF).
|
||||
// The last linebreak is not included, if any---although this
|
||||
/// may change in the future.
|
||||
/// </summary>
|
||||
/// <param name="stringreader">The incoming string reader</param>
|
||||
/// <param name="stringwriter">The outgoing stringwriter</param>
|
||||
/// <param name="charset">The outgoing charset for the string</param>
|
||||
/// <param name="forceRFC2047">If true, force the encoding of all the
|
||||
/// <param name="offset">These are the number of characters that
|
||||
/// will appear outside this string, e.g. the header name, etc.</param>
|
||||
/// characters (not just those that are given in RFC2027).</param>
|
||||
public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding charset, bool forceRFC2047, int offset)
|
||||
{
|
||||
if (offset > QPEncoder.MAX_CHARS_PER_LINE - 15)
|
||||
{
|
||||
throw new MailException("Invalid offset (header name is too long): "+offset);
|
||||
}
|
||||
|
||||
String line=null;
|
||||
|
||||
bool forceencoding=false;
|
||||
if (charset==null)
|
||||
{
|
||||
charset=Utils.Configuration.GetInstance().GetDefaultCharset();
|
||||
}
|
||||
while((line=stringreader.ReadLine())!=null)
|
||||
{
|
||||
int columnposition=0;
|
||||
|
||||
byte[] bytes=charset.GetBytes(line);
|
||||
|
||||
// see Rule #3 (spaces and tabs at end of line are encoded)
|
||||
StringBuilder blankendchars=new StringBuilder("");
|
||||
|
||||
int endpos=bytes.Length-1;
|
||||
|
||||
while (endpos >=0 && (bytes[endpos]==0x20 || bytes[endpos]==0x09) )
|
||||
{
|
||||
blankendchars.Insert(blankendchars.Length, EncodeByte(bytes[endpos]));
|
||||
endpos--;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<=endpos; i++)
|
||||
{
|
||||
String towrite="";
|
||||
if (forceencoding || NeedsEncoding(bytes[i], forceRFC2047))
|
||||
{
|
||||
columnposition+=3;
|
||||
towrite=EncodeByte(bytes[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
columnposition+=1;
|
||||
// this is a single byte, so multibyte chars won't
|
||||
// be affected by this.
|
||||
towrite=charset.GetString(new byte[]{bytes[i]});
|
||||
}
|
||||
|
||||
if (offset + columnposition > QPEncoder.MAX_CHARS_PER_LINE )
|
||||
{
|
||||
stringwriter.Write("="+QPEncoder.END_OF_LINE);
|
||||
columnposition=0;
|
||||
}
|
||||
stringwriter.Write(towrite);
|
||||
}
|
||||
|
||||
if (blankendchars.Length > 0)
|
||||
{
|
||||
if (offset+columnposition+blankendchars.Length > QPEncoder.MAX_CHARS_PER_LINE)
|
||||
{
|
||||
stringwriter.Write("="+QPEncoder.END_OF_LINE);
|
||||
}
|
||||
stringwriter.Write(blankendchars);
|
||||
}
|
||||
if (stringreader.Peek() >= 0)
|
||||
{
|
||||
stringwriter.Write("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail.Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Denotes 7bit encoding. Note that this doesn't really
|
||||
/// encode anything; it just specifies that this email is already
|
||||
/// in 7-bit ascii encoding.
|
||||
/// </summary>
|
||||
public class SevenBitEncoder : DoNothingEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
private SevenBitEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of this class.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SevenBitEncoder GetInstance()
|
||||
{
|
||||
return new SevenBitEncoder();
|
||||
}
|
||||
|
||||
|
||||
#region ContentTransferEncodingString
|
||||
/// <summary>
|
||||
/// The String that goes in the content transfer encoding header
|
||||
/// </summary>
|
||||
public override String ContentTransferEncodingString
|
||||
{
|
||||
get {return "7bit";}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
//using log4net;
|
||||
|
||||
using DotNetOpenMail.Encoding;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A mime representation of a file which can be transferred
|
||||
/// via email.
|
||||
/// </summary>
|
||||
public class FileAttachment : AbstractEmailAttachment
|
||||
{
|
||||
|
||||
//private static readonly ILog log = LogManager.GetLogger(typeof(FileAttachment));
|
||||
|
||||
/// <summary>
|
||||
/// Create a new File attachment from a FileInfo object
|
||||
/// </summary>
|
||||
/// <param name="fileinfo">A fileinfo object which points to a local file.</param>
|
||||
public FileAttachment(FileInfo fileinfo) : this(fileinfo, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new text file attachment from a StreamReader.
|
||||
/// </summary>
|
||||
/// <param name="streamreader">An open streamreader</param>
|
||||
public FileAttachment(StreamReader streamreader) : this(streamreader, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new binary file attachment from a BinaryReader.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">An open binaryreader</param>
|
||||
public FileAttachment(BinaryReader binaryreader) : this(binaryreader, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new binary file attachment from an array of bytes.
|
||||
/// </summary>
|
||||
/// <param name="bytes">An array of bytes</param>
|
||||
public FileAttachment(byte[] bytes) : this(bytes, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new file attachment from a String.
|
||||
/// </summary>
|
||||
/// <param name="content">The contents of the file</param>
|
||||
public FileAttachment(String content) : this(content, null)
|
||||
{
|
||||
}
|
||||
|
||||
#region FileAttachment
|
||||
/// <summary>
|
||||
/// Create a new File attachment with a contentid from a FileInfo object.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="fileinfo">A fileinfo object which points to a local file.</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(FileInfo fileinfo, String contentid)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
if (FileName==null)
|
||||
{
|
||||
FileName=fileinfo.Name;
|
||||
}
|
||||
this._fileinfo=fileinfo;
|
||||
this._contentid=contentid;
|
||||
this.CharSet=null;
|
||||
//this.Contents=contents;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
//this.Encoder=EncoderFactory.GetEncoder(EncoderFactory.GetEncoder(EncodingType);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileAttachment
|
||||
/// <summary>
|
||||
/// Create a new file attachment from a StreamReader.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="streamreader">An open streamreader</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(StreamReader streamreader, String contentid)
|
||||
{
|
||||
if (this.ContentType==null)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
}
|
||||
String tmp=streamreader.ReadToEnd();
|
||||
streamreader.Close();
|
||||
this.Contents=tmp;
|
||||
this.CharSet=null;
|
||||
this._contentid=contentid;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileAttachment
|
||||
/// <summary>
|
||||
/// Create a new file attachment from a BinaryReader.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="binaryreader">An open binary readerr</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(BinaryReader binaryreader, String contentid)
|
||||
{
|
||||
if (this.ContentType==null)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
}
|
||||
|
||||
this._contentbytes=Utils.BinaryReaderUtil.ReadIntoByteArray(binaryreader);
|
||||
binaryreader.Close();
|
||||
this.CharSet=null;
|
||||
this._contentid=contentid;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileAttachment
|
||||
/// <summary>
|
||||
/// Create a new file attachment from a byte array.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="bytes">An array of bytes</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(byte[] bytes, String contentid)
|
||||
{
|
||||
if (this.ContentType==null)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
}
|
||||
this.ContentBytes=bytes;
|
||||
this.CharSet=null;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Create a new text file attachment from a String.
|
||||
/// The contentid will be used to refer to this attachment in
|
||||
/// another mime part of the email.
|
||||
/// </summary>
|
||||
/// <param name="content">The contents of the file</param>
|
||||
/// <param name="contentid">the content id value</param>
|
||||
public FileAttachment(String content, String contentid)
|
||||
{
|
||||
if (this.ContentType==null)
|
||||
{
|
||||
this.ContentType="binary/octet-stream";
|
||||
}
|
||||
this.Contents=content;
|
||||
this.CharSet=null;
|
||||
this.Encoding=EncodingType.Base64;
|
||||
this._contentid=contentid;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
using log4net;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// Perform the low-level interaction with the external
|
||||
/// SMTP server
|
||||
/// </summary>
|
||||
public class GenericSmtpNegotiator : TcpClient, ISmtpProxy
|
||||
{
|
||||
private bool _isConnected=false;
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(GenericSmtpNegotiator));
|
||||
|
||||
private IPEndPoint _ipEndPoint;
|
||||
private int _timeout=30000; // default is 30 seconds
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the GenericSmtpNegotiator
|
||||
/// </summary>
|
||||
/// <param name="ipEndPoint"></param>
|
||||
public GenericSmtpNegotiator(IPEndPoint ipEndPoint)
|
||||
{
|
||||
this._ipEndPoint=ipEndPoint;
|
||||
this.ReceiveTimeout=_timeout;
|
||||
}
|
||||
|
||||
#region Open
|
||||
/// <summary>
|
||||
/// Connect to the server and return the initial
|
||||
/// welcome string. Throw a MailException if we
|
||||
/// can't connect.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SmtpResponse Open()
|
||||
{
|
||||
try {
|
||||
Connect(_ipEndPoint);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new MailException("Could not connect to "+_ipEndPoint.Address+":"+_ipEndPoint.Port, ex);
|
||||
}
|
||||
_isConnected=true;
|
||||
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Helo
|
||||
/// <summary>
|
||||
/// Send the HELO string.
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse Helo(String localHostName)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
String message = "HELO "+localHostName+SmtpProxy.ENDOFLINE;
|
||||
//LogDebug("SENDING: "+message);
|
||||
|
||||
Write(message);
|
||||
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MailFrom
|
||||
/// <summary>
|
||||
/// Send the MAIL FROM command
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <param name="mailfrom">The Envelope-From address</param>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse MailFrom(EmailAddress mailfrom)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
String message = "MAIL FROM: <"+mailfrom.Email+">"+SmtpProxy.ENDOFLINE;
|
||||
LogDebug("SENDING: "+message);
|
||||
|
||||
Write(message);
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RcptTo
|
||||
/// <summary>
|
||||
/// Send the MAIL FROM command
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <param name="rcpttoaddress">A recipient's address</param>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse RcptTo(EmailAddress rcpttoaddress)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
|
||||
String message= "RCPT TO: <"+rcpttoaddress.Email+">"+SmtpProxy.ENDOFLINE;
|
||||
LogDebug("SENDING: "+message);
|
||||
Write(message);
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
/// <summary>
|
||||
/// Send the DATA string (without the data)
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse Data()
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
String message = "DATA"+SmtpProxy.ENDOFLINE;
|
||||
//LogDebug("SENDING: "+message);
|
||||
|
||||
Write(message);
|
||||
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WriteData
|
||||
/// <summary>
|
||||
/// Send the message content string
|
||||
/// Throw a MailException if we can't
|
||||
/// connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse WriteData(String message)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
|
||||
StringReader reader=new StringReader(message);
|
||||
String line=null;
|
||||
|
||||
while ((line=reader.ReadLine())!=null)
|
||||
{
|
||||
// checking for dot at the beginning of the
|
||||
// line (RFC821 sec. 4.5.2)
|
||||
|
||||
if (line.Length > 0 && line[0]=='.')
|
||||
{
|
||||
Write("."+line+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Write(line+SmtpProxy.ENDOFLINE);
|
||||
}
|
||||
}
|
||||
Write(SmtpProxy.ENDOFLINE+"."+SmtpProxy.ENDOFLINE);
|
||||
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadSmtpResponse
|
||||
private SmtpResponse ReadSmtpResponse()
|
||||
{
|
||||
String response=ReadResponse();
|
||||
String responseCodeStr=response.Substring(0, 3);
|
||||
String responseMessage="";
|
||||
if (response.Length > 4)
|
||||
{
|
||||
responseMessage=response.Substring(4);
|
||||
}
|
||||
try
|
||||
{
|
||||
int responseCode=Convert.ToInt32(responseCodeStr);
|
||||
return new SmtpResponse(responseCode, responseMessage);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new MailException("Could not understand response from server: "+response);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Write
|
||||
/// <summary>
|
||||
/// Write a string to the current connection.
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
private void Write(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Text.ASCIIEncoding en = new System.Text.ASCIIEncoding() ;
|
||||
byte[] WriteBuffer = new byte[1024] ;
|
||||
WriteBuffer = en.GetBytes(message) ;
|
||||
|
||||
NetworkStream stream = GetStream() ;
|
||||
stream.Write(WriteBuffer,0,WriteBuffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogError(ex.Message);
|
||||
throw new MailException("Error while sending data to the server: "+ex.Message, ex);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Quit
|
||||
/// <summary>
|
||||
/// Send the QUIT command
|
||||
/// Throw a MailException if we can't connect.
|
||||
/// </summary>
|
||||
/// <returns>the SMTP response</returns>
|
||||
public SmtpResponse Quit()
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
throw new MailException("The connection is closed.");
|
||||
}
|
||||
Write("QUIT"+SmtpProxy.ENDOFLINE);
|
||||
return ReadSmtpResponse();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadResponse
|
||||
private string ReadResponse()
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
|
||||
byte []serverbuff = new Byte[1024];
|
||||
NetworkStream stream = GetStream();
|
||||
int count = stream.Read( serverbuff, 0, 1024 );
|
||||
if (count == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return enc.GetString( serverbuff, 0, count );
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogError(ex.Message);
|
||||
throw new MailException("Error while receiving data from server: "+ex.Message, ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LogError
|
||||
private void LogError(String message)
|
||||
{
|
||||
log.Error(message);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LogDebug
|
||||
private void LogDebug(String message)
|
||||
{
|
||||
log.Debug(message);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using DotNetOpenMail.Encoding;
|
||||
using DotNetOpenMail.Utils;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// An HTML email attachment
|
||||
/// </summary>
|
||||
public class HtmlAttachment : AbstractEmailAttachment
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Create a new HTML Attachment. It flags the content/type
|
||||
/// as "text/html", uses Quoted Printable encoding by
|
||||
/// default, and uses the default character set, which is
|
||||
/// ISO-8859-1 unless otherwise specified in the .config file.
|
||||
/// </summary>
|
||||
/// <param name="contents">The HTML content of the attachment</param>
|
||||
public HtmlAttachment(String contents)
|
||||
{
|
||||
this.ContentType="text/html";
|
||||
this.Contents=contents;
|
||||
this.CharSet=System.Text.Encoding.GetEncoding(Configuration.GetInstance().GetDefaultEncoding("iso-8859-1"));
|
||||
this.Encoding=EncodingType.QuotedPrintable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// Objects of a class which implements this interface
|
||||
/// can be converted to a string which can be used in
|
||||
/// an email.
|
||||
/// </summary>
|
||||
internal interface IEmailStringable
|
||||
{
|
||||
String ToDataString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Mike Bridge <mike@bridgecanada.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any
|
||||
* person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice
|
||||
* shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace DotNetOpenMail
|
||||
{
|
||||
/// <summary>
|
||||
/// A message which can be sent.
|
||||
/// </summary>
|
||||
internal interface ISendableMessage : IEmailStringable
|
||||
{
|
||||
bool Send(SmtpServer smtpserver);
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user