From a32acbdd23c6e6e058735f4f01b5686a8db4e6f4 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 27 Nov 2018 14:22:36 +0000 Subject: [PATCH] add DotNetOpenMail source --- .../Backup/DotNetOpenMail.sln | 38 + .../DotNetOpenMail/AbstractEmailAttachment.cs | 354 +++ .../Backup/DotNetOpenMail/AssemblyInfo.cs | 86 + .../DotNetOpenMail/DotNetOpenMail.csproj | 309 +++ .../DotNetOpenMail/DotNetOpenMail.csproj.user | 48 + .../Backup/DotNetOpenMail/EhloSmtpResponse.cs | 80 + .../Backup/DotNetOpenMail/EmailAddress.cs | 205 ++ .../DotNetOpenMail/EmailAddressCollection.cs | 151 ++ .../Backup/DotNetOpenMail/EmailMessage.cs | 675 +++++ .../DotNetOpenMail/Encoding/Base64Encoder.cs | 221 ++ .../Encoding/DoNothingEncoder.cs | 96 + .../Encoding/EightBitEncoder.cs | 73 + .../DotNetOpenMail/Encoding/EncoderFactory.cs | 79 + .../DotNetOpenMail/Encoding/EncodingType.cs | 27 + .../DotNetOpenMail/Encoding/IEncoder.cs | 82 + .../DotNetOpenMail/Encoding/QPEncoder.cs | 446 ++++ .../Encoding/SevenBitEncoder.cs | 69 + .../Backup/DotNetOpenMail/FileAttachment.cs | 199 ++ .../Backup/DotNetOpenMail/HtmlAttachment.cs | 56 + .../Backup/DotNetOpenMail/IEmailStringable.cs | 42 + .../Backup/DotNetOpenMail/ISendableMessage.cs | 41 + .../Backup/DotNetOpenMail/ISmtpProxy.cs | 95 + .../DotNetOpenMail/Logging/LogMessage.cs | 44 + .../Backup/DotNetOpenMail/Logging/Logger.cs | 77 + .../Backup/DotNetOpenMail/MailException.cs | 63 + .../Backup/DotNetOpenMail/MessageHeader.cs | 111 + .../DotNetOpenMail/MessageHeaderCollection.cs | 120 + .../Backup/DotNetOpenMail/MimeBoundary.cs | 86 + .../Backup/DotNetOpenMail/MimeContainer.cs | 101 + .../Backup/DotNetOpenMail/RFC2822Date.cs | 75 + .../Backup/DotNetOpenMail/RawEmailMessage.cs | 128 + .../Backup/DotNetOpenMail/Resources/ARM.cs | 170 ++ .../Resources/DotNetOpenMail.resx | 54 + .../DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs | 63 + .../DotNetOpenMail/SmtpAuth/LoginAuthToken.cs | 135 + .../SmtpAuth/SmtpAuthFactory.cs | 67 + .../DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs | 101 + .../Backup/DotNetOpenMail/SmtpException.cs | 92 + .../Backup/DotNetOpenMail/SmtpProxy.cs | 516 ++++ .../Backup/DotNetOpenMail/SmtpResponse.cs | 99 + .../Backup/DotNetOpenMail/SmtpResponseCode.cs | 179 ++ .../Backup/DotNetOpenMail/SmtpServer.cs | 532 ++++ .../Backup/DotNetOpenMail/TextAttachment.cs | 59 + .../DotNetOpenMail/Utils/BinaryStreamUtil.cs | 58 + .../DotNetOpenMail/Utils/Configuration.cs | 112 + .../Utils/EmailAddressParser.cs | 114 + .../DotNetOpenMail/Utils/VersionInfo.cs | 75 + .../DotNetOpenMailTests/AssemblyInfo.cs | 89 + .../DotNetOpenMailTests.csproj | 251 ++ .../DotNetOpenMailTests.csproj.user | 48 + .../DotNetOpenMailTests/EmailAddressTests.cs | 75 + .../EmailMessageInAlternateEncodings.cs | 307 +++ .../DotNetOpenMailTests/EmailMessageTests.cs | 590 +++++ .../Encoding/Base64EncoderTests.cs | 103 + .../Encoding/EightBitEncoderTests.cs | 132 + .../Encoding/QPEncoderTests.cs | 170 ++ .../Encoding/SevenBitEncoderTests.cs | 132 + .../DotNetOpenMailTests/ExampleTests.cs | 122 + .../FileAttachmentTests.cs | 248 ++ .../FileAttachmentTests2.cs | 186 ++ .../DotNetOpenMailTests/Log4netLogger.cs | 26 + .../Backup/DotNetOpenMailTests/QuickTest.cs | 98 + .../DotNetOpenMailTests/RFC2822DateTests.cs | 109 + .../RawEmailMessageTests.cs | 78 + .../DotNetOpenMailTests/Resources/ARMTests.cs | 57 + .../DotNetOpenMailTests/RussianTests.cs | 72 + .../SmtpAuth/LocalAuthTests.cs | 309 +++ .../SmtpAuth/MockedSlowProxy.cs | 33 + .../SmtpAuth/MockedSmtpProxy.cs | 94 + .../DotNetOpenMailTests/SmtpProxyTests.cs | 94 + .../SmtpServerTests/SmtpServerTests.cs | 76 + .../DotNetOpenMailTests/TestAddressHelper.cs | 78 + .../TestFiles/ImportedEmail.txt | 4 + .../DotNetOpenMailTests/TestFiles/grover.jpg | Bin 0 -> 5881 bytes .../TestFiles/groverUpsideDown.jpg | Bin 0 -> 5763 bytes .../Utils/EmailAddressParserTests.cs | 69 + DotNetOpenMail-0.5.8b/CHANGES.txt | 85 + DotNetOpenMail-0.5.8b/DotNetOpenMail.sln | 40 + .../DotNetOpenMail/AbstractEmailAttachment.cs | 354 +++ .../DotNetOpenMail/AssemblyInfo.cs | 86 + .../DotNetOpenMail/DotNetOpenMail.csproj | 220 ++ .../DotNetOpenMail/DotNetOpenMail.csproj.user | 44 + .../DotNetOpenMail/DotNetOpenMail.xml | 2208 +++++++++++++++++ .../DotNetOpenMail/EhloSmtpResponse.cs | 80 + .../DotNetOpenMail/EmailAddress.cs | 205 ++ .../DotNetOpenMail/EmailAddressCollection.cs | 151 ++ .../DotNetOpenMail/EmailMessage.cs | 675 +++++ .../DotNetOpenMail/Encoding/Base64Encoder.cs | 221 ++ .../Encoding/DoNothingEncoder.cs | 96 + .../Encoding/EightBitEncoder.cs | 73 + .../DotNetOpenMail/Encoding/EncoderFactory.cs | 79 + .../DotNetOpenMail/Encoding/EncodingType.cs | 27 + .../DotNetOpenMail/Encoding/IEncoder.cs | 82 + .../DotNetOpenMail/Encoding/QPEncoder.cs | 446 ++++ .../Encoding/SevenBitEncoder.cs | 69 + .../DotNetOpenMail/FileAttachment.cs | 199 ++ .../DotNetOpenMail/GenericSmtpNegotiator.cs | 279 +++ .../DotNetOpenMail/HtmlAttachment.cs | 56 + .../DotNetOpenMail/IEmailStringable.cs | 42 + .../DotNetOpenMail/ISendableMessage.cs | 41 + .../DotNetOpenMail/ISmtpProxy.cs | 95 + .../DotNetOpenMail/Logging/LogMessage.cs | 44 + .../DotNetOpenMail/Logging/Logger.cs | 77 + .../DotNetOpenMail/MailException.cs | 63 + .../DotNetOpenMail/MessageHeader.cs | 111 + .../DotNetOpenMail/MessageHeaderCollection.cs | 120 + .../DotNetOpenMail/MimeBoundary.cs | 86 + .../DotNetOpenMail/MimeContainer.cs | 101 + .../DotNetOpenMail/RFC2822Date.cs | 75 + .../DotNetOpenMail/RawEmailMessage.cs | 128 + .../DotNetOpenMail/Resources/ARM.cs | 170 ++ .../Resources/DotNetOpenMail.resx | 54 + .../DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs | 63 + .../DotNetOpenMail/SmtpAuth/LoginAuthToken.cs | 135 + .../SmtpAuth/SmtpAuthFactory.cs | 67 + .../DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs | 101 + .../DotNetOpenMail/SmtpAuth/SmtpAuthType.cs | 49 + .../DotNetOpenMail/SmtpException.cs | 92 + .../DotNetOpenMail/SmtpProxy.cs | 516 ++++ .../DotNetOpenMail/SmtpResponse.cs | 99 + .../DotNetOpenMail/SmtpResponseCode.cs | 179 ++ .../DotNetOpenMail/SmtpServer.cs | 532 ++++ .../DotNetOpenMail/TextAttachment.cs | 59 + .../DotNetOpenMail/Utils/BinaryStreamUtil.cs | 58 + .../DotNetOpenMail/Utils/Configuration.cs | 112 + .../Utils/EmailAddressParser.cs | 114 + .../DotNetOpenMail/Utils/VersionInfo.cs | 75 + ...gnTimeResolveAssemblyReferencesInput.cache | Bin 0 -> 6306 bytes ...NetOpenMail.csproj.CoreCompileInputs.cache | 1 + ...tNetOpenMail.csprojAssemblyReference.cache | Bin 0 -> 15454 bytes ...le_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs | 0 ...le_5937a670-0e60-4077-877b-f7221da3dda1.cs | 0 ...le_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs | 0 .../DesignTimeResolveAssemblyReferences.cache | Bin 0 -> 670 bytes ...gnTimeResolveAssemblyReferencesInput.cache | Bin 0 -> 6310 bytes ...le_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs | 0 ...le_5937a670-0e60-4077-877b-f7221da3dda1.cs | 0 ...le_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs | 0 .../DotNetOpenMailTests.dll.config.demo | 9 + .../DotNetOpenMailTests.dll.log4net | 40 + .../DotNetOpenMailTests/AssemblyInfo.cs | 89 + .../DotNetOpenMailTests.csproj | 183 ++ .../DotNetOpenMailTests.csproj.user | 44 + .../DotNetOpenMailTests/EmailAddressTests.cs | 75 + .../EmailMessageInAlternateEncodings.cs | 307 +++ .../DotNetOpenMailTests/EmailMessageTests.cs | 590 +++++ .../Encoding/Base64EncoderTests.cs | 103 + .../Encoding/EightBitEncoderTests.cs | 132 + .../Encoding/QPEncoderTests.cs | 170 ++ .../Encoding/SevenBitEncoderTests.cs | 132 + .../DotNetOpenMailTests/ExampleTests.cs | 122 + .../FileAttachmentTests.cs | 248 ++ .../FileAttachmentTests2.cs | 186 ++ .../DotNetOpenMailTests/Log4netLogger.cs | 26 + .../DotNetOpenMailTests/QuickTest.cs | 98 + .../DotNetOpenMailTests/RFC2822DateTests.cs | 109 + .../RawEmailMessageTests.cs | 78 + .../DotNetOpenMailTests/Resources/ARMTests.cs | 57 + .../DotNetOpenMailTests/RussianTests.cs | 72 + .../SmtpAuth/LocalAuthTests.cs | 309 +++ .../SmtpAuth/MockedSlowProxy.cs | 33 + .../SmtpAuth/MockedSmtpProxy.cs | 94 + .../DotNetOpenMailTests/SmtpProxyTests.cs | 94 + .../SmtpServerTests/SmtpServerTests.cs | 76 + .../DotNetOpenMailTests/TestAddressHelper.cs | 78 + .../TestFiles/ImportedEmail.txt | 4 + .../TestFiles/acrobattestpage.pdf | Bin 0 -> 20016 bytes .../DotNetOpenMailTests/TestFiles/grover.jpg | Bin 0 -> 5881 bytes .../TestFiles/groverUpsideDown.jpg | Bin 0 -> 5763 bytes .../Utils/EmailAddressParserTests.cs | 69 + ...gnTimeResolveAssemblyReferencesInput.cache | Bin 0 -> 6662 bytes ...enMailTests.csproj.CoreCompileInputs.cache | 1 + ...penMailTests.csprojAssemblyReference.cache | Bin 0 -> 22500 bytes .../DotNetOpenMailTests/obj/Debug/build.force | 0 ...gnTimeResolveAssemblyReferencesInput.cache | Bin 0 -> 6666 bytes ...enMailTests.csproj.CoreCompileInputs.cache | 1 + ...tOpenMailTests.csproj.FileListAbsolute.txt | 2 + ...penMailTests.csprojAssemblyReference.cache | Bin 0 -> 33615 bytes .../DotNetOpenMail_MSDN.ndoc | 39 + DotNetOpenMail-0.5.8b/LICENSE.txt | 25 + DotNetOpenMail-0.5.8b/README.txt | 24 + DotNetOpenMail-0.5.8b/README_NUNIT.txt | 17 + DotNetOpenMail-0.5.8b/UpgradeLog.htm | Bin 0 -> 96484 bytes DotNetOpenMail-0.5.8b/lib/log4net.dll | Bin 0 -> 266240 bytes DotNetOpenMail-0.5.8b/lib/nmock.dll | Bin 0 -> 40960 bytes DotNetOpenMail-0.5.8b/lib/nunit.framework.dll | Bin 0 -> 28672 bytes 186 files changed, 23323 insertions(+) create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail.sln create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/AbstractEmailAttachment.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/AssemblyInfo.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/DotNetOpenMail.csproj create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/DotNetOpenMail.csproj.user create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EhloSmtpResponse.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailAddress.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailAddressCollection.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailMessage.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/Base64Encoder.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/DoNothingEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EightBitEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EncoderFactory.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EncodingType.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/IEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/QPEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/SevenBitEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/FileAttachment.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/HtmlAttachment.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/IEmailStringable.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/ISendableMessage.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/ISmtpProxy.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Logging/LogMessage.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Logging/Logger.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MailException.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MessageHeader.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MessageHeaderCollection.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MimeBoundary.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MimeContainer.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/RFC2822Date.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/RawEmailMessage.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Resources/ARM.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Resources/DotNetOpenMail.resx create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/LoginAuthToken.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/SmtpAuthFactory.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpException.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpProxy.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpResponse.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpResponseCode.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpServer.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/TextAttachment.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/BinaryStreamUtil.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/Configuration.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/EmailAddressParser.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/VersionInfo.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/AssemblyInfo.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/DotNetOpenMailTests.csproj create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/DotNetOpenMailTests.csproj.user create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailAddressTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailMessageInAlternateEncodings.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailMessageTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/Base64EncoderTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/EightBitEncoderTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/QPEncoderTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/SevenBitEncoderTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/ExampleTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/FileAttachmentTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/FileAttachmentTests2.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Log4netLogger.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/QuickTest.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RFC2822DateTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RawEmailMessageTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Resources/ARMTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RussianTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/LocalAuthTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/MockedSlowProxy.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/MockedSmtpProxy.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpProxyTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpServerTests/SmtpServerTests.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestAddressHelper.cs create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestFiles/ImportedEmail.txt create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestFiles/grover.jpg create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestFiles/groverUpsideDown.jpg create mode 100644 DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Utils/EmailAddressParserTests.cs create mode 100644 DotNetOpenMail-0.5.8b/CHANGES.txt create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail.sln create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/AbstractEmailAttachment.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/AssemblyInfo.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.csproj create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.csproj.user create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.xml create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/EhloSmtpResponse.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailAddress.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailAddressCollection.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailMessage.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/Base64Encoder.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/DoNothingEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EightBitEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EncoderFactory.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EncodingType.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/IEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/QPEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/SevenBitEncoder.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/FileAttachment.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/GenericSmtpNegotiator.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/HtmlAttachment.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/IEmailStringable.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/ISendableMessage.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/ISmtpProxy.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Logging/LogMessage.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Logging/Logger.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/MailException.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/MessageHeader.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/MessageHeaderCollection.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/MimeBoundary.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/MimeContainer.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/RFC2822Date.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/RawEmailMessage.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Resources/ARM.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Resources/DotNetOpenMail.resx create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/LoginAuthToken.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthFactory.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthType.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpException.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpProxy.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpResponse.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpResponseCode.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpServer.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/TextAttachment.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/BinaryStreamUtil.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/Configuration.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/EmailAddressParser.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/VersionInfo.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DotNetOpenMail.csproj.CoreCompileInputs.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DotNetOpenMail.csprojAssemblyReference.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/DesignTimeResolveAssemblyReferences.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests.dll.config.demo create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests.dll.log4net create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/AssemblyInfo.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/DotNetOpenMailTests.csproj create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/DotNetOpenMailTests.csproj.user create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailAddressTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailMessageInAlternateEncodings.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailMessageTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/Base64EncoderTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/EightBitEncoderTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/QPEncoderTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/SevenBitEncoderTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/ExampleTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/FileAttachmentTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/FileAttachmentTests2.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Log4netLogger.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/QuickTest.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RFC2822DateTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RawEmailMessageTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Resources/ARMTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RussianTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/LocalAuthTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/MockedSlowProxy.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/MockedSmtpProxy.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpProxyTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpServerTests/SmtpServerTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestAddressHelper.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/ImportedEmail.txt create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/acrobattestpage.pdf create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/grover.jpg create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/groverUpsideDown.jpg create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Utils/EmailAddressParserTests.cs create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DotNetOpenMailTests.csproj.CoreCompileInputs.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DotNetOpenMailTests.csprojAssemblyReference.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/build.force create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csproj.CoreCompileInputs.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csproj.FileListAbsolute.txt create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csprojAssemblyReference.cache create mode 100644 DotNetOpenMail-0.5.8b/DotNetOpenMail_MSDN.ndoc create mode 100644 DotNetOpenMail-0.5.8b/LICENSE.txt create mode 100644 DotNetOpenMail-0.5.8b/README.txt create mode 100644 DotNetOpenMail-0.5.8b/README_NUNIT.txt create mode 100644 DotNetOpenMail-0.5.8b/UpgradeLog.htm create mode 100644 DotNetOpenMail-0.5.8b/lib/log4net.dll create mode 100644 DotNetOpenMail-0.5.8b/lib/nmock.dll create mode 100644 DotNetOpenMail-0.5.8b/lib/nunit.framework.dll diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail.sln b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail.sln new file mode 100644 index 00000000..f8585332 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail.sln @@ -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 diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/AbstractEmailAttachment.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/AbstractEmailAttachment.cs new file mode 100644 index 00000000..882c1a50 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/AbstractEmailAttachment.cs @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// 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 + /// + 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"; + + /// + /// The mail encoding type (e.g. quoted-printable, etc) + /// + protected EncodingType _encodingtype; + + /// + /// The "content type" of the attachment + /// + protected String _contenttype; + + /// + /// The content-transfer encoding of the attachment + /// + protected String _contenttransferencoding; + + /// + /// The content disposition of the attachment + /// + protected String _contentdisposition; + + /// + /// The content description of the attachment + /// + protected String _contentdescription; + + /// + /// The character set of the encoded text + /// + protected System.Text.Encoding _charset=null; + + /// + /// The unencoded contents, as a string (optional) + /// + protected String _contents=null; + + /// + /// An optional content id + /// + protected String _contentid=null; + + /// + /// The file name to identify the content. + /// (This can be different from the actual file name, + /// if there was one.) + /// + protected String _filename=null; + + /// + /// The file source to read from + /// + protected FileInfo _fileinfo=null; + + /// + /// The binary source of the file + /// + protected Byte[] _contentbytes=null; + + /// + /// Empty constructor + /// + public AbstractEmailAttachment() + { + } + + #region GetEncodedContents + /// + /// Get the contents, encoded for shipping via SMTP + /// + /// The encoder to encode the contents + /// returns the encoded string, ready for SMTP transfer + 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 + /// + /// Return the encoded contents, including mime + /// header. + /// + /// + 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 + /// + /// The encoding type for this attachment. + /// + public EncodingType Encoding + { + get {return _encodingtype;} + set {_encodingtype=value;} + } + #endregion + + #region ContentType + /// + /// The "content type" of the attachment + /// + public String ContentType + { + get {return _contenttype;} + set {_contenttype=value;} + } + #endregion + + #region CharSet + /// + /// The character set of the encoded text + /// + public System.Text.Encoding CharSet + { + get {return _charset;} + set {_charset=value;} + } + #endregion + + #region ContentId + /// + /// An optional content id that is used to refer to + /// the attachment from elsewhere within a multipart/related + /// email. + /// + public String ContentId + { + get {return _contentid;} + set {_contentid=value;} + } + #endregion + + #region FileName + /// + /// The file name to attach to the attachment. + /// + public String FileName + { + get {return _filename;} + set {_filename=value;} + } + #endregion + + #region Contents + /// + /// The unencoded contents, as a string (optional) + /// + public String Contents + { + get {return _contents;} + set {_contents=value;} + } + #endregion + + #region ContentBytes + /// + /// The raw bytes of the content (if this is the way + /// it was set.) + /// + public byte[] ContentBytes + { + get {return _contentbytes;} + set {_contentbytes=value;} + } + #endregion + + #region GetInternalMimeHeader + /// + /// Create the internal mime header, as found on the + /// mime-attachment itself. + /// + /// + /// + 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 + + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/AssemblyInfo.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/AssemblyInfo.cs new file mode 100644 index 00000000..2a1c3348 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/AssemblyInfo.cs @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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\. 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("")] diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/DotNetOpenMail.csproj b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/DotNetOpenMail.csproj new file mode 100644 index 00000000..ca166386 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/DotNetOpenMail.csproj @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/DotNetOpenMail.csproj.user b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/DotNetOpenMail.csproj.user new file mode 100644 index 00000000..b2a5c158 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/DotNetOpenMail.csproj.user @@ -0,0 +1,48 @@ + + + + + + + + + + + + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EhloSmtpResponse.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EhloSmtpResponse.cs new file mode 100644 index 00000000..bc5bc221 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EhloSmtpResponse.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; +using DotNetOpenMail.SmtpAuth; + +namespace DotNetOpenMail +{ + /// + /// The server response from EHLO + /// + public class EhloSmtpResponse + { + private int _responseCode=0; + private String _message; + + ArrayList smtpAuthTypes=new ArrayList(); + + /// + /// Create an instance of the EhloSmtpResponse class + /// + public EhloSmtpResponse() + { + } + + /// + /// Get the available Auth Types strings + /// as reported by the server. + /// (e.g. "login", etc.) + /// + /// + public String[] GetAvailableAuthTypes() + { + String[] stringArray=new String[smtpAuthTypes.Count]; + smtpAuthTypes.CopyTo(stringArray); + + return stringArray; + //return (SmtpAuthType[]) smtpAuthTypes.ToArray(typeof (SmtpAuthType[])); + } + + /// + /// Add an Auth type (by string as contained in the + /// EHLO authentication. These are converted to lower + /// case. + /// + /// The auth type from EHLO + public void AddAvailableAuthType(String authType) + { + smtpAuthTypes.Add(authType.Trim().ToLower()); + } + + /* + /// + /// Add an Auth type + /// + /// + public void AddAvailableAuthType(SmtpAuthType smtpAuthType) + { + smtpAuthTypes.Add(smtpAuthType); + } + */ + + /// + /// The SMTP Reponse code + /// + public int ResponseCode + { + get { return _responseCode; } + set { _responseCode=value; } + } + + /// + /// The SMTP Message. This will be "OK" if successful, + /// otherwise it will be the part that failed. + /// + public String Message + { + get { return _message; } + set { _message=value; } + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailAddress.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailAddress.cs new file mode 100644 index 00000000..1b26d381 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailAddress.cs @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// 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. + /// + 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 + /// + /// Create an instance of an email address object. + /// + /// The address portion of the email + /// The name portion of the email. + public EmailAddress(String email, String name) + { + if (email!=null) + { + email=email.Trim(); + } + this._email=email; + this._name=name; + } + #endregion + + #region EmailAddress + /// + /// Create an instance of an email address object. + /// + /// The address portion of the email + public EmailAddress(String email) + { + if (email!=null) + { + email=email.Trim(); + } + else + { + email=""; + } + this._email=email; + } + #endregion + + #region EmailAddress + /// + /// Create an character-encoded instance of an email address object. + /// + /// The address portion of the email + /// The name portion of the email. + /// The character set to encode the name portion of the email address. + /// The encoding type to use to encode the name portion of the mail address. + 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 + /// + /// The email address portion of the email address object + /// + public String Email + { + get {return _email;} + } + #endregion + + #region Name + /// + /// The name portion of the email address object + /// + 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 + /// + /// Create the string representation of this email address + /// (encoded or otherwise) as it will appear in the email + /// + /// + 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 + /// + /// Calls ToDataString. + /// + /// + public override String ToString() + { + return ToDataString(); + } + #endregion + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailAddressCollection.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailAddressCollection.cs new file mode 100644 index 00000000..f01f3d51 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailAddressCollection.cs @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A collection of EmailAddress objects. Implements + /// CollectionBase + /// + public class EmailAddressCollection : CollectionBase + { + /// + /// Create a new instance of the EmailAddressCollection + /// + public EmailAddressCollection() + { + } + + #region Add + /// + /// Add an object to the collection + /// + /// The EmailAddress object to add + /// + public int Add( EmailAddress emailaddress ) + { + return( List.Add( emailaddress ) ); + } + #endregion + + #region Add + /// + /// Append a collection of objects to the existing collection + /// + /// The EmailAddressCollection to append to the existing collection. + public void AddCollection( EmailAddressCollection emailaddresses ) + { + foreach (EmailAddress emailaddress in emailaddresses) + { + List.Add(emailaddress); + } + } + #endregion + + #region IndexOf + /// + /// Find the index of the EmailAddress in the collection + /// + /// The object to find. + /// The index, from 0, or -1 if not found. + public int IndexOf( EmailAddress value ) + { + return( List.IndexOf( value ) ); + } + #endregion + + #region Insert + /// + /// Insert an EmailAddress into the collection at the + /// specified index. + /// + /// The index, starting at zero. + /// The email address to add to the collection + public void Insert( int index, EmailAddress emailaddress ) + { + List.Insert( index, emailaddress ); + } + #endregion + + #region Remove + /// + /// Remove an address, if found, from the collection. + /// + /// The EmailAddress to remove + public void Remove( EmailAddress emailaddress ) + { + List.Remove( emailaddress ); + } + #endregion + + #region ToDataString + /// + /// Render the email addresses in a comma-separated list, + /// suitable for being rendered in an email. + /// + /// + 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 + /// + /// Calls ToDataString(). + /// + /// + public override String ToString() + { + return ToDataString(); + } + #endregion + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailMessage.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailMessage.cs new file mode 100644 index 00000000..58e476e1 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/EmailMessage.cs @@ -0,0 +1,675 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An Email Message + /// + 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 + /// + /// Create a new instance of an EmailMessage. + /// + public EmailMessage() + { + _mimeboundary=new MimeBoundary(); + _charset=System.Text.Encoding.GetEncoding(Configuration.GetInstance().GetDefaultEncoding("iso-8859-1")); + _bodytext=GetNoMimeMessage(); + } + #endregion + + #region Subject + /// + /// The subject line or subject header of the + /// email. + /// + public String Subject + { + get {return _subject;} + set {_subject=value;} + } + #endregion + + #region FromAddress + /// + /// 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. + /// + public EmailAddress FromAddress + { + get {return _fromaddress;} + set {_fromaddress=value;} + } + #endregion + + #region EnvelopeFromAddress + /// + /// Normally the FromAddress is used as the + /// envelope-from address, but it can be + /// overridden here, if it is not null. + /// + public EmailAddress EnvelopeFromAddress + { + get {return _envelopefromaddress;} + set {_envelopefromaddress=value;} + } + #endregion + + #region AddToAddress + /// + /// Add a To address to the Headers. This will also + /// be used during the "RCPT TO" SMTP negotiation + /// + /// Email Address object of the recipient + public void AddToAddress(EmailAddress emailaddress) + { + _toaddresses.Add(emailaddress); + } + /// + /// Add a To address to the Headers. This will also + /// be used during the "RCPT TO" SMTP negotiation + /// + /// The plain email address (don't include the name) + public void AddToAddress(String email) + { + _toaddresses.Add(new EmailAddress(email)); + } + #endregion + + #region ToAddresses + /// + /// Retrieve the collection of recipients + /// that will appear in the "To" header of the + /// email. + /// + public EmailAddressCollection ToAddresses + { + get {return _toaddresses;} + } + #endregion + + #region AddCcAddress + /// + /// Add a Cc address to the Headers. This will also + /// be used during the "RCPT TO" SMTP negotiation + /// + /// Email Address object of the recipient + public void AddCcAddress(EmailAddress emailaddress) + { + _ccaddresses.Add(emailaddress); + } + /// + /// Add a Cc address to the Headers. This will also + /// be used during the "RCPT TO" SMTP negotiation + /// + /// The plain email address (don't include the name) + public void AddCcAddress(String email) + { + _ccaddresses.Add(new EmailAddress(email)); + } + #endregion + + #region CcAddresses + /// + /// Retrieve the collection of recipients + /// that will appear in the "Cc" header of the + /// email. + /// + public EmailAddressCollection CcAddresses + { + get {return _ccaddresses;} + } + #endregion + + #region AddBccAddress + /// + /// 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. + /// + /// The EmailAddress object + public void AddBccAddress(EmailAddress emailaddress) + { + _bccaddresses.Add(emailaddress); + } + + /// + /// 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. + /// + /// The plain email address (don't include the name) + public void AddBccAddress(String email) + { + _bccaddresses.Add(new EmailAddress(email)); + } + #endregion + + #region BccAddresses + /// + /// Get the current EmailAddressCollection of BCC addresses + /// + public EmailAddressCollection BccAddresses + { + get {return _bccaddresses;} + } + #endregion + + #region Organization + /// + /// Get/set the organization (as it will appear in the organization + /// header + /// + public String Organization + { + get {return _organization;} + set {_organization=value;} + } + #endregion + + #region XMailer + /// + /// Get the current XMailer setting for the X-Mailer header. + /// + public String XMailer + { + get {return this._xmailer;} + set {this._xmailer=value;} + } + #endregion + + #region AddCustomHeader + /// + /// Add a custom mail header, e.g. "X-MyHeader". + /// + /// The header name (without a colon) + /// The value of the header. This value will not + /// be encoded. + public void AddCustomHeader(String header, String val) + { + _custommessageheaders.Add(new MessageHeader(header, val)); + } + #endregion + + #region HeaderCharSet + /// + /// The charset that is used for encoding the headers + /// + public System.Text.Encoding HeaderCharSet + { + get {return _charset;} + set {_charset=value;} + } + #endregion + + #region HeaderEncoding + /// + /// The mime encoding that is used for encoding the headers + /// + public Encoding.EncodingType HeaderEncoding + { + get {return this._encodingtype;} + set {_encodingtype=value;} + } + #endregion + + #region GetStandardHeaders + /// + /// Get the minimal header set in the specified character, + /// and using the mime encoder provided. + /// + 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 + /// + /// Encode a header value using the current header encoder and charset. + /// + /// The header name + /// The header value + /// + 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 + /// + /// Returns true if there is content that should be "multipart/mixed" + /// + /// true if the content is multipart/mixed. + private bool HasMixedContent() + { + return (_mixedfileattachments.Count > 0); + } + #endregion + + #region HasRelatedContent + /// + /// Returns true if there is content that should be "multipart/related" + /// + /// true if the content is multipart/related. + private bool HasRelatedContent() + { + return (_relatedfileattachments.Count > 0); + } + #endregion + + #region ToDataStringHeaders + /// + /// Encode the headers as they will appear in the email + /// + /// the charset encoding for the string + /// the mime encoding + /// the encoded string + 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 + /// + /// Encode the email body as it will appear in the email + /// + /// the encoded body + 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 + /// + /// format the body text---not implemented yet. + /// + /// + /// + private String FormatBodyText(String text) + { + return text; + } + #endregion + + #region GetNoMimeMessage + private String GetNoMimeMessage() + { + return ARM.GetInstance().GetString("this_is_mime"); + } + #endregion + + /// + /// 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. + /// + public String BodyText + { + get { return _bodytext;} + set { _bodytext=value;} + } + + #region ToDataString + /// + /// Render the encoded message for smtp "DATA" transmission. + /// This is the final version that will get sent to the + /// + /// + public String ToDataString() + { + IEncoder encoder=EncoderFactory.GetEncoder(HeaderEncoding); + return ToDataStringHeaders(this.HeaderCharSet, encoder)+SmtpProxy.ENDOFLINE+ToDataStringBody(); + + } + #endregion + + #region Send + /// + /// 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 + /// + /// The outgoing SMTP server. + /// true if sent successfully. (note that this + /// will not currently return false, but in the future + /// a false value may be used) + 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 + /// + /// Set the content type string in the mime header + /// + public String ContentType + { + get {return _contenttype;} + set {_contenttype=value;} + } + #endregion + + #region TextPart + /// + /// Set the plain text part of the email. This is optional + /// + public TextAttachment TextPart + { + set {_textpart=value;} + get {return _textpart;} + } + #endregion + + #region HtmlPart + /// + /// Set the html part of the email. This is optional + /// + public HtmlAttachment HtmlPart + { + set {_htmlpart=value;} + get {return _htmlpart;} + } + #endregion + + #region AddMixedAttachment + /// + /// Add an attachment which will appear to the user as + /// a separate file. (It is not referred to in the email itself.) + /// + /// The file attachment + public void AddMixedAttachment(FileAttachment fileattachment) + { + _mixedfileattachments.Add(fileattachment); + } + #endregion + + #region AddRelatedAttachment + /// + /// 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. + /// + /// The file attachment + public void AddRelatedAttachment(FileAttachment fileattachment) + { + _relatedfileattachments.Add(fileattachment); + } + #endregion + } +} + + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/Base64Encoder.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/Base64Encoder.cs new file mode 100644 index 00000000..21f87ca7 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/Base64Encoder.cs @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Encode a file in Base64 Encoding. + /// + /// See: http://www.freesoft.org/CIE/RFC/1521/7.htm + /// + public class Base64Encoder : IEncoder + { + /// + /// The maximum chars per line before end of line char(s) + /// + public static readonly int MAX_CHARS_PER_LINE=76; + + /// + /// The end-of-line character(s) to use + /// + public static readonly String END_OF_LINE="\r\n"; + + #region Base64Encoder + /// + /// Empty Constructor + /// + private Base64Encoder() + { + } + #endregion + + #region GetInstance + /// + /// Create an instance of this class + /// + public static Base64Encoder GetInstance() + { + return new Base64Encoder(); + } + #endregion + + #region Encode + /// + /// 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. + /// + /// Reader for incoming string + /// Writer for outgoing encoded string + /// The character encoding for the encoded string. + 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 + /// + /// Encode the File's data in base64. + /// + /// Reader for incoming string + /// Writer for outgoing encoded string + /// The character set for the encoded string + 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 + /// + /// Encode the File's data in base64. + /// + /// Reader for incoming string + /// Writer for outgoing encoded string + 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 + /// + /// Encode a string in Base64 in a particular characters set + /// + /// The source text + /// the charset for the encoded text + /// Returns an encoded string + 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 + /// + /// Encode header as per RFC 2047: + /// http://www.faqs.org/rfcs/rfc2047.html + /// + /// The header name + /// The header text to be encoded (data only) + /// The charset for the encoded string + /// ignored for this class + /// Returns the encoded string + 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 + /// + /// Chop the text into lines that are smaller + /// than MAX_CHARS_PER_LINE + /// + /// + /// + private String MakeLines(String source) + { + StringBuilder sb=new StringBuilder(); + int pos=0; + for (int i=0; i=Base64Encoder.MAX_CHARS_PER_LINE) + { + sb.Append(Base64Encoder.END_OF_LINE); + pos=0; + } + } + return sb.ToString(); + } + #endregion + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public String ContentTransferEncodingString + { + get {return "base64";} + } + #endregion + + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/DoNothingEncoder.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/DoNothingEncoder.cs new file mode 100644 index 00000000..4a623948 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/DoNothingEncoder.cs @@ -0,0 +1,96 @@ +using System; +using System.Text; +using System.IO; + +namespace DotNetOpenMail.Encoding +{ + /// + /// An encoder that does nothing. (This is essentially + /// what the 7bit and 8bit encodings are; they are just + /// markers, not actual encodings) + /// + public abstract class DoNothingEncoder : IEncoder + { + /// + /// Empty constructor + /// + public DoNothingEncoder() + { + } + + #region Encode + /// + /// Echo the text back unchanged. + /// + /// Reader for the incoming string + /// Writer for the outgoing string + /// The encodigng for the outgoing string (ignored) + 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 + /// + /// Echo the text back unchanged + /// + /// The incoming filestream + /// The outgoing filestream + /// Charset (ignored) + 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 + /// + /// Echo the text back unchanged (good for 7bit text only). + /// + /// The incoming binaryreader + /// The outgoing stream + public void Encode(BinaryReader binaryreader, StringWriter stringwriter) + { + throw new Exception("Binary reader doesn't do anything for this reader"); + //stringwriter.Write(binaryreader.ReadString()); + } + #endregion + + /// + /// Do nothing to the header string + /// + /// The header key + /// The header value + /// The charset to encode in (ignored) + /// (ignored) + /// + public String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding) + { + return val; + } + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public virtual String ContentTransferEncodingString + { + get {throw new ApplicationException("Implement this");} + } + #endregion + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EightBitEncoder.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EightBitEncoder.cs new file mode 100644 index 00000000..9c743a32 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EightBitEncoder.cs @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Denotes 8bit encoding. Note that this doesn't really + /// encode anything; it just specifies that this email is already + /// in 8-bit encoding. + /// + public class EightBitEncoder : DoNothingEncoder + { + #region EightBitEncoder + /// + /// Empty Constructor + /// + private EightBitEncoder() + { + } + #endregion + + #region GetInstance + /// + /// Create the EightBitEncoder object. + /// + public static EightBitEncoder GetInstance() + { + return new EightBitEncoder(); + } + #endregion + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public override String ContentTransferEncodingString + { + get {return "8bit";} + } + #endregion + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EncoderFactory.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EncoderFactory.cs new file mode 100644 index 00000000..aa684f36 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EncoderFactory.cs @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Factory for instantiating the right encoder class, + /// given an encoding + /// + internal class EncoderFactory + { + + /// + /// Empty Constructor. + /// + internal EncoderFactory() + { + } + + /// + /// Method for determining the correct encoder for this + /// encoding type. + /// + /// Enumerated encoding type + /// Returns the proper IEncoder implementation + /// Throws an ApplicationException if the specified encoding is unknown. + 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"); + } + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EncodingType.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EncodingType.cs new file mode 100644 index 00000000..c0c66718 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/EncodingType.cs @@ -0,0 +1,27 @@ +using System; + +namespace DotNetOpenMail.Encoding +{ + /// + /// Enumeration of encoding types. + /// + public enum EncodingType + { + /// + /// The Quoted-Printable encoding + /// + QuotedPrintable, + /// + /// The Base-65 encoding + /// + Base64, + /// + /// The 7Bit encoding marker + /// + SevenBit, + /// + /// The 8Bit encoding marker + /// + EightBit + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/IEncoder.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/IEncoder.cs new file mode 100644 index 00000000..2ef4ceba --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/IEncoder.cs @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An interface for a string encoder + /// + public interface IEncoder + { + + /// + /// Encode from the stringreader to the stringwriter. + /// + /// an open stringreader to the source string + /// where the output is written + /// the outgoing charset + void Encode(StringReader source, StringWriter destination, System.Text.Encoding charset); + + /// + /// Encode the file stream into the stringwriter. + /// + /// an open stream to file to be read + /// where the output is written + /// the outgoing charset + void Encode(FileStream filestream, StringWriter destination, System.Text.Encoding charset); + + /// + /// Encode the binary reader into the stringwriter. + /// + /// an open binary reader for the data to be encoded. + /// where the output is written + void Encode(BinaryReader binaryreader, StringWriter destination); + + + /// + /// Encode the string according to rfc-2047 if some of it + /// falls outside the 7bit ASCII charset. + /// + /// The header key + /// The header value string + /// Charset for the encoded string + /// Force encoding, even if in ascii-only. + /// The encoded string + String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding); + + /// + /// The String that goes in the content transfer encoding header + /// + String ContentTransferEncodingString {get;} + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/QPEncoder.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/QPEncoder.cs new file mode 100644 index 00000000..83dabc34 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/QPEncoder.cs @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// See: http://www.freesoft.org/CIE/RFC/1521/6.htm + /// + public class QPEncoder : IEncoder + { + /// + /// Logger + /// + //private static readonly ILog log = LogManager.GetLogger(typeof(QPEncoder)); + + /// + /// Maximum characters per line, before the end-of-line character + /// + public static readonly int MAX_CHARS_PER_LINE=76; + + /// + /// The end-of-line character(s). + /// + public static readonly String END_OF_LINE="\r\n"; + + + #region QPEncoder + /// + /// Empty Constructor + /// + private QPEncoder() + { + } + #endregion + + #region GetInstance + /// + /// Create an instance of the encoder + /// + /// The instantiated Quoted-printable encoder + public static QPEncoder GetInstance() + { + return new QPEncoder(); + } + #endregion + + #region Encode + /// + /// Encode the incoming stream in quoted-printable encoding. + /// + /// The incoming binary reader + /// The outgoing string writer + public void Encode(BinaryReader binaryreader, StringWriter stringwriter) + { + throw new ApplicationException("Not Implemented Yet; use a base64 encoder instead."); + } + #endregion + + #region Encode + /// + /// Encode the incoming stream in quoted-printable encoding. + /// + /// The incoming file stream + /// The outgoing string writer + /// The charset to write the outgoing string in + 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 + /// + /// 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 + /// + /// The incoming string reader + /// The outgoing stringwriter + /// The outgoing charset for the string + public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding charset) + { + Encode(stringreader, stringwriter, charset, false, 0); + } + #endregion + + #region EncodeString + /// + /// Encode the string in quoted printable format + /// + /// The source string + /// The outgoing charset + /// the encoded string + public String EncodeString(String str, System.Text.Encoding charset) + { + return EncodeString(str, charset, false, 0); + } + #endregion + + #region EncodeString + /// + /// Encode the string in quoted printable format + /// + /// The source string + /// The outgoing charset + /// Force encoding, even if not required by qp RFC + /// The total characters outside the encoding. This is used to figure + /// out how long the line will be after encoding. + /// the encoded string + 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 + /// + /// Encode header as per RFC 2047: + /// http://www.faqs.org/rfcs/rfc2047.html + /// + /// + /// This doesn't split long lines yet + /// the header name + /// the string to encode + /// The charset to encode to + /// Force encoding, even if not required by qp RFC + /// the encoded string, suitable for use in a header + 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 + /// + /// Encode a char according to quoted-printable + /// standard + /// + /// the char to encode + /// the encoded char representation + 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 + /// + /// Encode a byte according to quoted-printable + /// standard + /// + /// the byte to encode + /// the encoded byte representation + private String EncodeByte(byte ch) + { + return String.Format("={0:X2}",(int) ch); + } + #endregion + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public String ContentTransferEncodingString + { + get {return "quoted-printable";} + } + #endregion + + #region NeedsEncoding + /// + /// Return true if the char needs to be encoded. + /// + /// + /// + /// + 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 + /// + /// Return true if the byte needs to be encoded. + /// + /// + /// + /// + 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 + /// + /// Return true if the string needs to be encoded. + /// + /// The string to check + /// true if outside 127-bit, or one of the + /// quoted-printable special characters. + internal bool IsNonAscii(String str) + { + for (int i=0; i + /// Check if the character is one of the non-qp + /// characters + /// + /// the character to check + /// true if outside the acceptable qp range + 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 + /// + /// 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. + /// + /// The incoming string reader + /// The outgoing stringwriter + /// The outgoing charset for the string + /// If true, force the encoding of all the + /// These are the number of characters that + /// will appear outside this string, e.g. the header name, etc. + /// characters (not just those that are given in RFC2027). + 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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/SevenBitEncoder.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/SevenBitEncoder.cs new file mode 100644 index 00000000..f83254d0 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Encoding/SevenBitEncoder.cs @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Denotes 7bit encoding. Note that this doesn't really + /// encode anything; it just specifies that this email is already + /// in 7-bit ascii encoding. + /// + public class SevenBitEncoder : DoNothingEncoder + { + /// + /// Empty constructor + /// + private SevenBitEncoder() + { + } + + /// + /// Create an instance of this class. + /// + /// + public static SevenBitEncoder GetInstance() + { + return new SevenBitEncoder(); + } + + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public override String ContentTransferEncodingString + { + get {return "7bit";} + } + #endregion + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/FileAttachment.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/FileAttachment.cs new file mode 100644 index 00000000..983dda03 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/FileAttachment.cs @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A mime representation of a file which can be transferred + /// via email. + /// + public class FileAttachment : AbstractEmailAttachment + { + + //private static readonly ILog log = LogManager.GetLogger(typeof(FileAttachment)); + + /// + /// Create a new File attachment from a FileInfo object + /// + /// A fileinfo object which points to a local file. + public FileAttachment(FileInfo fileinfo) : this(fileinfo, null) + { + } + + /// + /// Create a new text file attachment from a StreamReader. + /// + /// An open streamreader + public FileAttachment(StreamReader streamreader) : this(streamreader, null) + { + } + + /// + /// Create a new binary file attachment from a BinaryReader. + /// + /// An open binaryreader + public FileAttachment(BinaryReader binaryreader) : this(binaryreader, null) + { + } + + /// + /// Create a new binary file attachment from an array of bytes. + /// + /// An array of bytes + public FileAttachment(byte[] bytes) : this(bytes, null) + { + } + + /// + /// Create a new file attachment from a String. + /// + /// The contents of the file + public FileAttachment(String content) : this(content, null) + { + } + + #region FileAttachment + /// + /// 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. + /// + /// A fileinfo object which points to a local file. + /// the content id value + 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 + /// + /// 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. + /// + /// An open streamreader + /// the content id value + 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 + /// + /// 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. + /// + /// An open binary readerr + /// the content id value + 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 + /// + /// 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. + /// + /// An array of bytes + /// the content id value + 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 + + /// + /// 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. + /// + /// The contents of the file + /// the content id value + 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; + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/HtmlAttachment.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/HtmlAttachment.cs new file mode 100644 index 00000000..440b789c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/HtmlAttachment.cs @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An HTML email attachment + /// + public class HtmlAttachment : AbstractEmailAttachment + { + + /// + /// 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. + /// + /// The HTML content of the attachment + 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; + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/IEmailStringable.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/IEmailStringable.cs new file mode 100644 index 00000000..1e84605d --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/IEmailStringable.cs @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Objects of a class which implements this interface + /// can be converted to a string which can be used in + /// an email. + /// + internal interface IEmailStringable + { + String ToDataString(); + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/ISendableMessage.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/ISendableMessage.cs new file mode 100644 index 00000000..be852484 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/ISendableMessage.cs @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A message which can be sent. + /// + internal interface ISendableMessage : IEmailStringable + { + bool Send(SmtpServer smtpserver); + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/ISmtpProxy.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/ISmtpProxy.cs new file mode 100644 index 00000000..8d5b7595 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/ISmtpProxy.cs @@ -0,0 +1,95 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; + +//using log4net; + +namespace DotNetOpenMail +{ + /// + /// Interact directly with the SMTP server. + /// + public interface ISmtpProxy + { + /// + /// Open the connection + /// + /// The SMTP response + SmtpResponse Open(); + + /// + /// Send the HELO command + /// + /// + /// + SmtpResponse Helo(String localHostName); + + /// + /// Send the EHLO command + /// + /// + /// + EhloSmtpResponse Ehlo(String localHostName); + + /// + /// Send the MAIL FROM command + /// + /// + /// + SmtpResponse MailFrom(EmailAddress mailfrom); + + /// + /// Send one RCPT TO command + /// + /// + /// + SmtpResponse RcptTo(EmailAddress rcptto); + + /// + /// Send the DATA command + /// + /// + SmtpResponse Data(); + + /// + /// Write the message content + /// + /// + SmtpResponse WriteData(String str); + + /// + /// Send the QUIT message to the server + /// + /// + SmtpResponse Quit(); + + /// + /// Close the connection + /// + /// The SMTP response + void Close(); + + /// + /// Send the AUTH command + /// + /// the SMTP response + SmtpResponse Auth(String authtype); + + /// + /// Send any old string to the proxy + /// + /// the SMTP response + SmtpResponse SendString(String str); + + /// + /// Turn the SMTP Conversation Capture off/on. + /// If on, GetSmtpConversation will contain the + /// most recent conversation. + /// + /// the on/off value + bool CaptureSmtpConversation {get; set;} + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Logging/LogMessage.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Logging/LogMessage.cs new file mode 100644 index 00000000..b1a41ac2 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Logging/LogMessage.cs @@ -0,0 +1,44 @@ +using System; + +namespace DotNetOpenMail.Logging +{ + /// + /// Summary description for LogMessage. + /// + public class LogMessage + { + private Object _sender=null; + private String _message=null; + + /// + /// The log message + /// + public String Message + { + get {return _message;} + set {_message=value;} + } + + /// + /// The sender object + /// + public Object Sender + { + get {return _sender;} + set {_sender=value;} + } + + + /// + /// Log a message + /// + /// The object logging the message + /// The message to be logged + public LogMessage(Object sender, String message) + { + this._sender=sender; + this._message=message; + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Logging/Logger.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Logging/Logger.cs new file mode 100644 index 00000000..04ca0113 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Logging/Logger.cs @@ -0,0 +1,77 @@ +using System; + +namespace DotNetOpenMail.Logging +{ + /// + /// Summary description for Logger. + /// + public class Logger + { + /// + /// Log handler delegate + /// + public delegate void LogHandler(LogMessage logMessage); + + /// + /// Log event + /// + //public event LogHandler LogEvent; + + private static Logger _logger=new Logger(); + + private Logger() + { + } + + /// + /// Return the singleton object + /// + /// + public static Logger GetInstance() + { + return _logger; + } + + /// + /// Log a message with level "Info" + /// + /// + public void LogInfo(String message) + { + + } + + /// + /// Log a message with level "Debug" + /// + public void LogDebug(String message) + { + + } + + /// + /// Log a message with level "Error" + /// + public void LogError(String message) + { + + } + + /// + /// Log the output of sending smtp + /// + public void LogWriteSMTP(String message) + { + } + + /// + /// Log the reply via smtp + /// + /// + public void LogReceiveSMTP(String message) + { + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MailException.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MailException.cs new file mode 100644 index 00000000..e29dfed4 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MailException.cs @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// General Mail Exception, including network errors, + /// connection errors, and configuration errors. + /// + public class MailException : Exception + { + /// + /// Create an instance of a MailException + /// + public MailException() : base() + { + } + /// + /// Create an instance of a MailException + /// + /// The message describing the exception + public MailException(string message) : base(message) + { + } + + /// + /// Create an instance of a MailException + /// + /// The message describing the exception + /// The inner exception + public MailException(string message, Exception inner) : base(message, inner) + { + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MessageHeader.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MessageHeader.cs new file mode 100644 index 00000000..861bc1e2 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MessageHeader.cs @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// This represents one of the message headers as it + /// appears in the email. + /// + public class MessageHeader : IEmailStringable + { + private String _name; + private String _value; + private String _encodedvalue=null; + + /// + /// Create a new instance of a MessageHeader + /// + /// The header name (without a colon) + /// The unencoded value + public MessageHeader(string name, String value) + { + this._name=name; + this._value=value; + } + + /// + /// Create a new instance of a MessageHeader, with a mime-encoded + /// value. + /// + /// The header name (without a colon) + /// The non-encoded header value + /// The mime-encoded value + public MessageHeader(string name, String value, String encodedvalue) + { + this._name=name; + this._value=value; + this._encodedvalue=encodedvalue; + } + + /// + /// The name of the header. + /// + public String Name + { + get {return this._name;} + } + + /// + /// The unencoded value of the header + /// + public String Value + { + get {return this._value;} + } + + /// + /// The mime-encoded value of the header + /// + public String EncodedValue + { + get {return this._encodedvalue;} + } + + /// + /// The string representation of the header, as it will + /// appear in the email. + /// + /// + public String ToDataString() + { + if (_encodedvalue!=null) + { + return Name+": "+EncodedValue+SmtpProxy.ENDOFLINE; + } + else + { + return Name+": "+Value+SmtpProxy.ENDOFLINE; + } + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MessageHeaderCollection.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MessageHeaderCollection.cs new file mode 100644 index 00000000..23284074 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MessageHeaderCollection.cs @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A collection of MessageHeader objects + /// Implements the CollectionBase interface. + /// + public class MessageHeaderCollection : CollectionBase, IEmailStringable + { + /// + /// Initializes a new instance of the ArrayList class. + /// + public MessageHeaderCollection() + { + } + + #region Add + /// + /// Adds an object to the end of the MessageHeaderCollection + /// + /// The Object to be added to the end of the MessageHeaderCollection. + /// The value can be a null reference (Nothing in Visual Basic). + /// The MessageHeaderCollection index at which the value has been added. + public int Add( MessageHeader MessageHeader ) + { + return( List.Add( MessageHeader ) ); + } + #endregion + + #region IndexOf + /// + /// Returns the zero-based index of the first occurrence of a + /// value in the MessageHeaderCollection or in a portion of it. + /// + /// The Object to locate in the MessageHeaderCollection. The value + /// can be a null reference (Nothing in Visual Basic). + /// + public int IndexOf( MessageHeader value ) + { + return( List.IndexOf( value ) ); + } + #endregion + + #region Insert + /// + /// Inserts an element into the MessageHeaderCollection at + /// the specified index. + /// + /// The zero-based index at which value should be inserted + /// The MessageHeader to insert. + /// The value can be a null reference (Nothing in Visual Basic). + public void Insert( int index, MessageHeader MessageHeader ) + { + List.Insert( index, MessageHeader ); + } + #endregion + + #region Remove + /// + /// Removes the first occurrence of a + /// specific MessageHeader from the MessageHeaderCollection. + /// + /// The object to remove from the MessageHeaderCollection + public void Remove( MessageHeader MessageHeader ) + { + List.Remove( MessageHeader ); + } + #endregion + + #region ToDataString + /// + /// Write the MessageHeaderCollection to a string that can be + /// included in an email. + /// + /// The String as it will appear in the resulting email. + public String ToDataString() + { + StringBuilder sb=new StringBuilder(""); + foreach (MessageHeader messageheader in List) + { + sb.Append(messageheader.ToDataString()); + } + return sb.ToString(); + } + #endregion + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MimeBoundary.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MimeBoundary.cs new file mode 100644 index 00000000..a3438839 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/MimeBoundary.cs @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A boundary which delimits a MIME object. + /// + 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 + * + * 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 +{ + /// + /// A MIME container for content or other mime containers. + /// + 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(); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/RFC2822Date.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/RFC2822Date.cs new file mode 100644 index 00000000..6e4d403d --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/RFC2822Date.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Create a RFC 2822-compliant date. + /// + /// See section 3.3 in + /// http://ftp.rfc-editor.org/in-notes/rfc2822.txt + /// + public class RFC2822Date + { + private DateTime _datetime; + private TimeZone _timezone; + + /// + /// Create an instance of the RFC 2822 date object. + /// + /// The date to convert + /// The timezone to use in the conversion + public RFC2822Date(DateTime datetime, TimeZone timezone) + { + this._datetime=datetime; + this._timezone=timezone; + } + + /// + /// Generate the date string + /// + /// A RFC-2822 error code + 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); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/RawEmailMessage.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/RawEmailMessage.cs new file mode 100644 index 00000000..52de51a1 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/RawEmailMessage.cs @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A full, preformatted email message, including headers + /// + public class RawEmailMessage : ISendableMessage + { + private String _content=null; + private EmailAddressCollection _rcpttoaddresses=new EmailAddressCollection(); + private EmailAddress _mailfrom=null; + + /// + /// Create an instance of the RawEmailMessage + /// + public RawEmailMessage() + { + } + + #region Content + /// + /// The raw content of the email + /// + public String Content + { + get { return _content; } + set { _content = value; } + } + #endregion + + #region MailFrom + /// + /// The address to use in the envelope-from + /// SMTP negotiation + /// + public EmailAddress MailFrom + { + get { return _mailfrom; } + set { _mailfrom = value; } + } + #endregion + + #region RcptToAddresses + /// + /// The recipient addresses + /// + public EmailAddressCollection RcptToAddresses + { + get { return _rcpttoaddresses; } + } + #endregion + + #region AddRcptToAddress + /// + /// Add a recipient to the EmailAddressCollection + /// of recipients + /// + /// + public void AddRcptToAddress(EmailAddress emailaddress) + { + _rcpttoaddresses.Add(emailaddress); + } + #endregion + + #region Send + /// + /// Send the email via the specified SMTP server + /// + /// The SMTP server to use + /// true if the email was sent + 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 + /// + /// Render the message for smtp "DATA" transmission. + /// + /// The rendered String, which in this + /// case is the content itself, untouched. + public String ToDataString() + { + return _content; + } + #endregion + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Resources/ARM.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Resources/ARM.cs new file mode 100644 index 00000000..73f8c323 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Resources/ARM.cs @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// ARM= Assembly Resource Manager. Manage the strings for the + /// various CultureInfo types. + /// + public sealed class ARM + { + /// + /// The singleton object + /// + private static ARM _theinstance=new ARM(); + /// + /// The namespace of the resource files + /// + private string _pathname="DotNetOpenMail.Resources.DotNetOpenMail"; + /// + /// The singleton System.Resources.ResourceManager. + /// + private ResourceManager _resources=null; + + /// + /// Create the singleton + /// + private ARM() + { + _resources=new ResourceManager(_pathname, typeof(ARM).Assembly); + } + + /// + /// Get the instance of the class + /// + /// the ARM instance + public static ARM GetInstance() + { + return _theinstance; + } + + /// + /// Get an object from the file + /// + /// The key + /// The key lookup for the default culture + public object GetObject(string name) + { + return GetObject(null, name); + } + + /// + /// Get an object for the specified CultureInfo + /// + /// The specified culture for the resource + /// The key for the resource + /// returns an object, if one is found, else null + public object GetObject(CultureInfo culture, string name) + { + if (_resources != null) + { + return _resources.GetObject(name, culture); + } + return null; + } + + /// + /// Get a string for the specified CultureInfo for the + /// default culture + /// + /// The key for the resource + /// returns a string, if one is found, else null + public string GetString(string name) + { + return GetString(null, name, null); + } + + /// + /// Get a string for the specified CultureInfo for the + /// default culture. If not found, return defaultvalue + /// + /// The key for the resource + /// The value to return if there + /// is no value found. + /// returns a string, if one is found, else defaultvalue + public string GetString(string name, string defaultvalue) + { + return GetString(null, name, defaultvalue); + } + + /// + /// Get a string for the specified CultureInfo for the + /// current culture. If not found, return null + /// + /// The culture of the resulting string + /// The key for the resource + /// returns a string, if one is found, else + /// null + public string GetString(CultureInfo culture, string name) + { + return GetString(culture, name, null); + } + + /// + /// Get a string for the specified CultureInfo for the + /// default culture. If not found, return defaultvalue + /// + /// The culture of the resulting string + /// The key for the resource + /// The value to return if there + /// is no value found. + /// returns a string, if one is found, else defaultvalue + 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"); + } + + /// + /// Retrieve the entire resource set for this culture. + /// + /// The culture to examine + /// The resource set, if any. + public ResourceSet GetResourceSet(CultureInfo culture) + { + return _resources.GetResourceSet(culture, false, false); + } + + } +} + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Resources/DotNetOpenMail.resx b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Resources/DotNetOpenMail.resx new file mode 100644 index 00000000..a07c4de5 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Resources/DotNetOpenMail.resx @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.0.0.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + (no subject) + + + This is a multi-part message in MIME format + + + Unrecognized authentication type + + + Please include a MAIL FROM address. + + \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs new file mode 100644 index 00000000..f2199419 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 description for ISmtpAuthenticationToken. + /// + public interface ISmtpAuthToken + { + + /// + /// The user's login + /// + String UserName + { + get; set; + } + + /// + /// The user's password + /// + String Password + { + get; set; + } + + /// + /// Negotiate AUTH with the SmtpProxy. + /// + /// + SmtpResponse Negotiate(ISmtpProxy smtpProxy, String[] supportedAuthTypes); + + } + +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/LoginAuthToken.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/LoginAuthToken.cs new file mode 100644 index 00000000..aec23d38 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/LoginAuthToken.cs @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A LOCAL SMTP AUTH token + /// + 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"); + + /// + /// Create a new instance of the LOCAL SMTP + /// AUTH token + /// + public LoginAuthToken(String userName, String password) + { + this._userName=userName; + this._password=password; + } + + /// + /// The User's password + /// + public String Password + { + get {return _password;} + set {_password=value;} + } + + /// + /// The User's login + /// + public String UserName + { + get {return _userName;} + set {_userName=value;} + } + + /* + /// + /// Return true if this is among the supported AUTH + /// types. + /// + /// + /// + public bool IsSupported(SmtpAuthType[] authtypes) + { + log.Debug("CHECKING SUPPORTED TYPES"); + for (int i=0; i + /// the supported auth types + /// + 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; + } + + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/SmtpAuthFactory.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/SmtpAuthFactory.cs new file mode 100644 index 00000000..c945650a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/SmtpAuthFactory.cs @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 description for SmtpAuthHelper. + /// + internal class SmtpAuthFactory + { + //private static readonly ILog log = LogManager.GetLogger(typeof(SmtpAuthFactory)); + + internal SmtpAuthFactory() + { + } + + /// + /// Get the Auth type from the SMTP EHLO response. + /// If it is unrecognized or unimplemented, + /// return null. Case doesn't matter. + /// + /// The string as returned in EHLO negotiation. + /// The user's login + /// The User's password + 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; + } + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs new file mode 100644 index 00000000..d4b80468 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Token which will negotiate an authentication type + /// with the server. + /// + 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"); + + /// + /// Create a new instance of the LOCAL SMTP + /// AUTH token + /// + public SmtpAuthToken(String userName, String password) + { + this._userName=userName; + this._password=password; + } + + /// + /// The User's password + /// + public String Password + { + get {return _password;} + set {_password=value;} + } + + /// + /// The User's login + /// + public String UserName + { + get {return _userName;} + set {_userName=value;} + } + + /// + /// Return the 235 response code if valid, otherwise + /// return the error. + /// + /// The SmtpProxy being used + /// String array of EHLO-specified auth types + /// + 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); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpException.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpException.cs new file mode 100644 index 00000000..c36d3d98 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpException.cs @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An SmtpException represents an SMTP response + /// code and an error message. Network and connection + /// errors are represented by a MailException instead. + /// + public class SmtpException : Exception + { + private int _errorcode; + + /// + /// Create a new instance of the SmtpException + /// + /// The SMTP error code + public SmtpException(int errorcode) + { + this._errorcode=errorcode; + } + + /// + /// Create a new instance of the SmtpException + /// + /// The SMTP error code + /// The SMTP error message + public SmtpException(int errorcode, string message) : base(message) + { + this._errorcode=errorcode; + } + + /// + /// Create a new instance of the SmtpException + /// + /// The SMTP error code + /// The SMTP error message + /// The inner exception + public SmtpException(int errorcode, string message, Exception inner) : base(message, inner) + { + this._errorcode=errorcode; + } + + /// + /// The SMTP error code. + /// + public int ErrorCode + { + get {return _errorcode;} + set {_errorcode=value;} + } + + /// + /// Convert to a string + /// + /// + public override string ToString() + { + return _errorcode+" "+this.Message; + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpProxy.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpProxy.cs new file mode 100644 index 00000000..eacaa439 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpProxy.cs @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A proxy to access an SMTP server. This drives + /// the protocol interaction. + /// + 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 + /// + /// Get an instance of the SMTP Proxy + /// + /// + /// + public static SmtpProxy GetInstance(SmtpServer smtpserver) + { + return new SmtpProxy(smtpserver); + } + #endregion + + #region Open + /// + /// Connect to the server and return the initial + /// welcome string. Throw a MailException if we + /// can't connect. + /// + /// + 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 + /// + /// Send the HELO string. + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Send the EHLO string. + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Send the MAIL FROM command + /// Throw a MailException if we can't connect. + /// + /// The Envelope-From address + /// the SMTP response + 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 + /// + /// Send the MAIL FROM command + /// Throw a MailException if we can't connect. + /// + /// A recipient's address + /// the SMTP response + 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 + /// + /// Send the DATA string (without the data) + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Send the message content string + /// Throw a MailException if we can't + /// connect. + /// + /// the SMTP response + 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 + /// + /// Parse the response from the EHLO into an + /// EhloSmtpResponse. Returns 250 "OK" if successful. + /// + /// + 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 + /// + /// Send the AUTH command + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + public SmtpResponse Auth(String authtype) + { + if (!_isConnected) + { + throw new MailException("The connection is closed."); + } + Write("AUTH "+authtype+SmtpProxy.ENDOFLINE); + return ReadSmtpResponse(); + } + #endregion + + #region SendString + /// + /// Send any old string to the proxy + /// + /// the SMTP response + public SmtpResponse SendString(String str) + { + if (!_isConnected) + { + throw new MailException("The connection is closed."); + } + Write(str+SmtpProxy.ENDOFLINE); + return ReadSmtpResponse(); + } + #endregion + + #region Write + /// + /// Write a string to the current connection. + /// + /// + 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 + /// + /// Send the QUIT command + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Set this to "true" if you want to capture the SMTP negotiation. + /// Once the conversation has finished, use "GetConversation" to + /// view it. + /// + 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 + */ + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpResponse.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpResponse.cs new file mode 100644 index 00000000..4f02ce3b --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpResponse.cs @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// The response from the SMTP server + /// + public class SmtpResponse + { + private int _responseCode; + private String _message; + + /// + /// Create an instance of the SmtpResponse + /// + /// + /// + public SmtpResponse(int responseCode, String message) + { + this._responseCode=responseCode; + this._message=message; + } + + /// + /// The SMTP Reponse code + /// + public int ResponseCode + { + get { return _responseCode; } + } + + /// + /// The SMTP Response String + /// + + public String Message + { + get { return _message; } + } + + /// + /// Was the response a fatal error? + /// + public bool IsFatalError + { + get { + return (this._responseCode>=500 && this._responseCode <= 599); + } + } + + /// + /// Was the response an OK message? + /// + public bool IsOk + { + get + { + return (this._responseCode>=200 && this._responseCode <= 299); + } + } + + /// + /// Convert this response to an exception + /// + /// The SmtpException corresponding to this response + public SmtpException GetException() + { + return new SmtpException(this._responseCode, this._message); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpResponseCode.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpResponseCode.cs new file mode 100644 index 00000000..1952e51a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpResponseCode.cs @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// SMTP server response codes and their meanings. + /// + public enum SmtpResponseCode: int + { + /// + /// System status, or system help reply. + /// + SystemStatus = 211, + /// + /// Help message. + /// + Help = 214, + /// + /// Domain service ready. Ready to start TLS. + /// + HeloReply = 220, + /// + /// Domain service closing transmission channel. + /// + Quit = 221, + /// + /// Authentication successfully completed. + /// + AuthSuccessful = 235, + /// + /// OK, queuing for node node started. Requested mail action completed. + /// + Ok = 250, + /// + /// OK, no messages waiting for node node. User not local, will forward to forwardpath. + /// + OkWillForward = 251, + /// + /// 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. + /// + OkWithoutVerify = 252, + /// + /// OK, messages pending messages for node node started. + /// + OkMsgStarted = 253, + /// + /// Start mail input, end with CRLF.CRLF + /// + StartMailInput = 354, + /// + /// Octet-offset is the transaction offset. + /// + TransactionOffset = 355, + /// + /// Domain service not available, closing transmission channel. + /// + ServiceNotAvailable = 421, + /// + /// A password transition is needed. + /// + PasswordNeeded = 432, + /// + /// Requested mail action not taken: mailbox unavailable. + /// + MailboxBusy = 450, + /// + /// Requested action aborted: local error in processing. Unable to process ATRN request now. + /// + ErrorProcessing = 451, + /// + /// Requested action not taken: insufficient system storage. + /// + InsufficientStorage = 452, + /// + /// You have no mail. + /// + NoMail = 453, + /// + /// TLS not available. Encryption required for requested authentication mechanism. + /// + TlsNotAvailable = 454, + /// + /// Unable to queue messages for node node. + /// + NoMsgQueue = 458, + /// + /// Node node not allowed: reason. + /// + NodeNotAllowed = 459, + /// + /// Command not recognized: command. Syntax error. + /// + UnknownCmd = 500, + /// + /// Syntax error, no parameters allowed. + /// + SyntaxError = 501, + /// + /// Command not implemented. + /// + CmdNotImplemented = 502, + /// + /// Bad sequence of commands. + /// + BadSequence = 503, + /// + /// Command parameter not implemented. + /// + ParamNotImplemented = 504, + /// + /// Security error. + /// + SecurityError = 505, + /// + /// Machine does not accept mail. + /// + MailNotAccepted = 521, + /// + /// Must issue a STARTTLS command first. Encryption required for requested authentication mechanism. + /// + StartTLSneeded = 530, + /// + /// Authentication mechanism is too weak. + /// + AuthTooWeak = 534, + /// + /// Encryption required for requested authentication mechanism. + /// + EncryptionRequired = 538, + /// + /// Requested action not taken: mailbox unavailable. + /// + ActionNotTaken = 550, + /// + /// User not local, please try forward path. + /// + NotLocalPleaseForward = 551, + /// + /// Requested mail action aborted: exceeded storage allocation. + /// + ExceedStorageAllowance = 552, + /// + /// Requested action not taken: mailbox name not allowed. + /// + MailboxNameNotAllowed = 553, + /// + /// Transaction failed. + /// + TransactionFailed = 554 + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpServer.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpServer.cs new file mode 100644 index 00000000..ae449cd0 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/SmtpServer.cs @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A description of an SMTP server. + /// + public class SmtpServer + { + //public delegate void SmtpDataMessagePresendHandler(object sender, MyEventArgs e); + + /// + /// Logging delegate + /// + public delegate void LogHandler(LogMessage logMessage); + + /// + /// Handle a message about to be sent + /// + public event LogHandler LogSmtpWrite; + + /// + /// Handle a message received + /// + public event LogHandler LogSmtpReceive; + + /// + /// Log that the conversation has completed + /// + 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 + /// + /// Create a new SMTP server at this hostname and + /// port. + /// + /// The address or hostname of the smtp server + /// The port of the smtp server. + public SmtpServer(String hostname, int port) + { + _id=hostname+":"+port; + _hostname=hostname; + _port=port; + } + #endregion + + #region SmtpServer + /// + /// Create a new SMTP server at this hostname and + /// port. + /// + /// The address or hostname of the smtp server + public SmtpServer(String hostname) + { + _id=hostname+":"+_port; + _hostname=hostname; + } + #endregion + + #region SmtpServer + /// + /// Create a new SMTP server at this hostname and + /// port. + /// + /// The ip address of the SMTP server + /// The port number of SMTP server + public SmtpServer(IPAddress ipaddress, int port) + { + _id=ipaddress.ToString()+":"+port; + _ipaddress=ipaddress; + _port=port; + } + #endregion + + #region GetIPEndPoint + /// + /// Get the end point for the SMTP server. The IPEndpoint will + /// be saved for later to prevent multiple hostname lookups. + /// + /// SmtpException is thrown if the host doesn't resolve. + /// returns an IPEndPoint for the SMTPServer. + 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 + /// + /// The timeout waiting for an SMTP command, in + /// milliseconds + /// + public int ServerTimeout + { + get {return _serverTimeout;} + set {_serverTimeout=value;} + } + #endregion + + #region GetSmtpProxy + /// + /// Get an instance of an SmtpProxy + /// + /// + 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 + /// + /// Figure out whether we need EHLO or not. + /// Currently, this is only for SMTP AUTH + /// + /// + private bool UseEhlo() + { + if (this._authToken!=null) + { + return true; + } + else + { + return false; + } + } + #endregion + + #region Send + /// + /// Send the email. + /// + /// The completed message + /// A list of email addresses which + /// are to be used in the RCPT TO SMTP communication + /// An email address for the MAIL FROM + /// part of the SMTP protocol. + /// throws an SmtpException if there + /// is an unexpected SMTP error number sent from the server. + /// throws a MailException if there + /// is a network problem, connection problem, or other issue. + /// + 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 + /// + /// Override the SmtpProxy. This is only + /// for testing smtp negotiation without an + /// smtp server. + /// + /// + public void OverrideSmtpProxy(ISmtpProxy smtpProxy) + { + _smtpProxy=smtpProxy; + } + #endregion + + #region SmtpAuthToken + /// + /// Get or set the SMTP AUTH token for the server. + /// + public ISmtpAuthToken SmtpAuthToken + { + get {return _authToken;} + set {_authToken = value;} + } + #endregion + + #region CaptureSmtpConversation + /// + /// 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. + /// + [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 + /// + /// Append this string to the conversation log. + /// + /// the string from the SMTP conversation + internal void AppendConversation(String str) + { + this._smtpConversation.Append(str); + } + #endregion + + #region GetSmtpConversation + /// + /// If CaptureSmtpConversation is true, a Send() will + /// be captured, and will be accessible here. + /// + /// The SMTP Conversation or null. + [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 + /// + /// The server hostname + /// + public String Hostname + { + get {return _hostname;} + } + #endregion + + #region Port + /// + /// The server port + /// + public int Port + { + get {return _port;} + } + #endregion + + /// + /// Return the host name, a colon, and a port number. + /// + /// + public override string ToString() + { + return Hostname+":"+Port; + } + + /// + /// Set the hostname used by the HELO + /// command. + /// + public String HeloHost + { + get + { + return _helohost; + } + set + { + _helohost=value; + } + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/TextAttachment.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/TextAttachment.cs new file mode 100644 index 00000000..d80a7bbe --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/TextAttachment.cs @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A mime representation of plain-text content. + /// + public class TextAttachment : AbstractEmailAttachment + { + + //private IEncoder _encoder=null; + //private String _mimetype="text/plain"; + /// + /// 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. + /// + /// + 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; + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/BinaryStreamUtil.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/BinaryStreamUtil.cs new file mode 100644 index 00000000..cb3d2c7c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/BinaryStreamUtil.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; + +namespace DotNetOpenMail.Utils +{ + /// + /// Something take a binary reader's data into a byte array. + /// + public class BinaryReaderUtil + { + /// + /// Constructor for BinaryReaderUtil + /// + public BinaryReaderUtil() + { + } + + /// + /// Read a binary stream into a byte array + /// (Cribbed from posting by Jon Skeet: + /// http://www.developerfusion.co.uk/show/4696/) + /// + /// An open Binary Reader + /// A byte array with the bytes from the disk + 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; + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/Configuration.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/Configuration.cs new file mode 100644 index 00000000..0d022450 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/Configuration.cs @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An interface to the configuration settings for the library. + /// This includes an interface to the .config file. + /// This is a singleton. + /// + public class Configuration + { + /// + /// The singleton + /// + private static Configuration _theinstance=new Configuration(); + + /// + /// Empty constructor + /// + private Configuration() + { + + } + + /// + /// Instantiate the instance of the object (if not created) + /// and return it. + /// + /// the Configuration singleton object + public static Configuration GetInstance() + { + return _theinstance; + } + + /// + /// Get the X-Sender header, if any is specified in the .config + /// file with the key dnom.headers.xsender. + /// + /// + public String GetXSender() + { + return System.Configuration.ConfigurationSettings.AppSettings["dnom.headers.xsender"]; + } + + /// + /// Get the default encoding, if any is specified in the .config + /// file with the key dnom.encoding. + /// + public String GetDefaultEncoding(String def) + { + return GetAppSetting("dnom.encoding", def); + } + + /// + /// Get the default charset, if any is specified in the .config + /// file with the key dnom.charset. + /// + public System.Text.Encoding GetDefaultCharset() + { + String encodingstr=GetAppSetting("dnom.encoding", "iso-8859-1"); + return System.Text.Encoding.GetEncoding(encodingstr); + } + + /// + /// Get an app setting from the .config file. If none is found + /// or it is empty or only whitespace, use the defaultvalue. + /// + /// The key to search for in the .config file + /// The default value if the value + /// is null or only whitespace. + private String GetAppSetting(String key, String defaultvalue) + { + String tmp=System.Configuration.ConfigurationSettings.AppSettings[key]; + if (tmp==null || tmp.Trim()=="") + { + return defaultvalue; + } + else + { + return tmp; + } + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/EmailAddressParser.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/EmailAddressParser.cs new file mode 100644 index 00000000..e34c3927 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/EmailAddressParser.cs @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Parse a email address string into an EmailAddress. + /// * This isn't very mature yet! * + /// + public class EmailAddressParser + { + private String _lastError=null; + + /// + /// Constructor + /// + public EmailAddressParser() + { + } + + /// + /// If the last conversion was unsuccessful, this + /// contains the error message. If it was successful, + /// it will be null. + /// + public String LastError + { + get {return _lastError;} + } + + /// + /// Parse a raw email address into an EmailAddress object. + /// If it can't be parsed, return null and set LastError + /// to the error message. + /// + /// + /// + public EmailAddress ParseRawEmailAddress(String rawemailaddress) + { + // see: http://www.twilightsoul.com/Default.aspx?PageContentID=10&tabid=134 + String regex=@"^((?([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+[\t\x20]*|"""+ + @"[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*"")+)?[\t\x20]*"+ + @"<(?([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+"+ + @"(\.[!#-'\*\+\-/-9=\?A-Z\^-~]+)*|""[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*""))"+ + @"@(?(([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]*|"+ + @"(?([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+(\.[!#-'\*\+\"+ + @"-/-9=\?A-Z\^-~]+)*|"+ + @"""[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*""))"+ + @"@(?(([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); + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/VersionInfo.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/VersionInfo.cs new file mode 100644 index 00000000..c63704ed --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMail/Utils/VersionInfo.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// The DotNetOpenMail Version. + /// + 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 + + /// + /// Empty Constructor + /// + private VersionInfo() + { + } + + /// + /// Get the singleton of this class + /// + /// + public static VersionInfo GetInstance() + { + return new VersionInfo(); + } + + /// + /// 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. + /// + /// + public override String ToString() + { + return String.Format("{0}.{1}.{2}{3}", majorid, minorid, incidentalid, status); + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/AssemblyInfo.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/AssemblyInfo.cs new file mode 100644 index 00000000..aa653dd1 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/AssemblyInfo.cs @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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\. 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("")] diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/DotNetOpenMailTests.csproj b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/DotNetOpenMailTests.csproj new file mode 100644 index 00000000..78027d12 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/DotNetOpenMailTests.csproj @@ -0,0 +1,251 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/DotNetOpenMailTests.csproj.user b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/DotNetOpenMailTests.csproj.user new file mode 100644 index 00000000..a4a4ef37 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/DotNetOpenMailTests.csproj.user @@ -0,0 +1,48 @@ + + + + + + + + + + + + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailAddressTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailAddressTests.cs new file mode 100644 index 00000000..2ba9034e --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailAddressTests.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 ",emailaddress.ToString()); + + emailaddress=new EmailAddress("test@test.com", "Last, First"); + Assert.AreEqual("\"Last, First\" ",emailaddress.ToString()); + + emailaddress=new EmailAddress("test@test.com", ""); + Assert.AreEqual("\"\" ",emailaddress.ToString()); + + emailaddress=new EmailAddress("test@test.com", "[First Last]"); + Assert.AreEqual("\"[First Last]\" ",emailaddress.ToString()); + + emailaddress=new EmailAddress("test@test.com", "(First Last)"); + Assert.AreEqual("\"(First Last)\" ",emailaddress.ToString()); + emailaddress=new EmailAddress("test@test.com", "First \"NickName\" Last"); + Assert.AreEqual("\"First \\\"NickName\\\" Last\" ",emailaddress.ToString()); + + + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailMessageInAlternateEncodings.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailMessageInAlternateEncodings.cs new file mode 100644 index 00000000..aa5594f6 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailMessageInAlternateEncodings.cs @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("æ±äº¬ã€æ—¥æœ¬èªž"); + //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("=1B$BEl5~!\"F|K\\8l=1B(B")==0) + { + //=67=71=4E=AC=30=01=65=E5=67=2C=8A=9E + + 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("æ±äº¬ã€æ—¥æœ¬èªž"); + + 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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailMessageTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailMessageTests.cs new file mode 100644 index 00000000..0f4ab50a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/EmailMessageTests.cs @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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 + + + } +} + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/Base64EncoderTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/Base64EncoderTests.cs new file mode 100644 index 00000000..59a8cc49 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/Base64EncoderTests.cs @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/EightBitEncoderTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/EightBitEncoderTests.cs new file mode 100644 index 00000000..74021f35 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/EightBitEncoderTests.cs @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/QPEncoderTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/QPEncoderTests.cs new file mode 100644 index 00000000..84a6deb0 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/QPEncoderTests.cs @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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()); + + } + */ + } +} + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/SevenBitEncoderTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/SevenBitEncoderTests.cs new file mode 100644 index 00000000..5db67a4a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Encoding/SevenBitEncoderTests.cs @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/ExampleTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/ExampleTests.cs new file mode 100644 index 00000000..01877b3c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/ExampleTests.cs @@ -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(""+ + "

Just checking up on where you were last night.

\r\n"+ + "

Send me a note!

\r\n\r\n"+ + "

-Charles

"); + + 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(""+ + "

Note to self: look at this photo again in 30 years.

"+ + "

\"Hawthorne

"+ + "

-Marcel

"); + + 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("

I regret that something "+ + "has come up unexpectedly,\r\n"+ + "and I must postpone our meeting.

\r\n"+ + "

Please read the 20 pages of my thoughts on this in the attached\r\n"+ + "PDF file.

\r\n

-Marcel

"); + + FileAttachment fileattachment=new FileAttachment(new FileInfo(@"..\..\TestFiles\grover.jpg")); + + fileattachment.ContentType="image/jpeg"; + + emailmessage.AddMixedAttachment(fileattachment); + + emailmessage.Send(TestAddressHelper.GetSmtpServer()); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/FileAttachmentTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/FileAttachmentTests.cs new file mode 100644 index 00000000..050ce945 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/FileAttachmentTests.cs @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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(""+ + "

This is a license.

\r\n"+ + "

We will spend your money on a new plasma TV.

\r\n"+ + ""); + + 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(""+ + "

This a jpeg.

\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(""+ + "

This is a license.

\r\n"+ + "

We will spend your money on a new plasma TV.

\r\n"+ + ""); + + 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(""+ + "

This a zip file.

\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); + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/FileAttachmentTests2.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/FileAttachmentTests2.cs new file mode 100644 index 00000000..81f223bb --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/FileAttachmentTests2.cs @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("

This is a PDF File

\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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Log4netLogger.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Log4netLogger.cs new file mode 100644 index 00000000..b1ee920a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Log4netLogger.cs @@ -0,0 +1,26 @@ +using System; + +using DotNetOpenMail.Logging; + +using log4net; + +namespace DotNetOpenMailTests +{ + /// + /// Summary description for Log4netLogger. + /// + 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); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/QuickTest.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/QuickTest.cs new file mode 100644 index 00000000..30167596 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/QuickTest.cs @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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", ""); + + 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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); + + + + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RFC2822DateTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RFC2822DateTests.cs new file mode 100644 index 00000000..b936f2b9 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RFC2822DateTests.cs @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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()); + + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RawEmailMessageTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RawEmailMessageTests.cs new file mode 100644 index 00000000..e09fde2c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RawEmailMessageTests.cs @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 description for RawEmailMessageTests. + /// + [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); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Resources/ARMTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Resources/ARMTests.cs new file mode 100644 index 00000000..1ba7f7be --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Resources/ARMTests.cs @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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() { + + } + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RussianTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RussianTests.cs new file mode 100644 index 00000000..7735d713 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/RussianTests.cs @@ -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); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/LocalAuthTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/LocalAuthTests.cs new file mode 100644 index 00000000..26ae7400 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/LocalAuthTests.cs @@ -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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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 + + + + } +} + diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/MockedSlowProxy.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/MockedSlowProxy.cs new file mode 100644 index 00000000..92709724 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/MockedSlowProxy.cs @@ -0,0 +1,33 @@ +using System; +using System.Net.Sockets; + +using DotNetOpenMail; +using DotNetOpenMail.SmtpAuth; + +namespace DotNetOpenMailTests.SmtpAuth +{ + /// + /// Summary description for MockedSlowServer. + /// + 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"); + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/MockedSmtpProxy.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/MockedSmtpProxy.cs new file mode 100644 index 00000000..d929fd2a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpAuth/MockedSmtpProxy.cs @@ -0,0 +1,94 @@ +using System; + +using DotNetOpenMail; +using DotNetOpenMail.SmtpAuth; +using DotNetOpenMail.Encoding; + +namespace DotNetOpenMailTests.SmtpAuth +{ + /// + /// Summary description for MockedSmtpProxy. + /// + 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 + } + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpProxyTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpProxyTests.cs new file mode 100644 index 00000000..079834da --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpProxyTests.cs @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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("This
\r\n..is the
\r\n..HTML
\r\npart."); + emailmessage.Send(_smtpserver); + + // this doesn't test anything yet + //log.Debug("MESSAGE: "+emailmessage.ToDataString()); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpServerTests/SmtpServerTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpServerTests/SmtpServerTests.cs new file mode 100644 index 00000000..b7cf9f95 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/SmtpServerTests/SmtpServerTests.cs @@ -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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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); + + + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestAddressHelper.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestAddressHelper.cs new file mode 100644 index 00000000..bc482156 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestAddressHelper.cs @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 description for TestAddressHelper. + /// + 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); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestFiles/ImportedEmail.txt b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestFiles/ImportedEmail.txt new file mode 100644 index 00000000..d8780114 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestFiles/ImportedEmail.txt @@ -0,0 +1,4 @@ +Subject: This is a test +To: mike@bridgecanada.com + +This is a test. diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestFiles/grover.jpg b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/TestFiles/grover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..19d8bd527060d487735ed5fdefa7a35a35135b9d GIT binary patch literal 5881 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 literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Utils/EmailAddressParserTests.cs b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Utils/EmailAddressParserTests.cs new file mode 100644 index 00000000..a213815c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/Backup/DotNetOpenMailTests/Utils/EmailAddressParserTests.cs @@ -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); + + + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/CHANGES.txt b/DotNetOpenMail-0.5.8b/CHANGES.txt new file mode 100644 index 00000000..50ba8661 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/CHANGES.txt @@ -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 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail.sln b/DotNetOpenMail-0.5.8b/DotNetOpenMail.sln new file mode 100644 index 00000000..d656a85e --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail.sln @@ -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 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/AbstractEmailAttachment.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/AbstractEmailAttachment.cs new file mode 100644 index 00000000..882c1a50 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/AbstractEmailAttachment.cs @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// 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 + /// + 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"; + + /// + /// The mail encoding type (e.g. quoted-printable, etc) + /// + protected EncodingType _encodingtype; + + /// + /// The "content type" of the attachment + /// + protected String _contenttype; + + /// + /// The content-transfer encoding of the attachment + /// + protected String _contenttransferencoding; + + /// + /// The content disposition of the attachment + /// + protected String _contentdisposition; + + /// + /// The content description of the attachment + /// + protected String _contentdescription; + + /// + /// The character set of the encoded text + /// + protected System.Text.Encoding _charset=null; + + /// + /// The unencoded contents, as a string (optional) + /// + protected String _contents=null; + + /// + /// An optional content id + /// + protected String _contentid=null; + + /// + /// The file name to identify the content. + /// (This can be different from the actual file name, + /// if there was one.) + /// + protected String _filename=null; + + /// + /// The file source to read from + /// + protected FileInfo _fileinfo=null; + + /// + /// The binary source of the file + /// + protected Byte[] _contentbytes=null; + + /// + /// Empty constructor + /// + public AbstractEmailAttachment() + { + } + + #region GetEncodedContents + /// + /// Get the contents, encoded for shipping via SMTP + /// + /// The encoder to encode the contents + /// returns the encoded string, ready for SMTP transfer + 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 + /// + /// Return the encoded contents, including mime + /// header. + /// + /// + 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 + /// + /// The encoding type for this attachment. + /// + public EncodingType Encoding + { + get {return _encodingtype;} + set {_encodingtype=value;} + } + #endregion + + #region ContentType + /// + /// The "content type" of the attachment + /// + public String ContentType + { + get {return _contenttype;} + set {_contenttype=value;} + } + #endregion + + #region CharSet + /// + /// The character set of the encoded text + /// + public System.Text.Encoding CharSet + { + get {return _charset;} + set {_charset=value;} + } + #endregion + + #region ContentId + /// + /// An optional content id that is used to refer to + /// the attachment from elsewhere within a multipart/related + /// email. + /// + public String ContentId + { + get {return _contentid;} + set {_contentid=value;} + } + #endregion + + #region FileName + /// + /// The file name to attach to the attachment. + /// + public String FileName + { + get {return _filename;} + set {_filename=value;} + } + #endregion + + #region Contents + /// + /// The unencoded contents, as a string (optional) + /// + public String Contents + { + get {return _contents;} + set {_contents=value;} + } + #endregion + + #region ContentBytes + /// + /// The raw bytes of the content (if this is the way + /// it was set.) + /// + public byte[] ContentBytes + { + get {return _contentbytes;} + set {_contentbytes=value;} + } + #endregion + + #region GetInternalMimeHeader + /// + /// Create the internal mime header, as found on the + /// mime-attachment itself. + /// + /// + /// + 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 + + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/AssemblyInfo.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/AssemblyInfo.cs new file mode 100644 index 00000000..2a1c3348 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/AssemblyInfo.cs @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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\. 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("")] diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.csproj b/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.csproj new file mode 100644 index 00000000..0f6ce9c6 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.csproj @@ -0,0 +1,220 @@ + + + + Local + 7.10.3077 + 2.0 + {6FBB299F-81A1-49EA-B00A-E916F8F797B3} + Debug + AnyCPU + + + DotNetOpenMail + + JScript + Grid + IE50 + false + Library + DotNetOpenMail + OnBuildSuccess + + + + v4.6 + + + 0.0 + + + + bin\Debug\ + false + 285212672 + false + + DEBUG;TRACE + DotNetOpenMail.xml + true + 4096 + false + + false + false + false + false + 4 + full + prompt + false + + + bin\Release\ + false + 285212672 + false + + TRACE + DotNetOpenMail.xml + false + 4096 + false + + true + false + false + false + 4 + none + prompt + false + + + + System + + + System.Data + + + System.XML + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + + \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.csproj.user b/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.csproj.user new file mode 100644 index 00000000..ca3451ea --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.csproj.user @@ -0,0 +1,44 @@ + + + + 7.10.3077 + Debug + AnyCPU + C:\Visual Studio Projects\DotNetOpenMail\lib\ + + + 0 + ShowAllFiles + 0 + + + false + false + false + false + false + + Project + + + + + + true + + + false + false + false + false + false + + Project + + + + + + true + + \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.xml b/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.xml new file mode 100644 index 00000000..4692563e --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/DotNetOpenMail.xml @@ -0,0 +1,2208 @@ + + + + DotNetOpenMail + + + + + 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 + + + + + The mail encoding type (e.g. quoted-printable, etc) + + + + + The "content type" of the attachment + + + + + The content-transfer encoding of the attachment + + + + + The content disposition of the attachment + + + + + The content description of the attachment + + + + + The character set of the encoded text + + + + + The unencoded contents, as a string (optional) + + + + + An optional content id + + + + + The file name to identify the content. + (This can be different from the actual file name, + if there was one.) + + + + + The file source to read from + + + + + The binary source of the file + + + + + Empty constructor + + + + + Get the contents, encoded for shipping via SMTP + + The encoder to encode the contents + returns the encoded string, ready for SMTP transfer + + + + Return the encoded contents, including mime + header. + + + + + + The encoding type for this attachment. + + + + + The "content type" of the attachment + + + + + The character set of the encoded text + + + + + An optional content id that is used to refer to + the attachment from elsewhere within a multipart/related + email. + + + + + The file name to attach to the attachment. + + + + + The unencoded contents, as a string (optional) + + + + + The raw bytes of the content (if this is the way + it was set.) + + + + + Create the internal mime header, as found on the + mime-attachment itself. + + + + + + + The server response from EHLO + + + + + Create an instance of the EhloSmtpResponse class + + + + + Get the available Auth Types strings + as reported by the server. + (e.g. "login", etc.) + + + + + + Add an Auth type (by string as contained in the + EHLO authentication. These are converted to lower + case. + + The auth type from EHLO + + + + The SMTP Reponse code + + + + + The SMTP Message. This will be "OK" if successful, + otherwise it will be the part that failed. + + + + + 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. + + + + + Create an instance of an email address object. + + The address portion of the email + The name portion of the email. + + + + Create an instance of an email address object. + + The address portion of the email + + + + Create an character-encoded instance of an email address object. + + The address portion of the email + The name portion of the email. + The character set to encode the name portion of the email address. + The encoding type to use to encode the name portion of the mail address. + + + + The email address portion of the email address object + + + + + The name portion of the email address object + + + + + Create the string representation of this email address + (encoded or otherwise) as it will appear in the email + + + + + + Calls ToDataString. + + + + + + A collection of EmailAddress objects. Implements + CollectionBase + + + + + Create a new instance of the EmailAddressCollection + + + + + Add an object to the collection + + The EmailAddress object to add + + + + + Append a collection of objects to the existing collection + + The EmailAddressCollection to append to the existing collection. + + + + Find the index of the EmailAddress in the collection + + The object to find. + The index, from 0, or -1 if not found. + + + + Insert an EmailAddress into the collection at the + specified index. + + The index, starting at zero. + The email address to add to the collection + + + + Remove an address, if found, from the collection. + + The EmailAddress to remove + + + + Render the email addresses in a comma-separated list, + suitable for being rendered in an email. + + + + + + Calls ToDataString(). + + + + + + An Email Message + + + + + Create a new instance of an EmailMessage. + + + + + The subject line or subject header of the + email. + + + + + 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. + + + + + Normally the FromAddress is used as the + envelope-from address, but it can be + overridden here, if it is not null. + + + + + Add a To address to the Headers. This will also + be used during the "RCPT TO" SMTP negotiation + + Email Address object of the recipient + + + + Add a To address to the Headers. This will also + be used during the "RCPT TO" SMTP negotiation + + The plain email address (don't include the name) + + + + Retrieve the collection of recipients + that will appear in the "To" header of the + email. + + + + + Add a Cc address to the Headers. This will also + be used during the "RCPT TO" SMTP negotiation + + Email Address object of the recipient + + + + Add a Cc address to the Headers. This will also + be used during the "RCPT TO" SMTP negotiation + + The plain email address (don't include the name) + + + + Retrieve the collection of recipients + that will appear in the "Cc" header of the + email. + + + + + 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. + + The EmailAddress object + + + + 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. + + The plain email address (don't include the name) + + + + Get the current EmailAddressCollection of BCC addresses + + + + + Get/set the organization (as it will appear in the organization + header + + + + + Get the current XMailer setting for the X-Mailer header. + + + + + Add a custom mail header, e.g. "X-MyHeader". + + The header name (without a colon) + The value of the header. This value will not + be encoded. + + + + The charset that is used for encoding the headers + + + + + The mime encoding that is used for encoding the headers + + + + + Get the minimal header set in the specified character, + and using the mime encoder provided. + + + + + Encode a header value using the current header encoder and charset. + + The header name + The header value + + + + + Returns true if there is content that should be "multipart/mixed" + + true if the content is multipart/mixed. + + + + Returns true if there is content that should be "multipart/related" + + true if the content is multipart/related. + + + + Encode the headers as they will appear in the email + + the charset encoding for the string + the mime encoding + the encoded string + + + + Encode the email body as it will appear in the email + + the encoded body + + + + format the body text---not implemented yet. + + + + + + + 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. + + + + + Render the encoded message for smtp "DATA" transmission. + This is the final version that will get sent to the + + + + + + 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 + + The outgoing SMTP server. + true if sent successfully. (note that this + will not currently return false, but in the future + a false value may be used) + + + + Set the content type string in the mime header + + + + + Set the plain text part of the email. This is optional + + + + + Set the html part of the email. This is optional + + + + + Add an attachment which will appear to the user as + a separate file. (It is not referred to in the email itself.) + + The file attachment + + + + 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. + + The file attachment + + + + Encode a file in Base64 Encoding. + + See: http://www.freesoft.org/CIE/RFC/1521/7.htm + + + + + The maximum chars per line before end of line char(s) + + + + + The end-of-line character(s) to use + + + + + Empty Constructor + + + + + Create an instance of this class + + + + + 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. + + Reader for incoming string + Writer for outgoing encoded string + The character encoding for the encoded string. + + + + Encode the File's data in base64. + + Reader for incoming string + Writer for outgoing encoded string + The character set for the encoded string + + + + Encode the File's data in base64. + + Reader for incoming string + Writer for outgoing encoded string + + + + Encode a string in Base64 in a particular characters set + + The source text + the charset for the encoded text + Returns an encoded string + + + + Encode header as per RFC 2047: + http://www.faqs.org/rfcs/rfc2047.html + + The header name + The header text to be encoded (data only) + The charset for the encoded string + ignored for this class + Returns the encoded string + + + + Chop the text into lines that are smaller + than MAX_CHARS_PER_LINE + + + + + + + The String that goes in the content transfer encoding header + + + + + An encoder that does nothing. (This is essentially + what the 7bit and 8bit encodings are; they are just + markers, not actual encodings) + + + + + Empty constructor + + + + + Echo the text back unchanged. + + Reader for the incoming string + Writer for the outgoing string + The encodigng for the outgoing string (ignored) + + + + Echo the text back unchanged + + The incoming filestream + The outgoing filestream + Charset (ignored) + + + + Echo the text back unchanged (good for 7bit text only). + + The incoming binaryreader + The outgoing stream + + + + Do nothing to the header string + + The header key + The header value + The charset to encode in (ignored) + (ignored) + + + + + The String that goes in the content transfer encoding header + + + + + Denotes 8bit encoding. Note that this doesn't really + encode anything; it just specifies that this email is already + in 8-bit encoding. + + + + + Empty Constructor + + + + + Create the EightBitEncoder object. + + + + + The String that goes in the content transfer encoding header + + + + + Factory for instantiating the right encoder class, + given an encoding + + + + + Empty Constructor. + + + + + Method for determining the correct encoder for this + encoding type. + + Enumerated encoding type + Returns the proper IEncoder implementation + Throws an ApplicationException if the specified encoding is unknown. + + + + Enumeration of encoding types. + + + + + The Quoted-Printable encoding + + + + + The Base-65 encoding + + + + + The 7Bit encoding marker + + + + + The 8Bit encoding marker + + + + + An interface for a string encoder + + + + + Encode from the stringreader to the stringwriter. + + an open stringreader to the source string + where the output is written + the outgoing charset + + + + Encode the file stream into the stringwriter. + + an open stream to file to be read + where the output is written + the outgoing charset + + + + Encode the binary reader into the stringwriter. + + an open binary reader for the data to be encoded. + where the output is written + + + + Encode the string according to rfc-2047 if some of it + falls outside the 7bit ASCII charset. + + The header key + The header value string + Charset for the encoded string + Force encoding, even if in ascii-only. + The encoded string + + + + The String that goes in the content transfer encoding header + + + + + See: http://www.freesoft.org/CIE/RFC/1521/6.htm + + + + + Maximum characters per line, before the end-of-line character + + + + + The end-of-line character(s). + + + + + Empty Constructor + + + + + Create an instance of the encoder + + The instantiated Quoted-printable encoder + + + + Encode the incoming stream in quoted-printable encoding. + + The incoming binary reader + The outgoing string writer + + + + Encode the incoming stream in quoted-printable encoding. + + The incoming file stream + The outgoing string writer + The charset to write the outgoing string in + + + + + Encode the string in quoted printable format + + The source string + The outgoing charset + the encoded string + + + + Encode the string in quoted printable format + + The source string + The outgoing charset + Force encoding, even if not required by qp RFC + The total characters outside the encoding. This is used to figure + out how long the line will be after encoding. + the encoded string + + + + Encode header as per RFC 2047: + http://www.faqs.org/rfcs/rfc2047.html + + + This doesn't split long lines yet + the header name + the string to encode + The charset to encode to + Force encoding, even if not required by qp RFC + the encoded string, suitable for use in a header + + + + Encode a char according to quoted-printable + standard + + the char to encode + the encoded char representation + + + + Encode a byte according to quoted-printable + standard + + the byte to encode + the encoded byte representation + + + + The String that goes in the content transfer encoding header + + + + + Return true if the char needs to be encoded. + + + + + + + + Return true if the byte needs to be encoded. + + + + + + + + Return true if the string needs to be encoded. + + The string to check + true if outside 127-bit, or one of the + quoted-printable special characters. + + + + Check if the character is one of the non-qp + characters + + the character to check + true if outside the acceptable qp range + + + + + Denotes 7bit encoding. Note that this doesn't really + encode anything; it just specifies that this email is already + in 7-bit ascii encoding. + + + + + Empty constructor + + + + + Create an instance of this class. + + + + + + The String that goes in the content transfer encoding header + + + + + A mime representation of a file which can be transferred + via email. + + + + + Create a new File attachment from a FileInfo object + + A fileinfo object which points to a local file. + + + + Create a new text file attachment from a StreamReader. + + An open streamreader + + + + Create a new binary file attachment from a BinaryReader. + + An open binaryreader + + + + Create a new binary file attachment from an array of bytes. + + An array of bytes + + + + Create a new file attachment from a String. + + The contents of the file + + + + 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. + + A fileinfo object which points to a local file. + the content id value + + + + 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. + + An open streamreader + the content id value + + + + 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. + + An open binary readerr + the content id value + + + + 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. + + An array of bytes + the content id value + + + + 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. + + The contents of the file + the content id value + + + + An HTML email attachment + + + + + 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. + + The HTML content of the attachment + + + + Objects of a class which implements this interface + can be converted to a string which can be used in + an email. + + + + + A message which can be sent. + + + + + Interact directly with the SMTP server. + + + + + Open the connection + + The SMTP response + + + + Send the HELO command + + + + + + + Send the EHLO command + + + + + + + Send the MAIL FROM command + + + + + + + Send one RCPT TO command + + + + + + + Send the DATA command + + + + + + Write the message content + + + + + + Send the QUIT message to the server + + + + + + Close the connection + + The SMTP response + + + + Send the AUTH command + + the SMTP response + + + + Send any old string to the proxy + + the SMTP response + + + + Turn the SMTP Conversation Capture off/on. + If on, GetSmtpConversation will contain the + most recent conversation. + + the on/off value + + + + Summary description for Logger. + + + + + Log handler delegate + + + + + Log event + + + + + Return the singleton object + + + + + + Log a message with level "Info" + + + + + + Log a message with level "Debug" + + + + + Log a message with level "Error" + + + + + Log the output of sending smtp + + + + + Log the reply via smtp + + + + + + Summary description for LogMessage. + + + + + The log message + + + + + The sender object + + + + + Log a message + + The object logging the message + The message to be logged + + + + General Mail Exception, including network errors, + connection errors, and configuration errors. + + + + + Create an instance of a MailException + + + + + Create an instance of a MailException + + The message describing the exception + + + + Create an instance of a MailException + + The message describing the exception + The inner exception + + + + This represents one of the message headers as it + appears in the email. + + + + + Create a new instance of a MessageHeader + + The header name (without a colon) + The unencoded value + + + + Create a new instance of a MessageHeader, with a mime-encoded + value. + + The header name (without a colon) + The non-encoded header value + The mime-encoded value + + + + The name of the header. + + + + + The unencoded value of the header + + + + + The mime-encoded value of the header + + + + + The string representation of the header, as it will + appear in the email. + + + + + + A collection of MessageHeader objects + Implements the CollectionBase interface. + + + + + Initializes a new instance of the ArrayList class. + + + + + Adds an object to the end of the MessageHeaderCollection + + The Object to be added to the end of the MessageHeaderCollection. + The value can be a null reference (Nothing in Visual Basic). + The MessageHeaderCollection index at which the value has been added. + + + + Returns the zero-based index of the first occurrence of a + value in the MessageHeaderCollection or in a portion of it. + + The Object to locate in the MessageHeaderCollection. The value + can be a null reference (Nothing in Visual Basic). + + + + + Inserts an element into the MessageHeaderCollection at + the specified index. + + The zero-based index at which value should be inserted + The MessageHeader to insert. + The value can be a null reference (Nothing in Visual Basic). + + + + Removes the first occurrence of a + specific MessageHeader from the MessageHeaderCollection. + + The object to remove from the MessageHeaderCollection + + + + Write the MessageHeaderCollection to a string that can be + included in an email. + + The String as it will appear in the resulting email. + + + + A boundary which delimits a MIME object. + + + + + A MIME container for content or other mime containers. + + + + + A full, preformatted email message, including headers + + + + + Create an instance of the RawEmailMessage + + + + + The raw content of the email + + + + + The address to use in the envelope-from + SMTP negotiation + + + + + The recipient addresses + + + + + Add a recipient to the EmailAddressCollection + of recipients + + + + + + Send the email via the specified SMTP server + + The SMTP server to use + true if the email was sent + + + + Render the message for smtp "DATA" transmission. + + The rendered String, which in this + case is the content itself, untouched. + + + + ARM= Assembly Resource Manager. Manage the strings for the + various CultureInfo types. + + + + + The singleton object + + + + + The namespace of the resource files + + + + + The singleton System.Resources.ResourceManager. + + + + + Create the singleton + + + + + Get the instance of the class + + the ARM instance + + + + Get an object from the file + + The key + The key lookup for the default culture + + + + Get an object for the specified CultureInfo + + The specified culture for the resource + The key for the resource + returns an object, if one is found, else null + + + + Get a string for the specified CultureInfo for the + default culture + + The key for the resource + returns a string, if one is found, else null + + + + Get a string for the specified CultureInfo for the + default culture. If not found, return defaultvalue + + The key for the resource + The value to return if there + is no value found. + returns a string, if one is found, else defaultvalue + + + + Get a string for the specified CultureInfo for the + current culture. If not found, return null + + The culture of the resulting string + The key for the resource + returns a string, if one is found, else + null + + + + Get a string for the specified CultureInfo for the + default culture. If not found, return defaultvalue + + The culture of the resulting string + The key for the resource + The value to return if there + is no value found. + returns a string, if one is found, else defaultvalue + + + + Retrieve the entire resource set for this culture. + + The culture to examine + The resource set, if any. + + + + Create a RFC 2822-compliant date. + + See section 3.3 in + http://ftp.rfc-editor.org/in-notes/rfc2822.txt + + + + + Create an instance of the RFC 2822 date object. + + The date to convert + The timezone to use in the conversion + + + + Generate the date string + + A RFC-2822 error code + + + + Summary description for ISmtpAuthenticationToken. + + + + + The user's login + + + + + The user's password + + + + + Negotiate AUTH with the SmtpProxy. + + + + + + A LOCAL SMTP AUTH token + + + + + Create a new instance of the LOCAL SMTP + AUTH token + + + + + The User's password + + + + + The User's login + + + + + Return the 235 response code if valid, otherwise + return the error. + + + the supported auth types + + + + + Summary description for SmtpAuthHelper. + + + + + Get the Auth type from the SMTP EHLO response. + If it is unrecognized or unimplemented, + return null. Case doesn't matter. + + The string as returned in EHLO negotiation. + The user's login + The User's password + + + + Token which will negotiate an authentication type + with the server. + + + + + Create a new instance of the LOCAL SMTP + AUTH token + + + + + The User's password + + + + + The User's login + + + + + Return the 235 response code if valid, otherwise + return the error. + + The SmtpProxy being used + String array of EHLO-specified auth types + + + + + An SmtpException represents an SMTP response + code and an error message. Network and connection + errors are represented by a MailException instead. + + + + + Create a new instance of the SmtpException + + The SMTP error code + + + + Create a new instance of the SmtpException + + The SMTP error code + The SMTP error message + + + + Create a new instance of the SmtpException + + The SMTP error code + The SMTP error message + The inner exception + + + + The SMTP error code. + + + + + Convert to a string + + + + + + A proxy to access an SMTP server. This drives + the protocol interaction. + + + + + Get an instance of the SMTP Proxy + + + + + + + Connect to the server and return the initial + welcome string. Throw a MailException if we + can't connect. + + + + + + Send the HELO string. + Throw a MailException if we can't connect. + + the SMTP response + + + + Send the EHLO string. + Throw a MailException if we can't connect. + + the SMTP response + + + + Send the MAIL FROM command + Throw a MailException if we can't connect. + + The Envelope-From address + the SMTP response + + + + Send the MAIL FROM command + Throw a MailException if we can't connect. + + A recipient's address + the SMTP response + + + + Send the DATA string (without the data) + Throw a MailException if we can't connect. + + the SMTP response + + + + Send the message content string + Throw a MailException if we can't + connect. + + the SMTP response + + + + Parse the response from the EHLO into an + EhloSmtpResponse. Returns 250 "OK" if successful. + + + + + + Send the AUTH command + Throw a MailException if we can't connect. + + the SMTP response + + + + Send any old string to the proxy + + the SMTP response + + + + Write a string to the current connection. + + + + + + Send the QUIT command + Throw a MailException if we can't connect. + + the SMTP response + + + + Set this to "true" if you want to capture the SMTP negotiation. + Once the conversation has finished, use "GetConversation" to + view it. + + + + + The response from the SMTP server + + + + + Create an instance of the SmtpResponse + + + + + + + The SMTP Reponse code + + + + + The SMTP Response String + + + + + Was the response a fatal error? + + + + + Was the response an OK message? + + + + + Convert this response to an exception + + The SmtpException corresponding to this response + + + + SMTP server response codes and their meanings. + + + + + System status, or system help reply. + + + + + Help message. + + + + + Domain service ready. Ready to start TLS. + + + + + Domain service closing transmission channel. + + + + + Authentication successfully completed. + + + + + OK, queuing for node node started. Requested mail action completed. + + + + + OK, no messages waiting for node node. User not local, will forward to forwardpath. + + + + + 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. + + + + + OK, messages pending messages for node node started. + + + + + Start mail input, end with CRLF.CRLF + + + + + Octet-offset is the transaction offset. + + + + + Domain service not available, closing transmission channel. + + + + + A password transition is needed. + + + + + Requested mail action not taken: mailbox unavailable. + + + + + Requested action aborted: local error in processing. Unable to process ATRN request now. + + + + + Requested action not taken: insufficient system storage. + + + + + You have no mail. + + + + + TLS not available. Encryption required for requested authentication mechanism. + + + + + Unable to queue messages for node node. + + + + + Node node not allowed: reason. + + + + + Command not recognized: command. Syntax error. + + + + + Syntax error, no parameters allowed. + + + + + Command not implemented. + + + + + Bad sequence of commands. + + + + + Command parameter not implemented. + + + + + Security error. + + + + + Machine does not accept mail. + + + + + Must issue a STARTTLS command first. Encryption required for requested authentication mechanism. + + + + + Authentication mechanism is too weak. + + + + + Encryption required for requested authentication mechanism. + + + + + Requested action not taken: mailbox unavailable. + + + + + User not local, please try forward path. + + + + + Requested mail action aborted: exceeded storage allocation. + + + + + Requested action not taken: mailbox name not allowed. + + + + + Transaction failed. + + + + + A description of an SMTP server. + + + + + Logging delegate + + + + + Handle a message about to be sent + + + + + Handle a message received + + + + + Log that the conversation has completed + + + + + Create a new SMTP server at this hostname and + port. + + The address or hostname of the smtp server + The port of the smtp server. + + + + Create a new SMTP server at this hostname and + port. + + The address or hostname of the smtp server + + + + Create a new SMTP server at this hostname and + port. + + The ip address of the SMTP server + The port number of SMTP server + + + + Get the end point for the SMTP server. The IPEndpoint will + be saved for later to prevent multiple hostname lookups. + + SmtpException is thrown if the host doesn't resolve. + returns an IPEndPoint for the SMTPServer. + + + + The timeout waiting for an SMTP command, in + milliseconds + + + + + Get an instance of an SmtpProxy + + + + + + Figure out whether we need EHLO or not. + Currently, this is only for SMTP AUTH + + + + + + Send the email. + + The completed message + A list of email addresses which + are to be used in the RCPT TO SMTP communication + An email address for the MAIL FROM + part of the SMTP protocol. + throws an SmtpException if there + is an unexpected SMTP error number sent from the server. + throws a MailException if there + is a network problem, connection problem, or other issue. + + + + + Override the SmtpProxy. This is only + for testing smtp negotiation without an + smtp server. + + + + + + Get or set the SMTP AUTH token for the server. + + + + + 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. + + + + + Append this string to the conversation log. + + the string from the SMTP conversation + + + + If CaptureSmtpConversation is true, a Send() will + be captured, and will be accessible here. + + The SMTP Conversation or null. + + + + The server hostname + + + + + The server port + + + + + Return the host name, a colon, and a port number. + + + + + + Set the hostname used by the HELO + command. + + + + + A mime representation of plain-text content. + + + + + 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. + + + + + + Something take a binary reader's data into a byte array. + + + + + Constructor for BinaryReaderUtil + + + + + Read a binary stream into a byte array + (Cribbed from posting by Jon Skeet: + http://www.developerfusion.co.uk/show/4696/) + + An open Binary Reader + A byte array with the bytes from the disk + + + + An interface to the configuration settings for the library. + This includes an interface to the .config file. + This is a singleton. + + + + + The singleton + + + + + Empty constructor + + + + + Instantiate the instance of the object (if not created) + and return it. + + the Configuration singleton object + + + + Get the X-Sender header, if any is specified in the .config + file with the key dnom.headers.xsender. + + + + + + Get the default encoding, if any is specified in the .config + file with the key dnom.encoding. + + + + + Get the default charset, if any is specified in the .config + file with the key dnom.charset. + + + + + Get an app setting from the .config file. If none is found + or it is empty or only whitespace, use the defaultvalue. + + The key to search for in the .config file + The default value if the value + is null or only whitespace. + + + + Parse a email address string into an EmailAddress. + * This isn't very mature yet! * + + + + + Constructor + + + + + If the last conversion was unsuccessful, this + contains the error message. If it was successful, + it will be null. + + + + + Parse a raw email address into an EmailAddress object. + If it can't be parsed, return null and set LastError + to the error message. + + + + + + + The DotNetOpenMail Version. + + + + + Empty Constructor + + + + + Get the singleton of this class + + + + + + 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. + + + + + diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/EhloSmtpResponse.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/EhloSmtpResponse.cs new file mode 100644 index 00000000..bc5bc221 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/EhloSmtpResponse.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; +using DotNetOpenMail.SmtpAuth; + +namespace DotNetOpenMail +{ + /// + /// The server response from EHLO + /// + public class EhloSmtpResponse + { + private int _responseCode=0; + private String _message; + + ArrayList smtpAuthTypes=new ArrayList(); + + /// + /// Create an instance of the EhloSmtpResponse class + /// + public EhloSmtpResponse() + { + } + + /// + /// Get the available Auth Types strings + /// as reported by the server. + /// (e.g. "login", etc.) + /// + /// + public String[] GetAvailableAuthTypes() + { + String[] stringArray=new String[smtpAuthTypes.Count]; + smtpAuthTypes.CopyTo(stringArray); + + return stringArray; + //return (SmtpAuthType[]) smtpAuthTypes.ToArray(typeof (SmtpAuthType[])); + } + + /// + /// Add an Auth type (by string as contained in the + /// EHLO authentication. These are converted to lower + /// case. + /// + /// The auth type from EHLO + public void AddAvailableAuthType(String authType) + { + smtpAuthTypes.Add(authType.Trim().ToLower()); + } + + /* + /// + /// Add an Auth type + /// + /// + public void AddAvailableAuthType(SmtpAuthType smtpAuthType) + { + smtpAuthTypes.Add(smtpAuthType); + } + */ + + /// + /// The SMTP Reponse code + /// + public int ResponseCode + { + get { return _responseCode; } + set { _responseCode=value; } + } + + /// + /// The SMTP Message. This will be "OK" if successful, + /// otherwise it will be the part that failed. + /// + public String Message + { + get { return _message; } + set { _message=value; } + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailAddress.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailAddress.cs new file mode 100644 index 00000000..1b26d381 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailAddress.cs @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// 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. + /// + 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 + /// + /// Create an instance of an email address object. + /// + /// The address portion of the email + /// The name portion of the email. + public EmailAddress(String email, String name) + { + if (email!=null) + { + email=email.Trim(); + } + this._email=email; + this._name=name; + } + #endregion + + #region EmailAddress + /// + /// Create an instance of an email address object. + /// + /// The address portion of the email + public EmailAddress(String email) + { + if (email!=null) + { + email=email.Trim(); + } + else + { + email=""; + } + this._email=email; + } + #endregion + + #region EmailAddress + /// + /// Create an character-encoded instance of an email address object. + /// + /// The address portion of the email + /// The name portion of the email. + /// The character set to encode the name portion of the email address. + /// The encoding type to use to encode the name portion of the mail address. + 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 + /// + /// The email address portion of the email address object + /// + public String Email + { + get {return _email;} + } + #endregion + + #region Name + /// + /// The name portion of the email address object + /// + 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 + /// + /// Create the string representation of this email address + /// (encoded or otherwise) as it will appear in the email + /// + /// + 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 + /// + /// Calls ToDataString. + /// + /// + public override String ToString() + { + return ToDataString(); + } + #endregion + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailAddressCollection.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailAddressCollection.cs new file mode 100644 index 00000000..f01f3d51 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailAddressCollection.cs @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A collection of EmailAddress objects. Implements + /// CollectionBase + /// + public class EmailAddressCollection : CollectionBase + { + /// + /// Create a new instance of the EmailAddressCollection + /// + public EmailAddressCollection() + { + } + + #region Add + /// + /// Add an object to the collection + /// + /// The EmailAddress object to add + /// + public int Add( EmailAddress emailaddress ) + { + return( List.Add( emailaddress ) ); + } + #endregion + + #region Add + /// + /// Append a collection of objects to the existing collection + /// + /// The EmailAddressCollection to append to the existing collection. + public void AddCollection( EmailAddressCollection emailaddresses ) + { + foreach (EmailAddress emailaddress in emailaddresses) + { + List.Add(emailaddress); + } + } + #endregion + + #region IndexOf + /// + /// Find the index of the EmailAddress in the collection + /// + /// The object to find. + /// The index, from 0, or -1 if not found. + public int IndexOf( EmailAddress value ) + { + return( List.IndexOf( value ) ); + } + #endregion + + #region Insert + /// + /// Insert an EmailAddress into the collection at the + /// specified index. + /// + /// The index, starting at zero. + /// The email address to add to the collection + public void Insert( int index, EmailAddress emailaddress ) + { + List.Insert( index, emailaddress ); + } + #endregion + + #region Remove + /// + /// Remove an address, if found, from the collection. + /// + /// The EmailAddress to remove + public void Remove( EmailAddress emailaddress ) + { + List.Remove( emailaddress ); + } + #endregion + + #region ToDataString + /// + /// Render the email addresses in a comma-separated list, + /// suitable for being rendered in an email. + /// + /// + 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 + /// + /// Calls ToDataString(). + /// + /// + public override String ToString() + { + return ToDataString(); + } + #endregion + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailMessage.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailMessage.cs new file mode 100644 index 00000000..58e476e1 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/EmailMessage.cs @@ -0,0 +1,675 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An Email Message + /// + 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 + /// + /// Create a new instance of an EmailMessage. + /// + public EmailMessage() + { + _mimeboundary=new MimeBoundary(); + _charset=System.Text.Encoding.GetEncoding(Configuration.GetInstance().GetDefaultEncoding("iso-8859-1")); + _bodytext=GetNoMimeMessage(); + } + #endregion + + #region Subject + /// + /// The subject line or subject header of the + /// email. + /// + public String Subject + { + get {return _subject;} + set {_subject=value;} + } + #endregion + + #region FromAddress + /// + /// 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. + /// + public EmailAddress FromAddress + { + get {return _fromaddress;} + set {_fromaddress=value;} + } + #endregion + + #region EnvelopeFromAddress + /// + /// Normally the FromAddress is used as the + /// envelope-from address, but it can be + /// overridden here, if it is not null. + /// + public EmailAddress EnvelopeFromAddress + { + get {return _envelopefromaddress;} + set {_envelopefromaddress=value;} + } + #endregion + + #region AddToAddress + /// + /// Add a To address to the Headers. This will also + /// be used during the "RCPT TO" SMTP negotiation + /// + /// Email Address object of the recipient + public void AddToAddress(EmailAddress emailaddress) + { + _toaddresses.Add(emailaddress); + } + /// + /// Add a To address to the Headers. This will also + /// be used during the "RCPT TO" SMTP negotiation + /// + /// The plain email address (don't include the name) + public void AddToAddress(String email) + { + _toaddresses.Add(new EmailAddress(email)); + } + #endregion + + #region ToAddresses + /// + /// Retrieve the collection of recipients + /// that will appear in the "To" header of the + /// email. + /// + public EmailAddressCollection ToAddresses + { + get {return _toaddresses;} + } + #endregion + + #region AddCcAddress + /// + /// Add a Cc address to the Headers. This will also + /// be used during the "RCPT TO" SMTP negotiation + /// + /// Email Address object of the recipient + public void AddCcAddress(EmailAddress emailaddress) + { + _ccaddresses.Add(emailaddress); + } + /// + /// Add a Cc address to the Headers. This will also + /// be used during the "RCPT TO" SMTP negotiation + /// + /// The plain email address (don't include the name) + public void AddCcAddress(String email) + { + _ccaddresses.Add(new EmailAddress(email)); + } + #endregion + + #region CcAddresses + /// + /// Retrieve the collection of recipients + /// that will appear in the "Cc" header of the + /// email. + /// + public EmailAddressCollection CcAddresses + { + get {return _ccaddresses;} + } + #endregion + + #region AddBccAddress + /// + /// 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. + /// + /// The EmailAddress object + public void AddBccAddress(EmailAddress emailaddress) + { + _bccaddresses.Add(emailaddress); + } + + /// + /// 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. + /// + /// The plain email address (don't include the name) + public void AddBccAddress(String email) + { + _bccaddresses.Add(new EmailAddress(email)); + } + #endregion + + #region BccAddresses + /// + /// Get the current EmailAddressCollection of BCC addresses + /// + public EmailAddressCollection BccAddresses + { + get {return _bccaddresses;} + } + #endregion + + #region Organization + /// + /// Get/set the organization (as it will appear in the organization + /// header + /// + public String Organization + { + get {return _organization;} + set {_organization=value;} + } + #endregion + + #region XMailer + /// + /// Get the current XMailer setting for the X-Mailer header. + /// + public String XMailer + { + get {return this._xmailer;} + set {this._xmailer=value;} + } + #endregion + + #region AddCustomHeader + /// + /// Add a custom mail header, e.g. "X-MyHeader". + /// + /// The header name (without a colon) + /// The value of the header. This value will not + /// be encoded. + public void AddCustomHeader(String header, String val) + { + _custommessageheaders.Add(new MessageHeader(header, val)); + } + #endregion + + #region HeaderCharSet + /// + /// The charset that is used for encoding the headers + /// + public System.Text.Encoding HeaderCharSet + { + get {return _charset;} + set {_charset=value;} + } + #endregion + + #region HeaderEncoding + /// + /// The mime encoding that is used for encoding the headers + /// + public Encoding.EncodingType HeaderEncoding + { + get {return this._encodingtype;} + set {_encodingtype=value;} + } + #endregion + + #region GetStandardHeaders + /// + /// Get the minimal header set in the specified character, + /// and using the mime encoder provided. + /// + 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 + /// + /// Encode a header value using the current header encoder and charset. + /// + /// The header name + /// The header value + /// + 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 + /// + /// Returns true if there is content that should be "multipart/mixed" + /// + /// true if the content is multipart/mixed. + private bool HasMixedContent() + { + return (_mixedfileattachments.Count > 0); + } + #endregion + + #region HasRelatedContent + /// + /// Returns true if there is content that should be "multipart/related" + /// + /// true if the content is multipart/related. + private bool HasRelatedContent() + { + return (_relatedfileattachments.Count > 0); + } + #endregion + + #region ToDataStringHeaders + /// + /// Encode the headers as they will appear in the email + /// + /// the charset encoding for the string + /// the mime encoding + /// the encoded string + 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 + /// + /// Encode the email body as it will appear in the email + /// + /// the encoded body + 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 + /// + /// format the body text---not implemented yet. + /// + /// + /// + private String FormatBodyText(String text) + { + return text; + } + #endregion + + #region GetNoMimeMessage + private String GetNoMimeMessage() + { + return ARM.GetInstance().GetString("this_is_mime"); + } + #endregion + + /// + /// 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. + /// + public String BodyText + { + get { return _bodytext;} + set { _bodytext=value;} + } + + #region ToDataString + /// + /// Render the encoded message for smtp "DATA" transmission. + /// This is the final version that will get sent to the + /// + /// + public String ToDataString() + { + IEncoder encoder=EncoderFactory.GetEncoder(HeaderEncoding); + return ToDataStringHeaders(this.HeaderCharSet, encoder)+SmtpProxy.ENDOFLINE+ToDataStringBody(); + + } + #endregion + + #region Send + /// + /// 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 + /// + /// The outgoing SMTP server. + /// true if sent successfully. (note that this + /// will not currently return false, but in the future + /// a false value may be used) + 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 + /// + /// Set the content type string in the mime header + /// + public String ContentType + { + get {return _contenttype;} + set {_contenttype=value;} + } + #endregion + + #region TextPart + /// + /// Set the plain text part of the email. This is optional + /// + public TextAttachment TextPart + { + set {_textpart=value;} + get {return _textpart;} + } + #endregion + + #region HtmlPart + /// + /// Set the html part of the email. This is optional + /// + public HtmlAttachment HtmlPart + { + set {_htmlpart=value;} + get {return _htmlpart;} + } + #endregion + + #region AddMixedAttachment + /// + /// Add an attachment which will appear to the user as + /// a separate file. (It is not referred to in the email itself.) + /// + /// The file attachment + public void AddMixedAttachment(FileAttachment fileattachment) + { + _mixedfileattachments.Add(fileattachment); + } + #endregion + + #region AddRelatedAttachment + /// + /// 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. + /// + /// The file attachment + public void AddRelatedAttachment(FileAttachment fileattachment) + { + _relatedfileattachments.Add(fileattachment); + } + #endregion + } +} + + diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/Base64Encoder.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/Base64Encoder.cs new file mode 100644 index 00000000..21f87ca7 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/Base64Encoder.cs @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Encode a file in Base64 Encoding. + /// + /// See: http://www.freesoft.org/CIE/RFC/1521/7.htm + /// + public class Base64Encoder : IEncoder + { + /// + /// The maximum chars per line before end of line char(s) + /// + public static readonly int MAX_CHARS_PER_LINE=76; + + /// + /// The end-of-line character(s) to use + /// + public static readonly String END_OF_LINE="\r\n"; + + #region Base64Encoder + /// + /// Empty Constructor + /// + private Base64Encoder() + { + } + #endregion + + #region GetInstance + /// + /// Create an instance of this class + /// + public static Base64Encoder GetInstance() + { + return new Base64Encoder(); + } + #endregion + + #region Encode + /// + /// 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. + /// + /// Reader for incoming string + /// Writer for outgoing encoded string + /// The character encoding for the encoded string. + 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 + /// + /// Encode the File's data in base64. + /// + /// Reader for incoming string + /// Writer for outgoing encoded string + /// The character set for the encoded string + 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 + /// + /// Encode the File's data in base64. + /// + /// Reader for incoming string + /// Writer for outgoing encoded string + 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 + /// + /// Encode a string in Base64 in a particular characters set + /// + /// The source text + /// the charset for the encoded text + /// Returns an encoded string + 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 + /// + /// Encode header as per RFC 2047: + /// http://www.faqs.org/rfcs/rfc2047.html + /// + /// The header name + /// The header text to be encoded (data only) + /// The charset for the encoded string + /// ignored for this class + /// Returns the encoded string + 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 + /// + /// Chop the text into lines that are smaller + /// than MAX_CHARS_PER_LINE + /// + /// + /// + private String MakeLines(String source) + { + StringBuilder sb=new StringBuilder(); + int pos=0; + for (int i=0; i=Base64Encoder.MAX_CHARS_PER_LINE) + { + sb.Append(Base64Encoder.END_OF_LINE); + pos=0; + } + } + return sb.ToString(); + } + #endregion + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public String ContentTransferEncodingString + { + get {return "base64";} + } + #endregion + + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/DoNothingEncoder.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/DoNothingEncoder.cs new file mode 100644 index 00000000..4a623948 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/DoNothingEncoder.cs @@ -0,0 +1,96 @@ +using System; +using System.Text; +using System.IO; + +namespace DotNetOpenMail.Encoding +{ + /// + /// An encoder that does nothing. (This is essentially + /// what the 7bit and 8bit encodings are; they are just + /// markers, not actual encodings) + /// + public abstract class DoNothingEncoder : IEncoder + { + /// + /// Empty constructor + /// + public DoNothingEncoder() + { + } + + #region Encode + /// + /// Echo the text back unchanged. + /// + /// Reader for the incoming string + /// Writer for the outgoing string + /// The encodigng for the outgoing string (ignored) + 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 + /// + /// Echo the text back unchanged + /// + /// The incoming filestream + /// The outgoing filestream + /// Charset (ignored) + 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 + /// + /// Echo the text back unchanged (good for 7bit text only). + /// + /// The incoming binaryreader + /// The outgoing stream + public void Encode(BinaryReader binaryreader, StringWriter stringwriter) + { + throw new Exception("Binary reader doesn't do anything for this reader"); + //stringwriter.Write(binaryreader.ReadString()); + } + #endregion + + /// + /// Do nothing to the header string + /// + /// The header key + /// The header value + /// The charset to encode in (ignored) + /// (ignored) + /// + public String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding) + { + return val; + } + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public virtual String ContentTransferEncodingString + { + get {throw new ApplicationException("Implement this");} + } + #endregion + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EightBitEncoder.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EightBitEncoder.cs new file mode 100644 index 00000000..9c743a32 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EightBitEncoder.cs @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Denotes 8bit encoding. Note that this doesn't really + /// encode anything; it just specifies that this email is already + /// in 8-bit encoding. + /// + public class EightBitEncoder : DoNothingEncoder + { + #region EightBitEncoder + /// + /// Empty Constructor + /// + private EightBitEncoder() + { + } + #endregion + + #region GetInstance + /// + /// Create the EightBitEncoder object. + /// + public static EightBitEncoder GetInstance() + { + return new EightBitEncoder(); + } + #endregion + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public override String ContentTransferEncodingString + { + get {return "8bit";} + } + #endregion + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EncoderFactory.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EncoderFactory.cs new file mode 100644 index 00000000..aa684f36 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EncoderFactory.cs @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Factory for instantiating the right encoder class, + /// given an encoding + /// + internal class EncoderFactory + { + + /// + /// Empty Constructor. + /// + internal EncoderFactory() + { + } + + /// + /// Method for determining the correct encoder for this + /// encoding type. + /// + /// Enumerated encoding type + /// Returns the proper IEncoder implementation + /// Throws an ApplicationException if the specified encoding is unknown. + 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"); + } + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EncodingType.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EncodingType.cs new file mode 100644 index 00000000..c0c66718 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/EncodingType.cs @@ -0,0 +1,27 @@ +using System; + +namespace DotNetOpenMail.Encoding +{ + /// + /// Enumeration of encoding types. + /// + public enum EncodingType + { + /// + /// The Quoted-Printable encoding + /// + QuotedPrintable, + /// + /// The Base-65 encoding + /// + Base64, + /// + /// The 7Bit encoding marker + /// + SevenBit, + /// + /// The 8Bit encoding marker + /// + EightBit + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/IEncoder.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/IEncoder.cs new file mode 100644 index 00000000..2ef4ceba --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/IEncoder.cs @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An interface for a string encoder + /// + public interface IEncoder + { + + /// + /// Encode from the stringreader to the stringwriter. + /// + /// an open stringreader to the source string + /// where the output is written + /// the outgoing charset + void Encode(StringReader source, StringWriter destination, System.Text.Encoding charset); + + /// + /// Encode the file stream into the stringwriter. + /// + /// an open stream to file to be read + /// where the output is written + /// the outgoing charset + void Encode(FileStream filestream, StringWriter destination, System.Text.Encoding charset); + + /// + /// Encode the binary reader into the stringwriter. + /// + /// an open binary reader for the data to be encoded. + /// where the output is written + void Encode(BinaryReader binaryreader, StringWriter destination); + + + /// + /// Encode the string according to rfc-2047 if some of it + /// falls outside the 7bit ASCII charset. + /// + /// The header key + /// The header value string + /// Charset for the encoded string + /// Force encoding, even if in ascii-only. + /// The encoded string + String EncodeHeaderString(String name, String val, System.Text.Encoding charset, bool forceencoding); + + /// + /// The String that goes in the content transfer encoding header + /// + String ContentTransferEncodingString {get;} + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/QPEncoder.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/QPEncoder.cs new file mode 100644 index 00000000..83dabc34 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/QPEncoder.cs @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// See: http://www.freesoft.org/CIE/RFC/1521/6.htm + /// + public class QPEncoder : IEncoder + { + /// + /// Logger + /// + //private static readonly ILog log = LogManager.GetLogger(typeof(QPEncoder)); + + /// + /// Maximum characters per line, before the end-of-line character + /// + public static readonly int MAX_CHARS_PER_LINE=76; + + /// + /// The end-of-line character(s). + /// + public static readonly String END_OF_LINE="\r\n"; + + + #region QPEncoder + /// + /// Empty Constructor + /// + private QPEncoder() + { + } + #endregion + + #region GetInstance + /// + /// Create an instance of the encoder + /// + /// The instantiated Quoted-printable encoder + public static QPEncoder GetInstance() + { + return new QPEncoder(); + } + #endregion + + #region Encode + /// + /// Encode the incoming stream in quoted-printable encoding. + /// + /// The incoming binary reader + /// The outgoing string writer + public void Encode(BinaryReader binaryreader, StringWriter stringwriter) + { + throw new ApplicationException("Not Implemented Yet; use a base64 encoder instead."); + } + #endregion + + #region Encode + /// + /// Encode the incoming stream in quoted-printable encoding. + /// + /// The incoming file stream + /// The outgoing string writer + /// The charset to write the outgoing string in + 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 + /// + /// 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 + /// + /// The incoming string reader + /// The outgoing stringwriter + /// The outgoing charset for the string + public void Encode(StringReader stringreader, StringWriter stringwriter, System.Text.Encoding charset) + { + Encode(stringreader, stringwriter, charset, false, 0); + } + #endregion + + #region EncodeString + /// + /// Encode the string in quoted printable format + /// + /// The source string + /// The outgoing charset + /// the encoded string + public String EncodeString(String str, System.Text.Encoding charset) + { + return EncodeString(str, charset, false, 0); + } + #endregion + + #region EncodeString + /// + /// Encode the string in quoted printable format + /// + /// The source string + /// The outgoing charset + /// Force encoding, even if not required by qp RFC + /// The total characters outside the encoding. This is used to figure + /// out how long the line will be after encoding. + /// the encoded string + 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 + /// + /// Encode header as per RFC 2047: + /// http://www.faqs.org/rfcs/rfc2047.html + /// + /// + /// This doesn't split long lines yet + /// the header name + /// the string to encode + /// The charset to encode to + /// Force encoding, even if not required by qp RFC + /// the encoded string, suitable for use in a header + 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 + /// + /// Encode a char according to quoted-printable + /// standard + /// + /// the char to encode + /// the encoded char representation + 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 + /// + /// Encode a byte according to quoted-printable + /// standard + /// + /// the byte to encode + /// the encoded byte representation + private String EncodeByte(byte ch) + { + return String.Format("={0:X2}",(int) ch); + } + #endregion + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public String ContentTransferEncodingString + { + get {return "quoted-printable";} + } + #endregion + + #region NeedsEncoding + /// + /// Return true if the char needs to be encoded. + /// + /// + /// + /// + 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 + /// + /// Return true if the byte needs to be encoded. + /// + /// + /// + /// + 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 + /// + /// Return true if the string needs to be encoded. + /// + /// The string to check + /// true if outside 127-bit, or one of the + /// quoted-printable special characters. + internal bool IsNonAscii(String str) + { + for (int i=0; i + /// Check if the character is one of the non-qp + /// characters + /// + /// the character to check + /// true if outside the acceptable qp range + 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 + /// + /// 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. + /// + /// The incoming string reader + /// The outgoing stringwriter + /// The outgoing charset for the string + /// If true, force the encoding of all the + /// These are the number of characters that + /// will appear outside this string, e.g. the header name, etc. + /// characters (not just those that are given in RFC2027). + 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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/SevenBitEncoder.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/SevenBitEncoder.cs new file mode 100644 index 00000000..f83254d0 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Encoding/SevenBitEncoder.cs @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Denotes 7bit encoding. Note that this doesn't really + /// encode anything; it just specifies that this email is already + /// in 7-bit ascii encoding. + /// + public class SevenBitEncoder : DoNothingEncoder + { + /// + /// Empty constructor + /// + private SevenBitEncoder() + { + } + + /// + /// Create an instance of this class. + /// + /// + public static SevenBitEncoder GetInstance() + { + return new SevenBitEncoder(); + } + + + #region ContentTransferEncodingString + /// + /// The String that goes in the content transfer encoding header + /// + public override String ContentTransferEncodingString + { + get {return "7bit";} + } + #endregion + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/FileAttachment.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/FileAttachment.cs new file mode 100644 index 00000000..983dda03 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/FileAttachment.cs @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A mime representation of a file which can be transferred + /// via email. + /// + public class FileAttachment : AbstractEmailAttachment + { + + //private static readonly ILog log = LogManager.GetLogger(typeof(FileAttachment)); + + /// + /// Create a new File attachment from a FileInfo object + /// + /// A fileinfo object which points to a local file. + public FileAttachment(FileInfo fileinfo) : this(fileinfo, null) + { + } + + /// + /// Create a new text file attachment from a StreamReader. + /// + /// An open streamreader + public FileAttachment(StreamReader streamreader) : this(streamreader, null) + { + } + + /// + /// Create a new binary file attachment from a BinaryReader. + /// + /// An open binaryreader + public FileAttachment(BinaryReader binaryreader) : this(binaryreader, null) + { + } + + /// + /// Create a new binary file attachment from an array of bytes. + /// + /// An array of bytes + public FileAttachment(byte[] bytes) : this(bytes, null) + { + } + + /// + /// Create a new file attachment from a String. + /// + /// The contents of the file + public FileAttachment(String content) : this(content, null) + { + } + + #region FileAttachment + /// + /// 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. + /// + /// A fileinfo object which points to a local file. + /// the content id value + 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 + /// + /// 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. + /// + /// An open streamreader + /// the content id value + 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 + /// + /// 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. + /// + /// An open binary readerr + /// the content id value + 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 + /// + /// 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. + /// + /// An array of bytes + /// the content id value + 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 + + /// + /// 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. + /// + /// The contents of the file + /// the content id value + 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; + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/GenericSmtpNegotiator.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/GenericSmtpNegotiator.cs new file mode 100644 index 00000000..9be40ec4 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/GenericSmtpNegotiator.cs @@ -0,0 +1,279 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; + +using log4net; + +namespace DotNetOpenMail +{ + /// + /// Perform the low-level interaction with the external + /// SMTP server + /// + 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 + + /// + /// Create an instance of the GenericSmtpNegotiator + /// + /// + public GenericSmtpNegotiator(IPEndPoint ipEndPoint) + { + this._ipEndPoint=ipEndPoint; + this.ReceiveTimeout=_timeout; + } + + #region Open + /// + /// Connect to the server and return the initial + /// welcome string. Throw a MailException if we + /// can't connect. + /// + /// + 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 + /// + /// Send the HELO string. + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Send the MAIL FROM command + /// Throw a MailException if we can't connect. + /// + /// The Envelope-From address + /// the SMTP response + 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 + /// + /// Send the MAIL FROM command + /// Throw a MailException if we can't connect. + /// + /// A recipient's address + /// the SMTP response + 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 + /// + /// Send the DATA string (without the data) + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Send the message content string + /// Throw a MailException if we can't + /// connect. + /// + /// the SMTP response + 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 + /// + /// Write a string to the current connection. + /// + /// + 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 + /// + /// Send the QUIT command + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/HtmlAttachment.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/HtmlAttachment.cs new file mode 100644 index 00000000..440b789c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/HtmlAttachment.cs @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An HTML email attachment + /// + public class HtmlAttachment : AbstractEmailAttachment + { + + /// + /// 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. + /// + /// The HTML content of the attachment + 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; + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/IEmailStringable.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/IEmailStringable.cs new file mode 100644 index 00000000..1e84605d --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/IEmailStringable.cs @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Objects of a class which implements this interface + /// can be converted to a string which can be used in + /// an email. + /// + internal interface IEmailStringable + { + String ToDataString(); + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/ISendableMessage.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/ISendableMessage.cs new file mode 100644 index 00000000..be852484 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/ISendableMessage.cs @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A message which can be sent. + /// + internal interface ISendableMessage : IEmailStringable + { + bool Send(SmtpServer smtpserver); + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/ISmtpProxy.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/ISmtpProxy.cs new file mode 100644 index 00000000..8d5b7595 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/ISmtpProxy.cs @@ -0,0 +1,95 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; + +//using log4net; + +namespace DotNetOpenMail +{ + /// + /// Interact directly with the SMTP server. + /// + public interface ISmtpProxy + { + /// + /// Open the connection + /// + /// The SMTP response + SmtpResponse Open(); + + /// + /// Send the HELO command + /// + /// + /// + SmtpResponse Helo(String localHostName); + + /// + /// Send the EHLO command + /// + /// + /// + EhloSmtpResponse Ehlo(String localHostName); + + /// + /// Send the MAIL FROM command + /// + /// + /// + SmtpResponse MailFrom(EmailAddress mailfrom); + + /// + /// Send one RCPT TO command + /// + /// + /// + SmtpResponse RcptTo(EmailAddress rcptto); + + /// + /// Send the DATA command + /// + /// + SmtpResponse Data(); + + /// + /// Write the message content + /// + /// + SmtpResponse WriteData(String str); + + /// + /// Send the QUIT message to the server + /// + /// + SmtpResponse Quit(); + + /// + /// Close the connection + /// + /// The SMTP response + void Close(); + + /// + /// Send the AUTH command + /// + /// the SMTP response + SmtpResponse Auth(String authtype); + + /// + /// Send any old string to the proxy + /// + /// the SMTP response + SmtpResponse SendString(String str); + + /// + /// Turn the SMTP Conversation Capture off/on. + /// If on, GetSmtpConversation will contain the + /// most recent conversation. + /// + /// the on/off value + bool CaptureSmtpConversation {get; set;} + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Logging/LogMessage.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Logging/LogMessage.cs new file mode 100644 index 00000000..b1a41ac2 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Logging/LogMessage.cs @@ -0,0 +1,44 @@ +using System; + +namespace DotNetOpenMail.Logging +{ + /// + /// Summary description for LogMessage. + /// + public class LogMessage + { + private Object _sender=null; + private String _message=null; + + /// + /// The log message + /// + public String Message + { + get {return _message;} + set {_message=value;} + } + + /// + /// The sender object + /// + public Object Sender + { + get {return _sender;} + set {_sender=value;} + } + + + /// + /// Log a message + /// + /// The object logging the message + /// The message to be logged + public LogMessage(Object sender, String message) + { + this._sender=sender; + this._message=message; + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Logging/Logger.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Logging/Logger.cs new file mode 100644 index 00000000..04ca0113 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Logging/Logger.cs @@ -0,0 +1,77 @@ +using System; + +namespace DotNetOpenMail.Logging +{ + /// + /// Summary description for Logger. + /// + public class Logger + { + /// + /// Log handler delegate + /// + public delegate void LogHandler(LogMessage logMessage); + + /// + /// Log event + /// + //public event LogHandler LogEvent; + + private static Logger _logger=new Logger(); + + private Logger() + { + } + + /// + /// Return the singleton object + /// + /// + public static Logger GetInstance() + { + return _logger; + } + + /// + /// Log a message with level "Info" + /// + /// + public void LogInfo(String message) + { + + } + + /// + /// Log a message with level "Debug" + /// + public void LogDebug(String message) + { + + } + + /// + /// Log a message with level "Error" + /// + public void LogError(String message) + { + + } + + /// + /// Log the output of sending smtp + /// + public void LogWriteSMTP(String message) + { + } + + /// + /// Log the reply via smtp + /// + /// + public void LogReceiveSMTP(String message) + { + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/MailException.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/MailException.cs new file mode 100644 index 00000000..e29dfed4 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/MailException.cs @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// General Mail Exception, including network errors, + /// connection errors, and configuration errors. + /// + public class MailException : Exception + { + /// + /// Create an instance of a MailException + /// + public MailException() : base() + { + } + /// + /// Create an instance of a MailException + /// + /// The message describing the exception + public MailException(string message) : base(message) + { + } + + /// + /// Create an instance of a MailException + /// + /// The message describing the exception + /// The inner exception + public MailException(string message, Exception inner) : base(message, inner) + { + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/MessageHeader.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/MessageHeader.cs new file mode 100644 index 00000000..861bc1e2 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/MessageHeader.cs @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// This represents one of the message headers as it + /// appears in the email. + /// + public class MessageHeader : IEmailStringable + { + private String _name; + private String _value; + private String _encodedvalue=null; + + /// + /// Create a new instance of a MessageHeader + /// + /// The header name (without a colon) + /// The unencoded value + public MessageHeader(string name, String value) + { + this._name=name; + this._value=value; + } + + /// + /// Create a new instance of a MessageHeader, with a mime-encoded + /// value. + /// + /// The header name (without a colon) + /// The non-encoded header value + /// The mime-encoded value + public MessageHeader(string name, String value, String encodedvalue) + { + this._name=name; + this._value=value; + this._encodedvalue=encodedvalue; + } + + /// + /// The name of the header. + /// + public String Name + { + get {return this._name;} + } + + /// + /// The unencoded value of the header + /// + public String Value + { + get {return this._value;} + } + + /// + /// The mime-encoded value of the header + /// + public String EncodedValue + { + get {return this._encodedvalue;} + } + + /// + /// The string representation of the header, as it will + /// appear in the email. + /// + /// + public String ToDataString() + { + if (_encodedvalue!=null) + { + return Name+": "+EncodedValue+SmtpProxy.ENDOFLINE; + } + else + { + return Name+": "+Value+SmtpProxy.ENDOFLINE; + } + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/MessageHeaderCollection.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/MessageHeaderCollection.cs new file mode 100644 index 00000000..23284074 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/MessageHeaderCollection.cs @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A collection of MessageHeader objects + /// Implements the CollectionBase interface. + /// + public class MessageHeaderCollection : CollectionBase, IEmailStringable + { + /// + /// Initializes a new instance of the ArrayList class. + /// + public MessageHeaderCollection() + { + } + + #region Add + /// + /// Adds an object to the end of the MessageHeaderCollection + /// + /// The Object to be added to the end of the MessageHeaderCollection. + /// The value can be a null reference (Nothing in Visual Basic). + /// The MessageHeaderCollection index at which the value has been added. + public int Add( MessageHeader MessageHeader ) + { + return( List.Add( MessageHeader ) ); + } + #endregion + + #region IndexOf + /// + /// Returns the zero-based index of the first occurrence of a + /// value in the MessageHeaderCollection or in a portion of it. + /// + /// The Object to locate in the MessageHeaderCollection. The value + /// can be a null reference (Nothing in Visual Basic). + /// + public int IndexOf( MessageHeader value ) + { + return( List.IndexOf( value ) ); + } + #endregion + + #region Insert + /// + /// Inserts an element into the MessageHeaderCollection at + /// the specified index. + /// + /// The zero-based index at which value should be inserted + /// The MessageHeader to insert. + /// The value can be a null reference (Nothing in Visual Basic). + public void Insert( int index, MessageHeader MessageHeader ) + { + List.Insert( index, MessageHeader ); + } + #endregion + + #region Remove + /// + /// Removes the first occurrence of a + /// specific MessageHeader from the MessageHeaderCollection. + /// + /// The object to remove from the MessageHeaderCollection + public void Remove( MessageHeader MessageHeader ) + { + List.Remove( MessageHeader ); + } + #endregion + + #region ToDataString + /// + /// Write the MessageHeaderCollection to a string that can be + /// included in an email. + /// + /// The String as it will appear in the resulting email. + public String ToDataString() + { + StringBuilder sb=new StringBuilder(""); + foreach (MessageHeader messageheader in List) + { + sb.Append(messageheader.ToDataString()); + } + return sb.ToString(); + } + #endregion + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/MimeBoundary.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/MimeBoundary.cs new file mode 100644 index 00000000..a3438839 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/MimeBoundary.cs @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A boundary which delimits a MIME object. + /// + 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 + * + * 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 +{ + /// + /// A MIME container for content or other mime containers. + /// + 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(); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/RFC2822Date.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/RFC2822Date.cs new file mode 100644 index 00000000..6e4d403d --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/RFC2822Date.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Create a RFC 2822-compliant date. + /// + /// See section 3.3 in + /// http://ftp.rfc-editor.org/in-notes/rfc2822.txt + /// + public class RFC2822Date + { + private DateTime _datetime; + private TimeZone _timezone; + + /// + /// Create an instance of the RFC 2822 date object. + /// + /// The date to convert + /// The timezone to use in the conversion + public RFC2822Date(DateTime datetime, TimeZone timezone) + { + this._datetime=datetime; + this._timezone=timezone; + } + + /// + /// Generate the date string + /// + /// A RFC-2822 error code + 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); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/RawEmailMessage.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/RawEmailMessage.cs new file mode 100644 index 00000000..52de51a1 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/RawEmailMessage.cs @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A full, preformatted email message, including headers + /// + public class RawEmailMessage : ISendableMessage + { + private String _content=null; + private EmailAddressCollection _rcpttoaddresses=new EmailAddressCollection(); + private EmailAddress _mailfrom=null; + + /// + /// Create an instance of the RawEmailMessage + /// + public RawEmailMessage() + { + } + + #region Content + /// + /// The raw content of the email + /// + public String Content + { + get { return _content; } + set { _content = value; } + } + #endregion + + #region MailFrom + /// + /// The address to use in the envelope-from + /// SMTP negotiation + /// + public EmailAddress MailFrom + { + get { return _mailfrom; } + set { _mailfrom = value; } + } + #endregion + + #region RcptToAddresses + /// + /// The recipient addresses + /// + public EmailAddressCollection RcptToAddresses + { + get { return _rcpttoaddresses; } + } + #endregion + + #region AddRcptToAddress + /// + /// Add a recipient to the EmailAddressCollection + /// of recipients + /// + /// + public void AddRcptToAddress(EmailAddress emailaddress) + { + _rcpttoaddresses.Add(emailaddress); + } + #endregion + + #region Send + /// + /// Send the email via the specified SMTP server + /// + /// The SMTP server to use + /// true if the email was sent + 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 + /// + /// Render the message for smtp "DATA" transmission. + /// + /// The rendered String, which in this + /// case is the content itself, untouched. + public String ToDataString() + { + return _content; + } + #endregion + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Resources/ARM.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Resources/ARM.cs new file mode 100644 index 00000000..73f8c323 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Resources/ARM.cs @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// ARM= Assembly Resource Manager. Manage the strings for the + /// various CultureInfo types. + /// + public sealed class ARM + { + /// + /// The singleton object + /// + private static ARM _theinstance=new ARM(); + /// + /// The namespace of the resource files + /// + private string _pathname="DotNetOpenMail.Resources.DotNetOpenMail"; + /// + /// The singleton System.Resources.ResourceManager. + /// + private ResourceManager _resources=null; + + /// + /// Create the singleton + /// + private ARM() + { + _resources=new ResourceManager(_pathname, typeof(ARM).Assembly); + } + + /// + /// Get the instance of the class + /// + /// the ARM instance + public static ARM GetInstance() + { + return _theinstance; + } + + /// + /// Get an object from the file + /// + /// The key + /// The key lookup for the default culture + public object GetObject(string name) + { + return GetObject(null, name); + } + + /// + /// Get an object for the specified CultureInfo + /// + /// The specified culture for the resource + /// The key for the resource + /// returns an object, if one is found, else null + public object GetObject(CultureInfo culture, string name) + { + if (_resources != null) + { + return _resources.GetObject(name, culture); + } + return null; + } + + /// + /// Get a string for the specified CultureInfo for the + /// default culture + /// + /// The key for the resource + /// returns a string, if one is found, else null + public string GetString(string name) + { + return GetString(null, name, null); + } + + /// + /// Get a string for the specified CultureInfo for the + /// default culture. If not found, return defaultvalue + /// + /// The key for the resource + /// The value to return if there + /// is no value found. + /// returns a string, if one is found, else defaultvalue + public string GetString(string name, string defaultvalue) + { + return GetString(null, name, defaultvalue); + } + + /// + /// Get a string for the specified CultureInfo for the + /// current culture. If not found, return null + /// + /// The culture of the resulting string + /// The key for the resource + /// returns a string, if one is found, else + /// null + public string GetString(CultureInfo culture, string name) + { + return GetString(culture, name, null); + } + + /// + /// Get a string for the specified CultureInfo for the + /// default culture. If not found, return defaultvalue + /// + /// The culture of the resulting string + /// The key for the resource + /// The value to return if there + /// is no value found. + /// returns a string, if one is found, else defaultvalue + 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"); + } + + /// + /// Retrieve the entire resource set for this culture. + /// + /// The culture to examine + /// The resource set, if any. + public ResourceSet GetResourceSet(CultureInfo culture) + { + return _resources.GetResourceSet(culture, false, false); + } + + } +} + diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Resources/DotNetOpenMail.resx b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Resources/DotNetOpenMail.resx new file mode 100644 index 00000000..a07c4de5 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Resources/DotNetOpenMail.resx @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.0.0.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + (no subject) + + + This is a multi-part message in MIME format + + + Unrecognized authentication type + + + Please include a MAIL FROM address. + + \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs new file mode 100644 index 00000000..f2199419 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/ISmtpAuthToken.cs @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 description for ISmtpAuthenticationToken. + /// + public interface ISmtpAuthToken + { + + /// + /// The user's login + /// + String UserName + { + get; set; + } + + /// + /// The user's password + /// + String Password + { + get; set; + } + + /// + /// Negotiate AUTH with the SmtpProxy. + /// + /// + SmtpResponse Negotiate(ISmtpProxy smtpProxy, String[] supportedAuthTypes); + + } + +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/LoginAuthToken.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/LoginAuthToken.cs new file mode 100644 index 00000000..aec23d38 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/LoginAuthToken.cs @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A LOCAL SMTP AUTH token + /// + 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"); + + /// + /// Create a new instance of the LOCAL SMTP + /// AUTH token + /// + public LoginAuthToken(String userName, String password) + { + this._userName=userName; + this._password=password; + } + + /// + /// The User's password + /// + public String Password + { + get {return _password;} + set {_password=value;} + } + + /// + /// The User's login + /// + public String UserName + { + get {return _userName;} + set {_userName=value;} + } + + /* + /// + /// Return true if this is among the supported AUTH + /// types. + /// + /// + /// + public bool IsSupported(SmtpAuthType[] authtypes) + { + log.Debug("CHECKING SUPPORTED TYPES"); + for (int i=0; i + /// the supported auth types + /// + 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; + } + + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthFactory.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthFactory.cs new file mode 100644 index 00000000..c945650a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthFactory.cs @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 description for SmtpAuthHelper. + /// + internal class SmtpAuthFactory + { + //private static readonly ILog log = LogManager.GetLogger(typeof(SmtpAuthFactory)); + + internal SmtpAuthFactory() + { + } + + /// + /// Get the Auth type from the SMTP EHLO response. + /// If it is unrecognized or unimplemented, + /// return null. Case doesn't matter. + /// + /// The string as returned in EHLO negotiation. + /// The user's login + /// The User's password + 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; + } + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs new file mode 100644 index 00000000..d4b80468 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthToken.cs @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Token which will negotiate an authentication type + /// with the server. + /// + 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"); + + /// + /// Create a new instance of the LOCAL SMTP + /// AUTH token + /// + public SmtpAuthToken(String userName, String password) + { + this._userName=userName; + this._password=password; + } + + /// + /// The User's password + /// + public String Password + { + get {return _password;} + set {_password=value;} + } + + /// + /// The User's login + /// + public String UserName + { + get {return _userName;} + set {_userName=value;} + } + + /// + /// Return the 235 response code if valid, otherwise + /// return the error. + /// + /// The SmtpProxy being used + /// String array of EHLO-specified auth types + /// + 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); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthType.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthType.cs new file mode 100644 index 00000000..207e1715 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpAuth/SmtpAuthType.cs @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Enumeration of SMTP Authentication + /// types. + /// + public enum SmtpAuthType + { + /// + /// UNKNOWN SMTP AUTH TYPE + /// + Unknown=0, + + /// + /// LOGIN SMTP AUTH + /// + Login=1 + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpException.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpException.cs new file mode 100644 index 00000000..c36d3d98 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpException.cs @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An SmtpException represents an SMTP response + /// code and an error message. Network and connection + /// errors are represented by a MailException instead. + /// + public class SmtpException : Exception + { + private int _errorcode; + + /// + /// Create a new instance of the SmtpException + /// + /// The SMTP error code + public SmtpException(int errorcode) + { + this._errorcode=errorcode; + } + + /// + /// Create a new instance of the SmtpException + /// + /// The SMTP error code + /// The SMTP error message + public SmtpException(int errorcode, string message) : base(message) + { + this._errorcode=errorcode; + } + + /// + /// Create a new instance of the SmtpException + /// + /// The SMTP error code + /// The SMTP error message + /// The inner exception + public SmtpException(int errorcode, string message, Exception inner) : base(message, inner) + { + this._errorcode=errorcode; + } + + /// + /// The SMTP error code. + /// + public int ErrorCode + { + get {return _errorcode;} + set {_errorcode=value;} + } + + /// + /// Convert to a string + /// + /// + public override string ToString() + { + return _errorcode+" "+this.Message; + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpProxy.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpProxy.cs new file mode 100644 index 00000000..eacaa439 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpProxy.cs @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A proxy to access an SMTP server. This drives + /// the protocol interaction. + /// + 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 + /// + /// Get an instance of the SMTP Proxy + /// + /// + /// + public static SmtpProxy GetInstance(SmtpServer smtpserver) + { + return new SmtpProxy(smtpserver); + } + #endregion + + #region Open + /// + /// Connect to the server and return the initial + /// welcome string. Throw a MailException if we + /// can't connect. + /// + /// + 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 + /// + /// Send the HELO string. + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Send the EHLO string. + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Send the MAIL FROM command + /// Throw a MailException if we can't connect. + /// + /// The Envelope-From address + /// the SMTP response + 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 + /// + /// Send the MAIL FROM command + /// Throw a MailException if we can't connect. + /// + /// A recipient's address + /// the SMTP response + 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 + /// + /// Send the DATA string (without the data) + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Send the message content string + /// Throw a MailException if we can't + /// connect. + /// + /// the SMTP response + 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 + /// + /// Parse the response from the EHLO into an + /// EhloSmtpResponse. Returns 250 "OK" if successful. + /// + /// + 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 + /// + /// Send the AUTH command + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + public SmtpResponse Auth(String authtype) + { + if (!_isConnected) + { + throw new MailException("The connection is closed."); + } + Write("AUTH "+authtype+SmtpProxy.ENDOFLINE); + return ReadSmtpResponse(); + } + #endregion + + #region SendString + /// + /// Send any old string to the proxy + /// + /// the SMTP response + public SmtpResponse SendString(String str) + { + if (!_isConnected) + { + throw new MailException("The connection is closed."); + } + Write(str+SmtpProxy.ENDOFLINE); + return ReadSmtpResponse(); + } + #endregion + + #region Write + /// + /// Write a string to the current connection. + /// + /// + 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 + /// + /// Send the QUIT command + /// Throw a MailException if we can't connect. + /// + /// the SMTP response + 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 + /// + /// Set this to "true" if you want to capture the SMTP negotiation. + /// Once the conversation has finished, use "GetConversation" to + /// view it. + /// + 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 + */ + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpResponse.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpResponse.cs new file mode 100644 index 00000000..4f02ce3b --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpResponse.cs @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// The response from the SMTP server + /// + public class SmtpResponse + { + private int _responseCode; + private String _message; + + /// + /// Create an instance of the SmtpResponse + /// + /// + /// + public SmtpResponse(int responseCode, String message) + { + this._responseCode=responseCode; + this._message=message; + } + + /// + /// The SMTP Reponse code + /// + public int ResponseCode + { + get { return _responseCode; } + } + + /// + /// The SMTP Response String + /// + + public String Message + { + get { return _message; } + } + + /// + /// Was the response a fatal error? + /// + public bool IsFatalError + { + get { + return (this._responseCode>=500 && this._responseCode <= 599); + } + } + + /// + /// Was the response an OK message? + /// + public bool IsOk + { + get + { + return (this._responseCode>=200 && this._responseCode <= 299); + } + } + + /// + /// Convert this response to an exception + /// + /// The SmtpException corresponding to this response + public SmtpException GetException() + { + return new SmtpException(this._responseCode, this._message); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpResponseCode.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpResponseCode.cs new file mode 100644 index 00000000..1952e51a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpResponseCode.cs @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// SMTP server response codes and their meanings. + /// + public enum SmtpResponseCode: int + { + /// + /// System status, or system help reply. + /// + SystemStatus = 211, + /// + /// Help message. + /// + Help = 214, + /// + /// Domain service ready. Ready to start TLS. + /// + HeloReply = 220, + /// + /// Domain service closing transmission channel. + /// + Quit = 221, + /// + /// Authentication successfully completed. + /// + AuthSuccessful = 235, + /// + /// OK, queuing for node node started. Requested mail action completed. + /// + Ok = 250, + /// + /// OK, no messages waiting for node node. User not local, will forward to forwardpath. + /// + OkWillForward = 251, + /// + /// 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. + /// + OkWithoutVerify = 252, + /// + /// OK, messages pending messages for node node started. + /// + OkMsgStarted = 253, + /// + /// Start mail input, end with CRLF.CRLF + /// + StartMailInput = 354, + /// + /// Octet-offset is the transaction offset. + /// + TransactionOffset = 355, + /// + /// Domain service not available, closing transmission channel. + /// + ServiceNotAvailable = 421, + /// + /// A password transition is needed. + /// + PasswordNeeded = 432, + /// + /// Requested mail action not taken: mailbox unavailable. + /// + MailboxBusy = 450, + /// + /// Requested action aborted: local error in processing. Unable to process ATRN request now. + /// + ErrorProcessing = 451, + /// + /// Requested action not taken: insufficient system storage. + /// + InsufficientStorage = 452, + /// + /// You have no mail. + /// + NoMail = 453, + /// + /// TLS not available. Encryption required for requested authentication mechanism. + /// + TlsNotAvailable = 454, + /// + /// Unable to queue messages for node node. + /// + NoMsgQueue = 458, + /// + /// Node node not allowed: reason. + /// + NodeNotAllowed = 459, + /// + /// Command not recognized: command. Syntax error. + /// + UnknownCmd = 500, + /// + /// Syntax error, no parameters allowed. + /// + SyntaxError = 501, + /// + /// Command not implemented. + /// + CmdNotImplemented = 502, + /// + /// Bad sequence of commands. + /// + BadSequence = 503, + /// + /// Command parameter not implemented. + /// + ParamNotImplemented = 504, + /// + /// Security error. + /// + SecurityError = 505, + /// + /// Machine does not accept mail. + /// + MailNotAccepted = 521, + /// + /// Must issue a STARTTLS command first. Encryption required for requested authentication mechanism. + /// + StartTLSneeded = 530, + /// + /// Authentication mechanism is too weak. + /// + AuthTooWeak = 534, + /// + /// Encryption required for requested authentication mechanism. + /// + EncryptionRequired = 538, + /// + /// Requested action not taken: mailbox unavailable. + /// + ActionNotTaken = 550, + /// + /// User not local, please try forward path. + /// + NotLocalPleaseForward = 551, + /// + /// Requested mail action aborted: exceeded storage allocation. + /// + ExceedStorageAllowance = 552, + /// + /// Requested action not taken: mailbox name not allowed. + /// + MailboxNameNotAllowed = 553, + /// + /// Transaction failed. + /// + TransactionFailed = 554 + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpServer.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpServer.cs new file mode 100644 index 00000000..ae449cd0 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/SmtpServer.cs @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A description of an SMTP server. + /// + public class SmtpServer + { + //public delegate void SmtpDataMessagePresendHandler(object sender, MyEventArgs e); + + /// + /// Logging delegate + /// + public delegate void LogHandler(LogMessage logMessage); + + /// + /// Handle a message about to be sent + /// + public event LogHandler LogSmtpWrite; + + /// + /// Handle a message received + /// + public event LogHandler LogSmtpReceive; + + /// + /// Log that the conversation has completed + /// + 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 + /// + /// Create a new SMTP server at this hostname and + /// port. + /// + /// The address or hostname of the smtp server + /// The port of the smtp server. + public SmtpServer(String hostname, int port) + { + _id=hostname+":"+port; + _hostname=hostname; + _port=port; + } + #endregion + + #region SmtpServer + /// + /// Create a new SMTP server at this hostname and + /// port. + /// + /// The address or hostname of the smtp server + public SmtpServer(String hostname) + { + _id=hostname+":"+_port; + _hostname=hostname; + } + #endregion + + #region SmtpServer + /// + /// Create a new SMTP server at this hostname and + /// port. + /// + /// The ip address of the SMTP server + /// The port number of SMTP server + public SmtpServer(IPAddress ipaddress, int port) + { + _id=ipaddress.ToString()+":"+port; + _ipaddress=ipaddress; + _port=port; + } + #endregion + + #region GetIPEndPoint + /// + /// Get the end point for the SMTP server. The IPEndpoint will + /// be saved for later to prevent multiple hostname lookups. + /// + /// SmtpException is thrown if the host doesn't resolve. + /// returns an IPEndPoint for the SMTPServer. + 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 + /// + /// The timeout waiting for an SMTP command, in + /// milliseconds + /// + public int ServerTimeout + { + get {return _serverTimeout;} + set {_serverTimeout=value;} + } + #endregion + + #region GetSmtpProxy + /// + /// Get an instance of an SmtpProxy + /// + /// + 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 + /// + /// Figure out whether we need EHLO or not. + /// Currently, this is only for SMTP AUTH + /// + /// + private bool UseEhlo() + { + if (this._authToken!=null) + { + return true; + } + else + { + return false; + } + } + #endregion + + #region Send + /// + /// Send the email. + /// + /// The completed message + /// A list of email addresses which + /// are to be used in the RCPT TO SMTP communication + /// An email address for the MAIL FROM + /// part of the SMTP protocol. + /// throws an SmtpException if there + /// is an unexpected SMTP error number sent from the server. + /// throws a MailException if there + /// is a network problem, connection problem, or other issue. + /// + 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 + /// + /// Override the SmtpProxy. This is only + /// for testing smtp negotiation without an + /// smtp server. + /// + /// + public void OverrideSmtpProxy(ISmtpProxy smtpProxy) + { + _smtpProxy=smtpProxy; + } + #endregion + + #region SmtpAuthToken + /// + /// Get or set the SMTP AUTH token for the server. + /// + public ISmtpAuthToken SmtpAuthToken + { + get {return _authToken;} + set {_authToken = value;} + } + #endregion + + #region CaptureSmtpConversation + /// + /// 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. + /// + [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 + /// + /// Append this string to the conversation log. + /// + /// the string from the SMTP conversation + internal void AppendConversation(String str) + { + this._smtpConversation.Append(str); + } + #endregion + + #region GetSmtpConversation + /// + /// If CaptureSmtpConversation is true, a Send() will + /// be captured, and will be accessible here. + /// + /// The SMTP Conversation or null. + [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 + /// + /// The server hostname + /// + public String Hostname + { + get {return _hostname;} + } + #endregion + + #region Port + /// + /// The server port + /// + public int Port + { + get {return _port;} + } + #endregion + + /// + /// Return the host name, a colon, and a port number. + /// + /// + public override string ToString() + { + return Hostname+":"+Port; + } + + /// + /// Set the hostname used by the HELO + /// command. + /// + public String HeloHost + { + get + { + return _helohost; + } + set + { + _helohost=value; + } + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/TextAttachment.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/TextAttachment.cs new file mode 100644 index 00000000..d80a7bbe --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/TextAttachment.cs @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// A mime representation of plain-text content. + /// + public class TextAttachment : AbstractEmailAttachment + { + + //private IEncoder _encoder=null; + //private String _mimetype="text/plain"; + /// + /// 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. + /// + /// + 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; + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/BinaryStreamUtil.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/BinaryStreamUtil.cs new file mode 100644 index 00000000..cb3d2c7c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/BinaryStreamUtil.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; + +namespace DotNetOpenMail.Utils +{ + /// + /// Something take a binary reader's data into a byte array. + /// + public class BinaryReaderUtil + { + /// + /// Constructor for BinaryReaderUtil + /// + public BinaryReaderUtil() + { + } + + /// + /// Read a binary stream into a byte array + /// (Cribbed from posting by Jon Skeet: + /// http://www.developerfusion.co.uk/show/4696/) + /// + /// An open Binary Reader + /// A byte array with the bytes from the disk + 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; + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/Configuration.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/Configuration.cs new file mode 100644 index 00000000..0d022450 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/Configuration.cs @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// An interface to the configuration settings for the library. + /// This includes an interface to the .config file. + /// This is a singleton. + /// + public class Configuration + { + /// + /// The singleton + /// + private static Configuration _theinstance=new Configuration(); + + /// + /// Empty constructor + /// + private Configuration() + { + + } + + /// + /// Instantiate the instance of the object (if not created) + /// and return it. + /// + /// the Configuration singleton object + public static Configuration GetInstance() + { + return _theinstance; + } + + /// + /// Get the X-Sender header, if any is specified in the .config + /// file with the key dnom.headers.xsender. + /// + /// + public String GetXSender() + { + return System.Configuration.ConfigurationSettings.AppSettings["dnom.headers.xsender"]; + } + + /// + /// Get the default encoding, if any is specified in the .config + /// file with the key dnom.encoding. + /// + public String GetDefaultEncoding(String def) + { + return GetAppSetting("dnom.encoding", def); + } + + /// + /// Get the default charset, if any is specified in the .config + /// file with the key dnom.charset. + /// + public System.Text.Encoding GetDefaultCharset() + { + String encodingstr=GetAppSetting("dnom.encoding", "iso-8859-1"); + return System.Text.Encoding.GetEncoding(encodingstr); + } + + /// + /// Get an app setting from the .config file. If none is found + /// or it is empty or only whitespace, use the defaultvalue. + /// + /// The key to search for in the .config file + /// The default value if the value + /// is null or only whitespace. + private String GetAppSetting(String key, String defaultvalue) + { + String tmp=System.Configuration.ConfigurationSettings.AppSettings[key]; + if (tmp==null || tmp.Trim()=="") + { + return defaultvalue; + } + else + { + return tmp; + } + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/EmailAddressParser.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/EmailAddressParser.cs new file mode 100644 index 00000000..e34c3927 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/EmailAddressParser.cs @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// Parse a email address string into an EmailAddress. + /// * This isn't very mature yet! * + /// + public class EmailAddressParser + { + private String _lastError=null; + + /// + /// Constructor + /// + public EmailAddressParser() + { + } + + /// + /// If the last conversion was unsuccessful, this + /// contains the error message. If it was successful, + /// it will be null. + /// + public String LastError + { + get {return _lastError;} + } + + /// + /// Parse a raw email address into an EmailAddress object. + /// If it can't be parsed, return null and set LastError + /// to the error message. + /// + /// + /// + public EmailAddress ParseRawEmailAddress(String rawemailaddress) + { + // see: http://www.twilightsoul.com/Default.aspx?PageContentID=10&tabid=134 + String regex=@"^((?([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+[\t\x20]*|"""+ + @"[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*"")+)?[\t\x20]*"+ + @"<(?([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+"+ + @"(\.[!#-'\*\+\-/-9=\?A-Z\^-~]+)*|""[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*""))"+ + @"@(?(([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]*|"+ + @"(?([\t\x20]*[!#-'\*\+\-/-9=\?A-Z\^-~]+(\.[!#-'\*\+\"+ + @"-/-9=\?A-Z\^-~]+)*|"+ + @"""[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*""))"+ + @"@(?(([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); + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/VersionInfo.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/VersionInfo.cs new file mode 100644 index 00000000..c63704ed --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/Utils/VersionInfo.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 +{ + /// + /// The DotNetOpenMail Version. + /// + 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 + + /// + /// Empty Constructor + /// + private VersionInfo() + { + } + + /// + /// Get the singleton of this class + /// + /// + public static VersionInfo GetInstance() + { + return new VersionInfo(); + } + + /// + /// 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. + /// + /// + public override String ToString() + { + return String.Format("{0}.{1}.{2}{3}", majorid, minorid, incidentalid, status); + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000000000000000000000000000000000000..bad13403928964139b78dd32a8b809b619c9bd8a GIT binary patch literal 6306 zcmeHL?@k*>5Vyf>FoYD-ln`jrOPjVyWKMR${FC^QVBA^_6xkN7ge|hZTbm7cx7O|+ z;3A%-Pf+y{+nKX{fFZO}eG(shmdERv-I>|h*}dOREFO!+{)PvC@p(7`#NOeS6iPI- zxzCkPowD|AF3c_Ay22~wx6{TxlZp#(Gn+Fr_(>aEzN3A~Ha+HRNu9K@=hq!>{mj}G zam>8UdSatTIk9(pD zt%L0GHCaJ8Hq7@qGAmRznGT1Q{kmd$7nG=%yy*$a@~lB26h%*I@bA*Qj^a0Wcj~C? zbbZ2aSMlry|LQ2ifq5$3=VqQuW@#ZgQ`0S5Q(0zIT1R_SAF1hPA7ip5MFS#)vzn2t z$(5Gv%K=H4m}VHlc~EpU7+0*!_K9|c$B&tOaXUNDRm-7mG}u3|n`jH2fqPO|OerDX zg7;j*oFL`8LzrFiJubDPnWeMr<`sE&5{?A)%b(Q9<+)8$RX_;l#)@$jz{J5vCMiGbFV8eRP)y3n( z6pbQ_!rc^w@_U|B1KvQx1dSqxh6y^T7iTSwI5;^9WFncs<`@!y1F_@-An-GeB#C4K z$s~{o@(^f@OaXa!Ug{#JjWPh~Qz}_C1iMvpce@f|$n?pwxsvVy&@R~AKD!`~K#$CC zR7DGMty|3tz033t?u0D`dpaBHIqkgW;G-3WlZ z@#<`C<#jcjhS3crfZZ!0552q|{3^Oy?SZbq?mQT&M_?qxgpvhz7NWJ2rD8A<{~R8G P|5hj;9)Mv1vo`q;$t5G_ literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DotNetOpenMail.csproj.CoreCompileInputs.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DotNetOpenMail.csproj.CoreCompileInputs.cache new file mode 100644 index 00000000..14d3550d --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DotNetOpenMail.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +d719a02e33b93cf9a4829e28dcc008bccccbdb23 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DotNetOpenMail.csprojAssemblyReference.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/DotNetOpenMail.csprojAssemblyReference.cache new file mode 100644 index 0000000000000000000000000000000000000000..c4445478cbfd1e08703bc818573f2315b1330786 GIT binary patch literal 15454 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 H8QuQ_zTDlU literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 00000000..e69de29b diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 00000000..e69de29b diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 00000000..e69de29b diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/DesignTimeResolveAssemblyReferences.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/DesignTimeResolveAssemblyReferences.cache new file mode 100644 index 0000000000000000000000000000000000000000..a9752730eb29d59bd61f2783381eea448c30fbae GIT binary patch literal 670 zcmaJfgc5Z(Bzj>{oGfP;}Z6g67e3MmCCLSQwbDxgB5o-EMD9)p#&x7t~UwzvL8 zeg_g9dT)19C?FzM+P7a%GjHB3>oLZz?Vy#$J;%a_H+7*Es><+}T`fyK7q~>8DGkH; z1T@yFoup%)@`NYDIP0Y8G)!9Pj23bjA9o8`7e{bDS4(Ioi)2)dt0z^Omg7W>gipyH zY|b$|M+42w2m{3GSG9!o$-RI3WK~EBg|QNlzY_S_h=l}F-FGc`1plROSwi$$iE=6m zqx9C#dcsUKr$U1sP|!@3aIDp;E}YvlU@*B4h{1nCmj%-wrqBI{X#u;Relz z|HS|HZvQzI8$~3(?-BSG2DGDxAh7T;dzM>CpR{P=sdWY8owNPDNBMiGKto$V`~ndg z>pWn7XKp^VeE6dDGUsm(=D$y?$9ykuuuxjo3tmb&ppPTIK=>|f9Pwo0_{{SV~*qWSU>Dh!`P4Smse+B!`s@UAhcJJ)s^s3 JGD@Ga?Hin}#4i8< literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000000000000000000000000000000000000..81a983599c35a9136992f0c9365fd66fd40dfb3f GIT binary patch literal 6310 zcmeHLZBH9V5VpZwFoYD-ln`jrYn!%7WKMR$yh(gWFiuelMYcsNVT-Kq#%9Cat+l(y zOA)`Nzo6<*Y-i3dfFZO}eG(shmdERv-I>|h*}Z2c7LUbZf8#^H^gJ9w;%swU3MJ~= z+T$ulP&Q;6%uyj;PFP zD0_TORuHa(^L3hetmbRmbzBg zC;WC5&u;Lqjxt@Gr_w!c=D7r03&}xEHXY4m37E7GcbPs^lZ_t6cvFfxMu=uLC85EU zmS>j(k~lF96vA0lbTt@PtW5WawuR4+Kz@BYJI__qWoKltcVIiw=2`=HrLaLMA>W|) zT;rTD<=R8QDF(jg9<+z_YHCGE%>)XHPzMP5=Sk!>|}b#;{?;V#7#> z;_~|m%eegTW4CKb zOYS$)rl)KnU0%D~V~hWJi!Cp+oSj?Bt}ZM>W@WXSzRQn$>S`2msP;Fk_gq~(K1k6h zvZ%Y8qELR%bE?l9Xpo>$*xWq5Fdm^EonNbn zCgEDIk{5ah^fu#eyZH+W=kBt<{r$}ygr(zO+3i*k!$LG}Y6nBls*cwA###+cM zWLJ}4;Q!cIiULeuW15I{!hO#%o?ts+Ij(EWge^FQ6s-X*fkD9kU}LR*24EtCbGy3hmCKky->sx~Nb>XlE{3J9(yAXy;3` zQ;lvuv{cW~1dGnZZ=OptNl*?9ULJ#&M_;c={l;G5iFSb3Q%{W?DE>Q)9vrvoB`EnT z(LDujULOZ{L#h;g@){dO-uHX)`;3(LtD~dI=XmOMo)m!)s+}2MAt^<0fy{nDJrn0ec0%xj z%2pS~OJu$OpJ1)V{VrHb5e6d^YP>=c#X1|WQSp8R2~=Pi9p!t0kWR literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 00000000..e69de29b diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 00000000..e69de29b diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMail/obj/Release/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 00000000..e69de29b diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests.dll.config.demo b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests.dll.config.demo new file mode 100644 index 00000000..a71c3341 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests.dll.config.demo @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests.dll.log4net b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests.dll.log4net new file mode 100644 index 00000000..3633f7a5 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests.dll.log4net @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/AssemblyInfo.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/AssemblyInfo.cs new file mode 100644 index 00000000..aa653dd1 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/AssemblyInfo.cs @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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\. 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("")] diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/DotNetOpenMailTests.csproj b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/DotNetOpenMailTests.csproj new file mode 100644 index 00000000..7b07f33a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/DotNetOpenMailTests.csproj @@ -0,0 +1,183 @@ + + + + Local + 7.10.3077 + 2.0 + {74F3DCD7-1325-4968-B466-38618A380CE9} + Debug + AnyCPU + + + DotNetOpenMailTests + + JScript + Grid + IE50 + false + Library + DotNetOpenMailTests + OnBuildSuccess + + + + v2.0 + + + 0.0 + + + bin\Debug\ + false + 285212672 + false + + DEBUG;TRACE + + true + 4096 + false + + false + false + false + false + 4 + full + prompt + + + bin\Release\ + false + 285212672 + false + + TRACE + + false + 4096 + false + + true + false + false + false + 4 + none + prompt + + + + DotNetOpenMail + {6FBB299F-81A1-49EA-B00A-E916F8F797B3} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + log4net + ..\lib\log4net.dll + + + nmock + ..\lib\nmock.dll + + + nunit.framework + ..\lib\nunit.framework.dll + + + System + + + System.Data + + + System.Web + + + System.XML + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + + + copy "$(SolutionDir)DotNetOpenMailTests.dll.*" "$(ProjectDir)$(OutDir)" + + \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/DotNetOpenMailTests.csproj.user b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/DotNetOpenMailTests.csproj.user new file mode 100644 index 00000000..36c2d068 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/DotNetOpenMailTests.csproj.user @@ -0,0 +1,44 @@ + + + + 7.10.3077 + Debug + AnyCPU + C:\Visual Studio Projects\DotNetOpenMail\lib\ + + + 0 + ShowAllFiles + 0 + + + false + false + false + false + false + + Project + + + + + + false + + + false + false + false + false + false + + Project + + + + + + true + + \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailAddressTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailAddressTests.cs new file mode 100644 index 00000000..2ba9034e --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailAddressTests.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 ",emailaddress.ToString()); + + emailaddress=new EmailAddress("test@test.com", "Last, First"); + Assert.AreEqual("\"Last, First\" ",emailaddress.ToString()); + + emailaddress=new EmailAddress("test@test.com", ""); + Assert.AreEqual("\"\" ",emailaddress.ToString()); + + emailaddress=new EmailAddress("test@test.com", "[First Last]"); + Assert.AreEqual("\"[First Last]\" ",emailaddress.ToString()); + + emailaddress=new EmailAddress("test@test.com", "(First Last)"); + Assert.AreEqual("\"(First Last)\" ",emailaddress.ToString()); + emailaddress=new EmailAddress("test@test.com", "First \"NickName\" Last"); + Assert.AreEqual("\"First \\\"NickName\\\" Last\" ",emailaddress.ToString()); + + + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailMessageInAlternateEncodings.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailMessageInAlternateEncodings.cs new file mode 100644 index 00000000..aa5594f6 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailMessageInAlternateEncodings.cs @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("æ±äº¬ã€æ—¥æœ¬èªž"); + //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("=1B$BEl5~!\"F|K\\8l=1B(B")==0) + { + //=67=71=4E=AC=30=01=65=E5=67=2C=8A=9E + + 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("æ±äº¬ã€æ—¥æœ¬èªž"); + + 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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailMessageTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailMessageTests.cs new file mode 100644 index 00000000..0f4ab50a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/EmailMessageTests.cs @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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 + + + } +} + diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/Base64EncoderTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/Base64EncoderTests.cs new file mode 100644 index 00000000..59a8cc49 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/Base64EncoderTests.cs @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/EightBitEncoderTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/EightBitEncoderTests.cs new file mode 100644 index 00000000..74021f35 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/EightBitEncoderTests.cs @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/QPEncoderTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/QPEncoderTests.cs new file mode 100644 index 00000000..84a6deb0 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/QPEncoderTests.cs @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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()); + + } + */ + } +} + diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/SevenBitEncoderTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/SevenBitEncoderTests.cs new file mode 100644 index 00000000..5db67a4a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Encoding/SevenBitEncoderTests.cs @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/ExampleTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/ExampleTests.cs new file mode 100644 index 00000000..01877b3c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/ExampleTests.cs @@ -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(""+ + "

Just checking up on where you were last night.

\r\n"+ + "

Send me a note!

\r\n\r\n"+ + "

-Charles

"); + + 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(""+ + "

Note to self: look at this photo again in 30 years.

"+ + "

\"Hawthorne

"+ + "

-Marcel

"); + + 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("

I regret that something "+ + "has come up unexpectedly,\r\n"+ + "and I must postpone our meeting.

\r\n"+ + "

Please read the 20 pages of my thoughts on this in the attached\r\n"+ + "PDF file.

\r\n

-Marcel

"); + + FileAttachment fileattachment=new FileAttachment(new FileInfo(@"..\..\TestFiles\grover.jpg")); + + fileattachment.ContentType="image/jpeg"; + + emailmessage.AddMixedAttachment(fileattachment); + + emailmessage.Send(TestAddressHelper.GetSmtpServer()); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/FileAttachmentTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/FileAttachmentTests.cs new file mode 100644 index 00000000..050ce945 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/FileAttachmentTests.cs @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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(""+ + "

This is a license.

\r\n"+ + "

We will spend your money on a new plasma TV.

\r\n"+ + ""); + + 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(""+ + "

This a jpeg.

\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(""+ + "

This is a license.

\r\n"+ + "

We will spend your money on a new plasma TV.

\r\n"+ + ""); + + 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(""+ + "

This a zip file.

\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); + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/FileAttachmentTests2.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/FileAttachmentTests2.cs new file mode 100644 index 00000000..81f223bb --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/FileAttachmentTests2.cs @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("

This is a PDF File

\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 + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Log4netLogger.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Log4netLogger.cs new file mode 100644 index 00000000..b1ee920a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Log4netLogger.cs @@ -0,0 +1,26 @@ +using System; + +using DotNetOpenMail.Logging; + +using log4net; + +namespace DotNetOpenMailTests +{ + /// + /// Summary description for Log4netLogger. + /// + 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); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/QuickTest.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/QuickTest.cs new file mode 100644 index 00000000..30167596 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/QuickTest.cs @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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", ""); + + 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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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); + + + + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RFC2822DateTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RFC2822DateTests.cs new file mode 100644 index 00000000..b936f2b9 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RFC2822DateTests.cs @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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()); + + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RawEmailMessageTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RawEmailMessageTests.cs new file mode 100644 index 00000000..e09fde2c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RawEmailMessageTests.cs @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 description for RawEmailMessageTests. + /// + [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); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Resources/ARMTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Resources/ARMTests.cs new file mode 100644 index 00000000..1ba7f7be --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Resources/ARMTests.cs @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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() { + + } + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RussianTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RussianTests.cs new file mode 100644 index 00000000..7735d713 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/RussianTests.cs @@ -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); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/LocalAuthTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/LocalAuthTests.cs new file mode 100644 index 00000000..26ae7400 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/LocalAuthTests.cs @@ -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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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 + + + + } +} + diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/MockedSlowProxy.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/MockedSlowProxy.cs new file mode 100644 index 00000000..92709724 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/MockedSlowProxy.cs @@ -0,0 +1,33 @@ +using System; +using System.Net.Sockets; + +using DotNetOpenMail; +using DotNetOpenMail.SmtpAuth; + +namespace DotNetOpenMailTests.SmtpAuth +{ + /// + /// Summary description for MockedSlowServer. + /// + 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"); + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/MockedSmtpProxy.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/MockedSmtpProxy.cs new file mode 100644 index 00000000..d929fd2a --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpAuth/MockedSmtpProxy.cs @@ -0,0 +1,94 @@ +using System; + +using DotNetOpenMail; +using DotNetOpenMail.SmtpAuth; +using DotNetOpenMail.Encoding; + +namespace DotNetOpenMailTests.SmtpAuth +{ + /// + /// Summary description for MockedSmtpProxy. + /// + 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 + } + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpProxyTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpProxyTests.cs new file mode 100644 index 00000000..079834da --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpProxyTests.cs @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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("This
\r\nis the
\r\nHTML
\r\npart."); + 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("This
\r\n..is the
\r\n..HTML
\r\npart."); + emailmessage.Send(_smtpserver); + + // this doesn't test anything yet + //log.Debug("MESSAGE: "+emailmessage.ToDataString()); + + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpServerTests/SmtpServerTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpServerTests/SmtpServerTests.cs new file mode 100644 index 00000000..b7cf9f95 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/SmtpServerTests/SmtpServerTests.cs @@ -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("This
\r\nis the
\r\nHTML
\r\npart."); + + 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); + + + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestAddressHelper.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestAddressHelper.cs new file mode 100644 index 00000000..bc482156 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestAddressHelper.cs @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005 Mike Bridge + * + * 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 description for TestAddressHelper. + /// + 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); + } + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/ImportedEmail.txt b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/ImportedEmail.txt new file mode 100644 index 00000000..d8780114 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/ImportedEmail.txt @@ -0,0 +1,4 @@ +Subject: This is a test +To: mike@bridgecanada.com + +This is a test. diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/acrobattestpage.pdf b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/acrobattestpage.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b903b117efd1b245c7cd47c947305cad2116ae00 GIT binary patch literal 20016 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 literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/grover.jpg b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/TestFiles/grover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..19d8bd527060d487735ed5fdefa7a35a35135b9d GIT binary patch literal 5881 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 literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Utils/EmailAddressParserTests.cs b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Utils/EmailAddressParserTests.cs new file mode 100644 index 00000000..a213815c --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/Utils/EmailAddressParserTests.cs @@ -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); + + + } + + + } +} diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000000000000000000000000000000000000..c764de35b08e5a46c7c35d15602b55564a71fc0a GIT binary patch literal 6662 zcmeHMZBrXJ5VpZ67?Kpzln`hVr%hibHCG#OAxxQ0f+1yEC}X>j8IB>kJJ|^CP98~z zaT$I~e?g}|vE4ntfkQ~4_6#3voDFVEp+rd= z+gt_IE$G1E!dMZWC;au?YAU(Sq~gL~&SZ@={-u&DfvW?_mVFjzN!?U(E3jN{|H5iT zam4&(D?L}rmKI8xjFU~%IXZ+U7e8R>b--N*?XCNoNm1F6v{GTx$WyuQR|2gbf$}5j zx}wUQS4uI@a%-z6n)&FJx(BmYgkR$2HSV$roB9rSsAkQX*sG>Xf$OeG>anVjN6n!k zwP5VQg|Ri^IJ6QPpZS! zr#|GDLp*-3|GZYxg>@?3;bx9YW@{liQ)3lJQ(0hC+6P-yAE>c%N5^PIiV{Q!S2ZqK znJX=8ZG|{2OfwAO6abwM#yKk!9YY(!=SNIFySzKcRmG(>G}x)wNVMs?;+7OPQ%cBJ z;62x{CP=x43Ul&-uerw>DxFC6D5=Rnu{)Rbl(q$ljJtuf(@H_T^}+s3aDtaq8+-7BWRiP)xYz_uut?`B(5 z3tDo&oJxAi7SiQb`;5*1=OebTK(luChs?{ld6r&$xtF@ik6Y?$FXFJ*-LT$rxM;MW zqP@tX)@kYm_$|+=E+3$Ng7zYZ`U%>t2j^ZCd2oCX#7I1b%^?&(2O{x1AmD2lMI6Nl zict_F&Cuih7;8b%< zrl=sV^~{{mn@n#|?lzjg!2tf8NgG*X(V9`x?ieWo7gVOO4$U01f-*=2473O=DbJK} zk6Vw-x zKO?5a{bp*0+1*U(aPyylfuF8x0JyX1it@bAbO`bkK$cdP%pLAKqN>`b5cAe-okFvn znr4%Ohx$p-U%rVGz9;OX5aJm?ytxrX;B#%1nlGs#*ca%}_14pP8_7{kLx?W{V(~^0 zcqE^L_K!Ex-eFc~|En7#y!Bi}h~e$HPa^sxqN}gV-R9uoV{ISG6rLK|SNsn)ybn(q ztWd$o-?4s;;3E~o50*1}k@wx+{4T#S?d}Z^$G?WVUh_&I8O0hZ`38h>z58(jNo=V6 zEi__lP}qzjp$%E?c`H$5xbO8Qkn-Y{K-!B~*eHRy`G$G z6y8(^XEpH&PEw#Ue)==_HJ0PBPPYyR>5R-k|I}&m^2%fFj2JN94f6dx;M_aS(<(AV ztW2JfG<0oV_c2~4?M+%!=i_bClR%msZbSwe*WJaCLWAC&aLW(|uff0ix0a9nGopWM KX%&h0M*jtm`j}S$ literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DotNetOpenMailTests.csproj.CoreCompileInputs.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DotNetOpenMailTests.csproj.CoreCompileInputs.cache new file mode 100644 index 00000000..b58bf621 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DotNetOpenMailTests.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +51b0e06c1af78da847e0503301cde828d69da0c0 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DotNetOpenMailTests.csprojAssemblyReference.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Debug/DotNetOpenMailTests.csprojAssemblyReference.cache new file mode 100644 index 0000000000000000000000000000000000000000..472214b51c916004369b7f688a21f07c52d1b504 GIT binary patch literal 22500 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 O4~gE*rBx{29sU=TW||KG literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csproj.CoreCompileInputs.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csproj.CoreCompileInputs.cache new file mode 100644 index 00000000..66de98e4 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +7b33b7ee5ed005a1612e241c08a61ea170258f0b diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csproj.FileListAbsolute.txt b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csproj.FileListAbsolute.txt new file mode 100644 index 00000000..c654e208 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csproj.FileListAbsolute.txt @@ -0,0 +1,2 @@ +D:\opensim\DotNetMail\DotNetOpenMail-0.5.8b-src\DotNetOpenMailTests\obj\Release\DotNetOpenMailTests.csprojAssemblyReference.cache +D:\opensim\DotNetMail\DotNetOpenMail-0.5.8b-src\DotNetOpenMailTests\obj\Release\DotNetOpenMailTests.csproj.CoreCompileInputs.cache diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csprojAssemblyReference.cache b/DotNetOpenMail-0.5.8b/DotNetOpenMailTests/obj/Release/DotNetOpenMailTests.csprojAssemblyReference.cache new file mode 100644 index 0000000000000000000000000000000000000000..4960b9771609ae61126e882d31a726d47b569c07 GIT binary patch literal 33615 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 literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/DotNetOpenMail_MSDN.ndoc b/DotNetOpenMail-0.5.8b/DotNetOpenMail_MSDN.ndoc new file mode 100644 index 00000000..0f5c4c1e --- /dev/null +++ b/DotNetOpenMail-0.5.8b/DotNetOpenMail_MSDN.ndoc @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/LICENSE.txt b/DotNetOpenMail-0.5.8b/LICENSE.txt new file mode 100644 index 00000000..12e082dd --- /dev/null +++ b/DotNetOpenMail-0.5.8b/LICENSE.txt @@ -0,0 +1,25 @@ +Copyright (c) 2005 Mike Bridge + +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. \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/README.txt b/DotNetOpenMail-0.5.8b/README.txt new file mode 100644 index 00000000..c962d60b --- /dev/null +++ b/DotNetOpenMail-0.5.8b/README.txt @@ -0,0 +1,24 @@ +DotNetOpenMail README + +INTRODUCTION +------------------------------------------------ + +DotNetOpenMail is a Microsoft .Net library which can be +used to create html and text emails with file attachments +and embedded images. You need an SMTP server and +your own .Net program to make use of it. + +See http://dotnetopenmail.sourceforge.net/ for the +latest downloads and discussion groups. + + +QUICK START +------------------------------------------------ + +1) Copy the DotNetOpenMail.dll and log4net dlls into + a directory where your project can access it +2) Create a Reference to it from within your project +3) Try some examples from the web site: + + http://dotnetopenmail.sourceforge.net/examples.html + diff --git a/DotNetOpenMail-0.5.8b/README_NUNIT.txt b/DotNetOpenMail-0.5.8b/README_NUNIT.txt new file mode 100644 index 00000000..9b88ec10 --- /dev/null +++ b/DotNetOpenMail-0.5.8b/README_NUNIT.txt @@ -0,0 +1,17 @@ +NOTES ON RUNNING THE NUNIT TESTS +-------------------------------------------------- + +The NUnit tests are currently set up to be compiled +from Visual Studio. You can get NUnit 2.2 from +http://www.nunit.org. + +In order for the tests to work, you will need to create +a file named DotNetOpenMailTests.dll.config (you can copy the +DotNetOpenMailTests.dll.config.demo file and edit it). +This file contains a default smtp server and To and From +addresses for testing. + +Note that the files DotNetOpenMailTests.dll.config and +DotNetOpenMailTests.dll.log4net are copied by the build +process into the directory where the test assembly +DotNetOpenMailTests.dll is deployed. \ No newline at end of file diff --git a/DotNetOpenMail-0.5.8b/UpgradeLog.htm b/DotNetOpenMail-0.5.8b/UpgradeLog.htm new file mode 100644 index 0000000000000000000000000000000000000000..e54ee0af2d2e3cee5e23e73c93b46db2eea5a5d1 GIT binary patch literal 96484 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 YA6wA$@mFlw0v@=fTH!hEUGOCNe=xYGJOBUy literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/lib/log4net.dll b/DotNetOpenMail-0.5.8b/lib/log4net.dll new file mode 100644 index 0000000000000000000000000000000000000000..7740fbd94dacd556c9c3351d47d5e3c8f2da88e6 GIT binary patch literal 266240 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 z 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 TfmIBwVqg^ms~GqXiGlwInG1CK literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/lib/nmock.dll b/DotNetOpenMail-0.5.8b/lib/nmock.dll new file mode 100644 index 0000000000000000000000000000000000000000..d5f0d22d39448d0c1bb929f3e1eedd3a244d6514 GIT binary patch literal 40960 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 literal 0 HcmV?d00001 diff --git a/DotNetOpenMail-0.5.8b/lib/nunit.framework.dll b/DotNetOpenMail-0.5.8b/lib/nunit.framework.dll new file mode 100644 index 0000000000000000000000000000000000000000..220a58a9e13bad5323617edf097dd34dd55eb3ac GIT binary patch literal 28672 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 amVsIZY8j|ypq7DJ25K3oW#Ip22L2nBo6=zb literal 0 HcmV?d00001