├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── OpaqueMail.CertHelper ├── CertHelper.cs ├── OpaqueMail.CertHelper.csproj ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── OpaqueMail.Proxy ├── EnumsAndStructs.cs ├── IMAP │ └── ImapProxy.cs ├── OpaqueMail.Proxy.csproj ├── POP3 │ └── Pop3Proxy.cs ├── Properties │ └── AssemblyInfo.cs ├── ProxyBase.cs ├── ProxyFunctions.cs ├── SMTP │ └── SmtpProxy.cs └── packages.config ├── OpaqueMail.ProxyService ├── App.config ├── OpaqueMail.ProxyService.csproj ├── OpaqueMail32.ico ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── ProxyService.Designer.cs ├── ProxyService.cs └── packages.config ├── OpaqueMail.ProxySettings ├── App.config ├── Form1.Designer.cs ├── Form1.Save.cs ├── Form1.cs ├── Form1.resx ├── OpaqueMail.Proxy.Sample.xml ├── OpaqueMail.ProxySettings.csproj ├── OpaqueMail32.ico ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Signature.Resources │ ├── OpaqueMail.htm │ ├── OpaqueMail.rtf │ ├── OpaqueMail.txt │ ├── colorschememapping.xml │ ├── filelist.xml │ └── themedata.thmx ├── Windows8Mail.cs ├── app.manifest └── packages.config ├── OpaqueMail.TestClient ├── App.config ├── Form1.Designer.cs ├── Form1.cs ├── Form1.resx ├── OpaqueMail.TestClient.csproj ├── OpaqueMail32.ico ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings └── packages.config ├── OpaqueMail.doxygen ├── OpaqueMail.doxygen.header.html ├── OpaqueMail.nupkg ├── OpaqueMail.sln ├── OpaqueMail ├── AlternateView.cs ├── Attachment.cs ├── Constants.cs ├── EnumsAndSupport.cs ├── Functions.cs ├── Imap │ ├── ImapClient.Properties.cs │ ├── ImapClient.Synchronous.cs │ └── ImapClient.cs ├── LockAsync.cs ├── MailAddress.cs ├── MailMessage.Pgp.cs ├── MailMessage.Smime.cs ├── MailMessage.cs ├── Mailbox.cs ├── MimePart.cs ├── OpaqueMail.csproj ├── Pgp.cs ├── Pop3 │ └── Pop3Client.cs ├── Properties │ └── AssemblyInfo.cs ├── Smtp │ ├── SmtpClient.Smime.cs │ └── SmtpClient.cs ├── TnefEncoding.cs └── packages.config ├── README.md └── packages └── repositories.config /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | *.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.pfx 193 | *.publishsettings 194 | node_modules/ 195 | orleans.codegen.cs 196 | 197 | # Since there are multiple workflows, uncomment next line to ignore bower_components 198 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 199 | #bower_components/ 200 | 201 | # RIA/Silverlight projects 202 | Generated_Code/ 203 | 204 | # Backup & report files from converting an old project file 205 | # to a newer Visual Studio version. Backup files are not needed, 206 | # because we have git ;-) 207 | _UpgradeReport_Files/ 208 | Backup*/ 209 | UpgradeLog*.XML 210 | UpgradeLog*.htm 211 | 212 | # SQL Server files 213 | *.mdf 214 | *.ldf 215 | 216 | # Business Intelligence projects 217 | *.rdl.data 218 | *.bim.layout 219 | *.bim_*.settings 220 | 221 | # Microsoft Fakes 222 | FakesAssemblies/ 223 | 224 | # GhostDoc plugin setting file 225 | *.GhostDoc.xml 226 | 227 | # Node.js Tools for Visual Studio 228 | .ntvs_analysis.dat 229 | 230 | # Visual Studio 6 build log 231 | *.plg 232 | 233 | # Visual Studio 6 workspace options file 234 | *.opt 235 | 236 | # Visual Studio LightSwitch build output 237 | **/*.HTMLClient/GeneratedArtifacts 238 | **/*.DesktopClient/GeneratedArtifacts 239 | **/*.DesktopClient/ModelManifest.xml 240 | **/*.Server/GeneratedArtifacts 241 | **/*.Server/ModelManifest.xml 242 | _Pvt_Extensions 243 | 244 | # Paket dependency manager 245 | .paket/paket.exe 246 | paket-files/ 247 | 248 | # FAKE - F# Make 249 | .fake/ 250 | 251 | # JetBrains Rider 252 | .idea/ 253 | *.sln.iml 254 | 255 | # CodeRush 256 | .cr/ 257 | 258 | # Python Tools for Visual Studio (PTVS) 259 | __pycache__/ 260 | *.pyc 261 | 262 | # ========================= 263 | # OpaqueMail settings 264 | # ========================= 265 | OpaqueMail.TestClient.exe.config -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### Changelog ### 2 | 3 | 2.5.4 - 2017-05-19 4 | * Fixed processing of messages with the string "UID" in their subjects. 5 | * Fixed handling of case-sensitive boundary names. 6 | 7 | 2.5.3 - 2017-03-30 8 | * Ensured that the last text/html MIME part is considered the body (in the case of multiple text/html MIME parts). 9 | 10 | 2.5.2 - 2017-03-22 11 | * Added fix in POP3 `GetMessagesAsync()` method for servers that return blank lines for UIDL command. 12 | 13 | 2.5.1 - 2017-03-16 14 | * Fixed alternate view MIME wrapping. 15 | * In SmtpProxy, eliminated unneeded certificate generation when messages aren't signed. 16 | 17 | 2.5.0 - 2017-02-27 18 | * Cleaned up a few edge cases based on static code analysis. 19 | 20 | 2.4.4 - 2017-02-16 21 | * Removed UID variants of `Pop3Client.DeleteMessage`, as deletion only works based on index. 22 | 23 | 2.4.3 - 2017-01-09 24 | * Fixed bug when headers contained high-byte characters after the 78th index. 25 | 26 | 2.4.2 - 2017-01-08 27 | * Updated `ImapClient.GetMessagePartialHelper` to deal with situations where the body length is shorter than what is reported. 28 | 29 | 2.4.1 - 2016-12-23 30 | * Added `Functions.GetCertificateByThumbprint` helper method. 31 | 32 | 2.3.4 - 2016-12-18 33 | * Added `GetMessagePartial()`. 34 | * Fixed StartTLS. 35 | 36 | 2.3.3 - 2016-12-14 37 | * Minor safeguards for null headers. 38 | 39 | 2.3.2 - 2016-12-10 40 | * Fixed issues with MIME when content types aren't defined. 41 | 42 | 2.3.1 - 2016-11-25 43 | * Fixed private scoping for pgpEncypted and pgpSigned. 44 | 45 | 2.3.0 - 2016-11-24 46 | * Fixed SMTP handling of attachments. 47 | * Added connection timeouts. 48 | * Fixed "PEEK" behavior for headers-only reads. 49 | 50 | 2.2.6 - 2016-08-28 51 | * 2.26 Added ability to specify supported SSL protocols. 52 | * Fixed occasional POP3 error. 53 | 54 | 2.2.5 - 2016-04-16 55 | * Removed unused variables. 56 | * Fixed message size calculation when attachments are present. 57 | 58 | 2.2.4 - 2015-11-26 59 | * Signed assembly with a strong name. 60 | * Simplified handling of malformed quoted-printable encodings. 61 | 62 | 2.2.3 - 2015-06-14 63 | * Improved SMTP server compatibility by forcing "EHLO" after TLS negotation. 64 | 65 | 2.2.2 - 2015-06-14 66 | * Added PGP "sign then encrypt". 67 | * Improved PGP function overloads. 68 | 69 | 2.2.1 - 2015-06-13 70 | * Added PGP signing and encryption. 71 | 72 | 2.2.0 - 2015-06-08 73 | * Added initial PGP support through BouncyCastle (decryption and signature verification). 74 | 75 | 2.1.0 - 2015-05-24 76 | * Quoted-printable encoding fixes. 77 | 78 | 2.0.0 - 2014-11-28 79 | * Combined `MailMessage` and `ReadOnlyMailMessage` into one class. 80 | 81 | 1.6.5 - 2014-01-19 82 | * Fixed bug related to signature verification. 83 | * Fixed bug with character decoding. 84 | * Improved IMAP IDLE. 85 | 86 | 1.6.4.2 - 2013-12-30 87 | * Made ReadData and SendCommand methods public. 88 | 89 | 1.5.8.2 - 2013-10-17 90 | * Fixed TNEF parsing bug. 91 | 92 | 1.5.7 - 2013-08-22 93 | * Added DeleteMessage() method for ImapClient. 94 | * Cleaned up code documentation. 95 | 96 | 1.5.6 - 2013-08-21 97 | * Added proxy support for Opera Mail. 98 | 99 | 1.5.5 - 2013-08-20 100 | * Standardized namespace to OpaqueMail.Net and OpaqueMail.Proxy. 101 | 102 | 1.5.4 - 2013-08-16 103 | * Added optional export of proxied messages. 104 | * Made self-signed certificates more conformant. 105 | 106 | 1.5.3 - 2013-08-15 107 | * Added Windows Live Mail support. 108 | 109 | 1.4.2 - 2013-08-13 110 | * Added Thunderbird configuration wizard. 111 | 112 | 1.3.2 - 2013-08-07 113 | * Added MULTIAPPEND and QRESYNC. 114 | * Slightly improved performance. 115 | 116 | 1.3.1 - 2013-08-06 117 | * Allowed the SMTP proxy to remove and/or replace existing S/MIME operations on outbound messages. 118 | 119 | 1.3.0 - 2013-08-06 120 | * Made performance improvements. 121 | * Added IMAP events. 122 | * Improved async support. 123 | 124 | 1.0.0 - 2013-07-04 125 | * Initial release. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bertjohnson/OpaqueMail/63d55f213a0dd6cf91ddd44e00b63526b083ac17/LICENSE.md -------------------------------------------------------------------------------- /OpaqueMail.CertHelper/OpaqueMail.CertHelper.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE} 8 | Library 9 | Properties 10 | OpaqueMail.CertHelper 11 | OpaqueMail.CertHelper 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | true 34 | 35 | 36 | OpaqueMail.pfx 37 | 38 | 39 | 40 | ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll 41 | True 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 67 | -------------------------------------------------------------------------------- /OpaqueMail.CertHelper/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Reflection; 17 | using System.Runtime.CompilerServices; 18 | using System.Runtime.InteropServices; 19 | 20 | // General Information about an assembly is controlled through the following 21 | // set of attributes. Change these attribute values to modify the information 22 | // associated with an assembly. 23 | [assembly: AssemblyTitle("OpaqueMail.CertHelper")] 24 | [assembly: AssemblyDescription(".NET helper library for interacting with X509 certificates.")] 25 | [assembly: AssemblyConfiguration("")] 26 | [assembly: AssemblyCompany("Bert Johnson")] 27 | [assembly: AssemblyProduct("OpaqueMail")] 28 | [assembly: AssemblyCopyright("Copyright © 2013-2017 Bert Johnson")] 29 | [assembly: AssemblyTrademark("")] 30 | [assembly: AssemblyCulture("")] 31 | 32 | // Setting ComVisible to false makes the types in this assembly not visible 33 | // to COM components. If you need to access a type in this assembly from 34 | // COM, set the ComVisible attribute to true on that type. 35 | [assembly: ComVisible(false)] 36 | 37 | // The following GUID is for the ID of the typelib if this project is exposed to COM 38 | [assembly: Guid("41516709-605d-41da-9e9e-7e1e36ad944b")] 39 | 40 | // Version information for an assembly consists of the following four values: 41 | // 42 | // Major Version 43 | // Minor Version 44 | // Build Number 45 | // Revision 46 | // 47 | // You can specify all the values or you can default the Build and Revision Numbers 48 | // by using the '*' as shown below: 49 | // [assembly: AssemblyVersion("1.0.*")] 50 | [assembly: AssemblyVersion("2.5.4")] 51 | [assembly: AssemblyFileVersion("2.5.4")] 52 | -------------------------------------------------------------------------------- /OpaqueMail.CertHelper/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /OpaqueMail.Proxy/OpaqueMail.Proxy.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B} 8 | Library 9 | Properties 10 | OpaqueMail.Proxy 11 | OpaqueMail.Proxy 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | true 34 | 35 | 36 | OpaqueMail.pfx 37 | 38 | 39 | 40 | ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll 41 | True 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | {9f1402f2-d701-43a5-9ad6-cfa926c31dce} 63 | OpaqueMail.CertHelper 64 | 65 | 66 | {bf21d27f-72ad-492e-8219-6c82c2330c72} 67 | OpaqueMail 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 82 | -------------------------------------------------------------------------------- /OpaqueMail.Proxy/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Reflection; 17 | using System.Runtime.CompilerServices; 18 | using System.Runtime.InteropServices; 19 | 20 | // General Information about an assembly is controlled through the following 21 | // set of attributes. Change these attribute values to modify the information 22 | // associated with an assembly. 23 | [assembly: AssemblyTitle("OpaqueMail.Proxy")] 24 | [assembly: AssemblyDescription("SMTP proxy to add or remove S/MIME message signing, encryption, and authentication for outbound messages.")] 25 | [assembly: AssemblyConfiguration("")] 26 | [assembly: AssemblyCompany("Bert Johnson")] 27 | [assembly: AssemblyProduct("OpaqueMail")] 28 | [assembly: AssemblyCopyright("Copyright © 2013-2017 Bert Johnson")] 29 | [assembly: AssemblyTrademark("")] 30 | [assembly: AssemblyCulture("")] 31 | 32 | // Setting ComVisible to false makes the types in this assembly not visible 33 | // to COM components. If you need to access a type in this assembly from 34 | // COM, set the ComVisible attribute to true on that type. 35 | [assembly: ComVisible(false)] 36 | 37 | // The following GUID is for the ID of the typelib if this project is exposed to COM 38 | [assembly: Guid("0041886a-2f82-4a5d-a8e1-ade1788bcd2e")] 39 | 40 | // Version information for an assembly consists of the following four values: 41 | // 42 | // Major Version 43 | // Minor Version 44 | // Build Number 45 | // Revision 46 | // 47 | // You can specify all the values or you can default the Build and Revision Numbers 48 | // by using the '*' as shown below: 49 | // [assembly: AssemblyVersion("1.0.*")] 50 | [assembly: AssemblyVersion("2.5.4")] 51 | [assembly: AssemblyFileVersion("2.5.4")] 52 | -------------------------------------------------------------------------------- /OpaqueMail.Proxy/ProxyBase.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail Proxy (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.IO; 19 | using System.Linq; 20 | using System.Net; 21 | using System.Net.Sockets; 22 | using System.Security.Cryptography.X509Certificates; 23 | using System.Text; 24 | using System.Threading.Tasks; 25 | 26 | namespace OpaqueMail.Proxy 27 | { 28 | /// 29 | /// Foundation for IMAP, POP3, and SMTP proxies. 30 | /// 31 | public class ProxyBase 32 | { 33 | #region Public Members 34 | /// Welcome message to be displayed when connecting. 35 | public string WelcomeMessage = "OpaqueMail Proxy"; 36 | /// Proxy logging level, determining how much information is logged. 37 | public LogLevel LogLevel = LogLevel.None; 38 | #endregion Public Members 39 | 40 | #region Protected Members 41 | /// Whether the proxy has been started. 42 | protected bool Started = false; 43 | /// A TcpListener to accept incoming connections. 44 | protected TcpListener Listener; 45 | /// A unique session identifier for logging. 46 | protected string SessionId = ""; 47 | /// A unique connection identifier for logging. 48 | protected int ConnectionId = 0; 49 | /// StreamWriter object to output event logs and exception information. 50 | protected StreamWriter LogWriter = null; 51 | /// A collection of all S/MIME signing certificates imported during this session. 52 | protected X509Certificate2Collection SmimeCertificatesReceived = new X509Certificate2Collection(); 53 | /// The last command received from the client. 54 | protected string LastCommandReceived = ""; 55 | /// The user transmitting this message. 56 | protected string UserName = ""; 57 | #endregion Protected Members 58 | 59 | #region Public Methods 60 | /// 61 | /// Handle service continuations following pauses. 62 | /// 63 | public void ProcessContinuation() 64 | { 65 | ProxyFunctions.Log(LogWriter, SessionId, "Service continuing after pause.", Proxy.LogLevel.Information, LogLevel); 66 | Started = true; 67 | } 68 | 69 | /// 70 | /// Handle pause event. 71 | /// 72 | public void ProcessPause() 73 | { 74 | ProxyFunctions.Log(LogWriter, SessionId, "Service pausing.", Proxy.LogLevel.Information, LogLevel); 75 | Started = false; 76 | } 77 | 78 | /// 79 | /// Handle power events, such as hibernation. 80 | /// 81 | /// Indicates the system's power status. 82 | public void ProcessPowerEvent(int powerStatus) 83 | { 84 | if (LogWriter != null) 85 | { 86 | switch (powerStatus) 87 | { 88 | case 0: 89 | ProxyFunctions.Log(LogWriter, SessionId, "Computer has asked permission to enter the suspended state.", Proxy.LogLevel.Information, LogLevel); 90 | break; 91 | case 2: 92 | ProxyFunctions.Log(LogWriter, SessionId, "Computer was denied permission to enter the suspended state.", Proxy.LogLevel.Information, LogLevel); 93 | break; 94 | case 4: 95 | ProxyFunctions.Log(LogWriter, SessionId, "Computer is about to enter the suspended state.", Proxy.LogLevel.Information, LogLevel); 96 | break; 97 | case 6: 98 | ProxyFunctions.Log(LogWriter, SessionId, "Computer has resumed operation after a critical suspension caused by a failing battery.", Proxy.LogLevel.Information, LogLevel); 99 | break; 100 | case 7: 101 | ProxyFunctions.Log(LogWriter, SessionId, "The computer has resumed operation after being suspsended.", Proxy.LogLevel.Information, LogLevel); 102 | break; 103 | case 8: 104 | ProxyFunctions.Log(LogWriter, SessionId, "Computer's battery power is low.", Proxy.LogLevel.Information, LogLevel); 105 | break; 106 | case 10: 107 | case 11: 108 | ProxyFunctions.Log(LogWriter, SessionId, "The computer's power status has changed.", Proxy.LogLevel.Information, LogLevel); 109 | break; 110 | case 18: 111 | ProxyFunctions.Log(LogWriter, SessionId, "The computer has resumed operation to handle an event.", Proxy.LogLevel.Information, LogLevel); 112 | break; 113 | } 114 | } 115 | } 116 | #endregion Public Methods 117 | } 118 | } -------------------------------------------------------------------------------- /OpaqueMail.Proxy/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /OpaqueMail.ProxyService/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OpaqueMail.ProxyService/OpaqueMail.ProxyService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C8F12621-2E22-48FD-8E52-71F1B059179E} 8 | WinExe 9 | Properties 10 | OpaqueMail.ProxyService 11 | OpaqueMail.ProxyService 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | OpaqueMail32.ico 36 | 37 | 38 | true 39 | 40 | 41 | OpaqueMail.pfx 42 | 43 | 44 | 45 | ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Component 62 | 63 | 64 | ProxyService.cs 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {9f1402f2-d701-43a5-9ad6-cfa926c31dce} 76 | OpaqueMail.CertHelper 77 | 78 | 79 | {fbdcf97d-7ef1-470d-a13f-04cab5911d6b} 80 | OpaqueMail.Proxy 81 | 82 | 83 | {bf21d27f-72ad-492e-8219-6c82c2330c72} 84 | OpaqueMail 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 101 | -------------------------------------------------------------------------------- /OpaqueMail.ProxyService/OpaqueMail32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bertjohnson/OpaqueMail/63d55f213a0dd6cf91ddd44e00b63526b083ac17/OpaqueMail.ProxyService/OpaqueMail32.ico -------------------------------------------------------------------------------- /OpaqueMail.ProxyService/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail Proxy (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.ServiceProcess; 17 | 18 | namespace OpaqueMail.Proxy 19 | { 20 | static class Program 21 | { 22 | /// 23 | /// The main entry point for the application. 24 | /// 25 | static void Main() 26 | { 27 | ServiceBase[] ServicesToRun; 28 | ServicesToRun = new ServiceBase[] 29 | { 30 | new ProxyService() 31 | }; 32 | ServiceBase.Run(ServicesToRun); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /OpaqueMail.ProxyService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Reflection; 17 | using System.Runtime.InteropServices; 18 | 19 | // General Information about an assembly is controlled through the following 20 | // set of attributes. Change these attribute values to modify the information 21 | // associated with an assembly. 22 | [assembly: AssemblyTitle("OpaqueMail.ProxyService")] 23 | [assembly: AssemblyDescription("SMTP proxy to add or remove S/MIME message signing, encryption, and authentication for outbound messages.")] 24 | [assembly: AssemblyConfiguration("")] 25 | [assembly: AssemblyCompany("Bert Johnson")] 26 | [assembly: AssemblyProduct("OpaqueMail")] 27 | [assembly: AssemblyCopyright("Copyright © 2013-2017 Bert Johnson")] 28 | [assembly: AssemblyTrademark("")] 29 | [assembly: AssemblyCulture("")] 30 | 31 | // Setting ComVisible to false makes the types in this assembly not visible 32 | // to COM components. If you need to access a type in this assembly from 33 | // COM, set the ComVisible attribute to true on that type. 34 | [assembly: ComVisible(false)] 35 | 36 | // The following GUID is for the ID of the typelib if this project is exposed to COM 37 | [assembly: Guid("a9696089-4b6c-47c6-b2a1-cd692d45287b")] 38 | 39 | // Version information for an assembly consists of the following four values: 40 | // 41 | // Major Version 42 | // Minor Version 43 | // Build Number 44 | // Revision 45 | // 46 | // You can specify all the values or you can default the Build and Revision Numbers 47 | // by using the '*' as shown below: 48 | // [assembly: AssemblyVersion("1.0.*")] 49 | [assembly: AssemblyVersion("2.5.4")] 50 | [assembly: AssemblyFileVersion("2.5.4")] 51 | -------------------------------------------------------------------------------- /OpaqueMail.ProxyService/ProxyService.Designer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | namespace OpaqueMail.Proxy 17 | { 18 | public partial class ProxyService 19 | { 20 | /// 21 | /// Required designer variable. 22 | /// 23 | private System.ComponentModel.IContainer components = null; 24 | 25 | /// 26 | /// Clean up any resources being used. 27 | /// 28 | /// true if managed resources should be disposed; otherwise, false. 29 | protected override void Dispose(bool disposing) 30 | { 31 | if (disposing && (components != null)) 32 | { 33 | components.Dispose(); 34 | } 35 | base.Dispose(disposing); 36 | } 37 | 38 | #region Component Designer generated code 39 | 40 | /// 41 | /// Required method for Designer support - do not modify 42 | /// the contents of this method with the code editor. 43 | /// 44 | private void InitializeComponent() 45 | { 46 | components = new System.ComponentModel.Container(); 47 | this.ServiceName = "OpaqueMail Proxy"; 48 | } 49 | 50 | #endregion 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /OpaqueMail.ProxyService/ProxyService.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail Proxy (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using OpaqueMail.Proxy; 17 | using System; 18 | using System.Collections; 19 | using System.Collections.Generic; 20 | using System.ComponentModel; 21 | using System.Configuration.Install; 22 | using System.Data; 23 | using System.Diagnostics; 24 | using System.IO; 25 | using System.Linq; 26 | using System.Net; 27 | using System.Security.Cryptography.X509Certificates; 28 | using System.ServiceProcess; 29 | using System.Text; 30 | using System.Threading; 31 | using System.Threading.Tasks; 32 | using System.Xml.XPath; 33 | 34 | namespace OpaqueMail.Proxy 35 | { 36 | /// 37 | /// Service to proxy SMTP, IMAP, and POP3 traffic. 38 | /// 39 | public partial class ProxyService : ServiceBase 40 | { 41 | #region Private Members 42 | /// List of all proxies that have been started. 43 | private List imapProxies = null; 44 | private List pop3Proxies = null; 45 | private List smtpProxies = null; 46 | #endregion Private Members 47 | 48 | #region Constructors 49 | /// 50 | /// Default constructor. 51 | /// 52 | public ProxyService() 53 | { 54 | InitializeComponent(); 55 | } 56 | #endregion Constructors 57 | 58 | #region Protected Methods 59 | /// 60 | /// Handle the service start event by reading the settings file and starting all specified proxy instances. 61 | /// 62 | protected override void OnStart(string[] args) 63 | { 64 | imapProxies = ImapProxy.StartProxiesFromSettingsFile(GetSettingsFileName()); 65 | pop3Proxies = Pop3Proxy.StartProxiesFromSettingsFile(GetSettingsFileName()); 66 | smtpProxies = SmtpProxy.StartProxiesFromSettingsFile(GetSettingsFileName()); 67 | } 68 | 69 | /// 70 | /// Handle the service stop event by stopping all proxies. 71 | /// 72 | protected override void OnStop() 73 | { 74 | if (imapProxies != null) 75 | { 76 | foreach (ImapProxy imapProxy in imapProxies) 77 | imapProxy.Stop(); 78 | 79 | imapProxies.Clear(); 80 | } 81 | if (pop3Proxies != null) 82 | { 83 | foreach (Pop3Proxy pop3Proxy in pop3Proxies) 84 | pop3Proxy.Stop(); 85 | 86 | pop3Proxies.Clear(); 87 | } 88 | if (smtpProxies != null) 89 | { 90 | foreach (SmtpProxy smtpProxy in smtpProxies) 91 | smtpProxy.Stop(); 92 | 93 | smtpProxies.Clear(); 94 | } 95 | } 96 | 97 | /// 98 | /// Handle service continuations following pauses. 99 | /// 100 | protected override void OnContinue() 101 | { 102 | if (imapProxies != null) 103 | { 104 | foreach (ImapProxy imapProxy in imapProxies) 105 | imapProxy.ProcessContinuation(); 106 | 107 | imapProxies.Clear(); 108 | } 109 | if (pop3Proxies != null) 110 | { 111 | foreach (Pop3Proxy pop3Proxy in pop3Proxies) 112 | pop3Proxy.ProcessContinuation(); 113 | 114 | pop3Proxies.Clear(); 115 | } 116 | if (smtpProxies != null) 117 | { 118 | foreach (SmtpProxy smtpProxy in smtpProxies) 119 | smtpProxy.ProcessContinuation(); 120 | 121 | smtpProxies.Clear(); 122 | } 123 | } 124 | 125 | /// 126 | /// Handle pause event. 127 | /// 128 | protected override void OnPause() 129 | { 130 | if (imapProxies != null) 131 | { 132 | foreach (ImapProxy imapProxy in imapProxies) 133 | imapProxy.ProcessPause(); 134 | 135 | imapProxies.Clear(); 136 | } 137 | if (pop3Proxies != null) 138 | { 139 | foreach (Pop3Proxy pop3Proxy in pop3Proxies) 140 | pop3Proxy.ProcessPause(); 141 | 142 | pop3Proxies.Clear(); 143 | } 144 | if (smtpProxies != null) 145 | { 146 | foreach (SmtpProxy smtpProxy in smtpProxies) 147 | smtpProxy.ProcessPause(); 148 | 149 | smtpProxies.Clear(); 150 | } 151 | } 152 | 153 | /// 154 | /// Handle power events, such as hibernation. 155 | /// 156 | protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus) 157 | { 158 | if (imapProxies != null) 159 | { 160 | foreach (ImapProxy imapProxy in imapProxies) 161 | imapProxy.ProcessPowerEvent((int)powerStatus); 162 | 163 | imapProxies.Clear(); 164 | } 165 | if (pop3Proxies != null) 166 | { 167 | foreach (Pop3Proxy pop3Proxy in pop3Proxies) 168 | pop3Proxy.ProcessPowerEvent((int)powerStatus); 169 | 170 | pop3Proxies.Clear(); 171 | } 172 | if (smtpProxies != null) 173 | { 174 | foreach (SmtpProxy smtpProxy in smtpProxies) 175 | smtpProxy.ProcessPowerEvent((int)powerStatus); 176 | 177 | smtpProxies.Clear(); 178 | } 179 | 180 | return base.OnPowerEvent(powerStatus); 181 | } 182 | #endregion Protected Methods 183 | 184 | #region Private Methods 185 | /// 186 | /// Return the path where the service's settings should be saved and loaded. 187 | /// 188 | private static string GetSettingsFileName() 189 | { 190 | return AppDomain.CurrentDomain.BaseDirectory + "\\OpaqueMail.Proxy.xml"; 191 | } 192 | #endregion Private Methods 193 | } 194 | 195 | /// 196 | /// Sets the service account to the local system. 197 | /// 198 | [RunInstaller(true)] 199 | public sealed class ProxyServiceProcessInstaller : ServiceProcessInstaller 200 | { 201 | public ProxyServiceProcessInstaller() 202 | { 203 | Account = ServiceAccount.LocalSystem; 204 | } 205 | } 206 | 207 | /// 208 | /// Handles OpaqueMail Proxy service installation. 209 | /// 210 | [RunInstaller(true)] 211 | public sealed class ProxyServiceInstaller : ServiceInstaller 212 | { 213 | /// 214 | /// Default constructor. 215 | /// 216 | public ProxyServiceInstaller() 217 | { 218 | Description = "Serves as a local SMTP, IMAP, and POP3 proxy, optionally adding authentication and S/MIME signing or encryption to all outbound email."; 219 | DisplayName = "OpaqueMail Proxy"; 220 | ServiceName = "OpaqueMailProxy"; 221 | StartType = ServiceStartMode.Automatic; 222 | } 223 | 224 | /// 225 | /// Handle installation and uninstallation. 226 | /// 227 | /// Whether we're uninstalling. False if installing, true if uninstalling 228 | /// Any service installation arguments. 229 | public void Install(bool uninstall, string[] args) 230 | { 231 | try 232 | { 233 | using (AssemblyInstaller installer = new AssemblyInstaller(typeof(Program).Assembly, args)) 234 | { 235 | IDictionary state = new Hashtable(); 236 | installer.UseNewContext = true; 237 | try 238 | { 239 | // Attempt to install or uninstall. 240 | if (uninstall) 241 | installer.Uninstall(state); 242 | else 243 | { 244 | installer.Install(state); 245 | installer.Commit(state); 246 | } 247 | } 248 | catch 249 | { 250 | // If an error is encountered, attempt to roll back. 251 | try 252 | { 253 | installer.Rollback(state); 254 | } 255 | catch { } 256 | 257 | throw; 258 | } 259 | } 260 | } 261 | catch (Exception ex) 262 | { 263 | Console.Error.WriteLine(ex.Message); 264 | } 265 | } 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /OpaqueMail.ProxyService/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/OpaqueMail.Proxy.Sample.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 1 6 | 7 | 8 | 9 | 10 | 0.0.0.0 11 | 12 | 13 | Any 14 | 15 | 587 16 | 17 | True 18 | 19 | 20 | smtp.gmail.com 21 | 22 | 587 23 | 24 | True 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | True 44 | 45 | 46 | 47 | 48 | BestEffort 49 | 50 | 51 | True 52 | 53 | True 54 | 55 | True 56 | 57 | 58 | True 59 | 60 | 61 | 62 | 63 | 64 | 65 | Logs\SMTPProxy{#}-{yyyy-MM-dd}.log 66 | 67 | Verbose 68 | 69 | 70 | 71 | 72 | 1 73 | 74 | 75 | 76 | 77 | 0.0.0.0 78 | 79 | 80 | Any 81 | 82 | 993 83 | 84 | True 85 | 86 | 87 | imap.gmail.com 88 | 89 | 993 90 | 91 | True 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Logs\IMAPProxy{#}-{yyyy-MM-dd}.log 104 | 105 | Verbose 106 | 107 | 108 | 109 | 110 | 1 111 | 112 | 113 | 114 | 115 | 0.0.0.0 116 | 117 | 118 | Any 119 | 120 | 995 121 | 122 | True 123 | 124 | 125 | pop.gmail.com 126 | 127 | 995 128 | 129 | True 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | Logs\POP3Proxy{#}-{yyyy-MM-dd}.log 142 | 143 | Verbose 144 | 145 | 146 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/OpaqueMail.ProxySettings.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EE9F6184-F918-4FC0-9018-3019DFB8A408} 8 | WinExe 9 | Properties 10 | OpaqueMail.ProxySettings 11 | OpaqueMail.ProxySettings 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | OpaqueMail32.ico 36 | 37 | 38 | app.manifest 39 | 40 | 41 | true 42 | 43 | 44 | OpaqueMail.pfx 45 | 46 | 47 | 48 | ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll 49 | True 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | Form 67 | 68 | 69 | Form1.cs 70 | 71 | 72 | Form 73 | 74 | 75 | 76 | 77 | 78 | Form1.cs 79 | Designer 80 | 81 | 82 | ResXFileCodeGenerator 83 | Resources.Designer.cs 84 | Designer 85 | 86 | 87 | True 88 | Resources.resx 89 | 90 | 91 | 92 | 93 | 94 | SettingsSingleFileGenerator 95 | Settings.Designer.cs 96 | 97 | 98 | True 99 | Settings.settings 100 | True 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | {9f1402f2-d701-43a5-9ad6-cfa926c31dce} 111 | OpaqueMail.CertHelper 112 | 113 | 114 | {c8f12621-2e22-48fd-8e52-71f1b059179e} 115 | OpaqueMail.ProxyService 116 | 117 | 118 | {fbdcf97d-7ef1-470d-a13f-04cab5911d6b} 119 | OpaqueMail.Proxy 120 | 121 | 122 | {bf21d27f-72ad-492e-8219-6c82c2330c72} 123 | OpaqueMail 124 | 125 | 126 | 127 | 128 | Always 129 | Designer 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 147 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/OpaqueMail32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bertjohnson/OpaqueMail/63d55f213a0dd6cf91ddd44e00b63526b083ac17/OpaqueMail.ProxySettings/OpaqueMail32.ico -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail Proxy (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System; 17 | using System.Windows.Forms; 18 | 19 | namespace OpaqueMail.Proxy.Settings 20 | { 21 | static class Program 22 | { 23 | /// 24 | /// The main entry point for the application. 25 | /// 26 | [STAThread] 27 | static void Main() 28 | { 29 | Application.EnableVisualStyles(); 30 | Application.SetCompatibleTextRenderingDefault(false); 31 | Application.Run(new Form1()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Reflection; 17 | using System.Runtime.InteropServices; 18 | 19 | // General Information about an assembly is controlled through the following 20 | // set of attributes. Change these attribute values to modify the information 21 | // associated with an assembly. 22 | [assembly: AssemblyTitle("OpaqueMail.ProxySettings")] 23 | [assembly: AssemblyDescription("SMTP proxy to add or remove S/MIME message signing, encryption, and authentication for outbound messages.")] 24 | [assembly: AssemblyConfiguration("")] 25 | [assembly: AssemblyCompany("Bert Johnson")] 26 | [assembly: AssemblyProduct("OpaqueMail")] 27 | [assembly: AssemblyCopyright("Copyright © 2013-2017 Bert Johnson")] 28 | [assembly: AssemblyTrademark("")] 29 | [assembly: AssemblyCulture("")] 30 | 31 | // Setting ComVisible to false makes the types in this assembly not visible 32 | // to COM components. If you need to access a type in this assembly from 33 | // COM, set the ComVisible attribute to true on that type. 34 | [assembly: ComVisible(false)] 35 | 36 | // The following GUID is for the ID of the typelib if this project is exposed to COM 37 | [assembly: Guid("6d67b499-de07-498e-8853-51c0b4d01253")] 38 | 39 | // Version information for an assembly consists of the following four values: 40 | // 41 | // Major Version 42 | // Minor Version 43 | // Build Number 44 | // Revision 45 | // 46 | // You can specify all the values or you can default the Build and Revision Numbers 47 | // by using the '*' as shown below: 48 | // [assembly: AssemblyVersion("1.0.*")] 49 | [assembly: AssemblyVersion("2.5.4")] 50 | [assembly: AssemblyFileVersion("2.5.4")] 51 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18051 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace OpaqueMail.Proxy.Settings.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpaqueMail.ProxySettings.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18051 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace OpaqueMail.Proxy.Settings.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 20 | 21 | public static Settings Default 22 | { 23 | get 24 | { 25 | return defaultInstance; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Signature.Resources/OpaqueMail.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bertjohnson/OpaqueMail/63d55f213a0dd6cf91ddd44e00b63526b083ac17/OpaqueMail.ProxySettings/Signature.Resources/OpaqueMail.txt -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Signature.Resources/colorschememapping.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Signature.Resources/filelist.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Signature.Resources/themedata.thmx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bertjohnson/OpaqueMail/63d55f213a0dd6cf91ddd44e00b63526b083ac17/OpaqueMail.ProxySettings/Signature.Resources/themedata.thmx -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/Windows8Mail.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail Proxy (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Linq; 19 | using System.Runtime.InteropServices; 20 | 21 | namespace OpaqueMail.Proxy.Settings 22 | { 23 | /// 24 | /// Helper class to create a loopback exception for the Windows 8 Mail app. 25 | /// 26 | /// See http://blogs.msdn.com/b/fiddler/archive/2011/09/14/fiddler-and-windows-8-metro-style-applications-https-and-private-network-capabilities.aspx for more information. 27 | public class Windows8MailHelper 28 | { 29 | #region Structs 30 | [StructLayoutAttribute(LayoutKind.Sequential)] 31 | internal struct SidAndAttributes 32 | { 33 | public IntPtr Sid; 34 | public uint Attributes; 35 | } 36 | 37 | [StructLayoutAttribute(LayoutKind.Sequential)] 38 | internal struct InetFirewallAcCapabilities 39 | { 40 | public uint Count; 41 | public IntPtr Capabilities; 42 | } 43 | 44 | [StructLayoutAttribute(LayoutKind.Sequential)] 45 | internal struct InetFirewallAcBinaries 46 | { 47 | public uint Count; 48 | public IntPtr Binaries; 49 | } 50 | 51 | [StructLayoutAttribute(LayoutKind.Sequential)] 52 | internal struct InetFirewallAppContainer 53 | { 54 | internal IntPtr AppContainerSid; 55 | internal IntPtr UserSid; 56 | [MarshalAs(UnmanagedType.LPWStr)] 57 | public string AppContainerName; 58 | [MarshalAs(UnmanagedType.LPWStr)] 59 | public string DisplayName; 60 | [MarshalAs(UnmanagedType.LPWStr)] 61 | public string Description; 62 | internal InetFirewallAcCapabilities Capabilities; 63 | internal InetFirewallAcBinaries Binaries; 64 | [MarshalAs(UnmanagedType.LPWStr)] 65 | public string WorkingDirectory; 66 | [MarshalAs(UnmanagedType.LPWStr)] 67 | public string PackageFullName; 68 | } 69 | #endregion Structs 70 | 71 | #region Externs 72 | [DllImport("FirewallAPI.dll")] 73 | internal static extern void NetworkIsolationFreeAppContainers(IntPtr pACs); 74 | 75 | [DllImport("FirewallAPI.dll")] 76 | internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids); 77 | 78 | [DllImport("FirewallAPI.dll")] 79 | private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SidAndAttributes[] appContainerSids); 80 | 81 | [DllImport("advapi32.dll", SetLastError = true)] 82 | internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid); 83 | 84 | [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] 85 | static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid); 86 | 87 | [DllImport("FirewallAPI.dll")] 88 | internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs); 89 | #endregion Externs 90 | 91 | #region Private Enums 92 | private enum NETISO_FLAG 93 | { 94 | NETISO_FLAG_FORCE_COMPUTE_BINARIES = 0x1, 95 | NETISO_FLAG_MAX = 0x2 96 | } 97 | #endregion Private Enums 98 | 99 | #region Internal Members 100 | internal List Apps = new List(); 101 | internal List AppList; 102 | internal List AppListConfig; 103 | internal IntPtr ACs; 104 | #endregion Internal Members 105 | 106 | #region Constructors 107 | /// 108 | /// Default constructor. 109 | /// 110 | public Windows8MailHelper() 111 | { 112 | AppList = PINetworkIsolationEnumAppContainers(); 113 | AppListConfig = PINetworkIsolationGetAppContainerConfig(); 114 | foreach (InetFirewallAppContainer PIApp in AppList) 115 | { 116 | AppContainer app = new AppContainer(PIApp.AppContainerName, PIApp.DisplayName, PIApp.WorkingDirectory, PIApp.AppContainerSid); 117 | 118 | List AppCapabilities = GetCapabilites(PIApp.Capabilities); 119 | 120 | app.LoopbackEnabled = CheckLoopback(PIApp.AppContainerSid); 121 | Apps.Add(app); 122 | } 123 | } 124 | #endregion Constructors 125 | 126 | #region Helper Classes 127 | /// 128 | /// Object to track app container information. 129 | /// 130 | internal class AppContainer 131 | { 132 | public String AppContainerName { get; set; } 133 | public String DisplayName { get; set; } 134 | public String WorkingDirectory { get; set; } 135 | public String StringSid { get; set; } 136 | public List Capabilities { get; set; } 137 | public bool LoopbackEnabled { get; set; } 138 | 139 | public AppContainer(String _appContainerName, String _displayName, String _workingDirectory, IntPtr _sid) 140 | { 141 | this.AppContainerName = _appContainerName; 142 | this.DisplayName = _displayName; 143 | this.WorkingDirectory = _workingDirectory; 144 | String tempSid; 145 | ConvertSidToStringSid(_sid, out tempSid); 146 | this.StringSid = tempSid; 147 | } 148 | } 149 | #endregion Helper Classes 150 | 151 | #region Public Methods 152 | /// 153 | /// Enable Windows 8 Mail loopback exemptions. 154 | /// 155 | public void EnableWindows8MailLoopback() 156 | { 157 | // Loop through and enable loopbacks for any Windows 8 Mail applications. 158 | for (int i = 0; i < Apps.Count; i++) 159 | { 160 | // Strings relevant to the Windows 8 Mail app. 161 | if (Apps[i].AppContainerName.Contains("microsoft.windowscommunicationsapps_") || Apps[i].AppContainerName.Contains("microsoft.winjs.")) 162 | Apps[i].LoopbackEnabled = true; 163 | } 164 | 165 | // Count the number of exemptions. 166 | int countEnabled = Apps.Where(_ => _.LoopbackEnabled == true).Count(); 167 | SidAndAttributes[] sidAndAttributesArray = new SidAndAttributes[countEnabled]; 168 | int count = 0; 169 | 170 | // Save our exemptions. 171 | for (int i = 0; i < Apps.Count; i++) 172 | { 173 | if (Apps[i].LoopbackEnabled) 174 | { 175 | sidAndAttributesArray[count].Attributes = 0; 176 | IntPtr ptr; 177 | ConvertStringSidToSid(Apps[i].StringSid, out ptr); 178 | sidAndAttributesArray[count].Sid = ptr; 179 | count++; 180 | } 181 | } 182 | NetworkIsolationSetAppContainerConfig((uint)countEnabled, sidAndAttributesArray); 183 | 184 | // Free our app container handles. 185 | NetworkIsolationFreeAppContainers(ACs); 186 | } 187 | #endregion Public Methods 188 | 189 | #region Private Methods 190 | /// 191 | /// Check if an application is set up for the loopback exemption. 192 | /// 193 | /// Pointer to the application container. 194 | private bool CheckLoopback(IntPtr intPtr) 195 | { 196 | foreach (SidAndAttributes item in AppListConfig) 197 | { 198 | string before, after; 199 | ConvertSidToStringSid(item.Sid, out before); 200 | ConvertSidToStringSid(intPtr, out after); 201 | 202 | return before == after; 203 | } 204 | 205 | return false; 206 | } 207 | 208 | /// 209 | /// Return a list of capabilities of a Windows 8 application. 210 | /// 211 | private static List GetCapabilites(InetFirewallAcCapabilities cap) 212 | { 213 | List myCapabilities = new List(); 214 | 215 | IntPtr arrayValue = cap.Capabilities; 216 | 217 | int structSize = Marshal.SizeOf(typeof(SidAndAttributes)); 218 | for (int i = 0; i < cap.Count; i++) 219 | { 220 | SidAndAttributes currentSidAndAttributes = (SidAndAttributes)Marshal.PtrToStructure(arrayValue, typeof(SidAndAttributes)); 221 | myCapabilities.Add(currentSidAndAttributes); 222 | arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); 223 | } 224 | 225 | return myCapabilities; 226 | } 227 | 228 | /// 229 | /// Return a list of Windows 8 app container configuration settings. 230 | /// 231 | private static List PINetworkIsolationGetAppContainerConfig() 232 | { 233 | IntPtr arrayValue = IntPtr.Zero; 234 | uint size = 0; 235 | List myCapabilities = new List(); 236 | 237 | GCHandle handlePdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned); 238 | GCHandle handlePpACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned); 239 | 240 | uint retVal = NetworkIsolationGetAppContainerConfig(out size, out arrayValue); 241 | 242 | int structSize = Marshal.SizeOf(typeof(SidAndAttributes)); 243 | for (int i = 0; i < size; i++) 244 | { 245 | SidAndAttributes currentSidAndAttributes = (SidAndAttributes)Marshal.PtrToStructure(arrayValue, typeof(SidAndAttributes)); 246 | myCapabilities.Add(currentSidAndAttributes); 247 | arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); 248 | } 249 | 250 | handlePdwCntPublicACs.Free(); 251 | handlePpACs.Free(); 252 | 253 | return myCapabilities; 254 | } 255 | 256 | /// 257 | /// Return a list of Windows 8 app containers. 258 | /// 259 | private List PINetworkIsolationEnumAppContainers() 260 | { 261 | IntPtr arrayValue = IntPtr.Zero; 262 | uint size = 0; 263 | List list = new List(); 264 | 265 | GCHandle handlePdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned); 266 | GCHandle handlePpACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned); 267 | 268 | uint retVal = NetworkIsolationEnumAppContainers((Int32)NETISO_FLAG.NETISO_FLAG_MAX, out size, out arrayValue); 269 | ACs = arrayValue; 270 | 271 | int structSize = Marshal.SizeOf(typeof(InetFirewallAppContainer)); 272 | for (int i = 0; i < size; i++) 273 | { 274 | InetFirewallAppContainer cur = (InetFirewallAppContainer)Marshal.PtrToStructure(arrayValue, typeof(InetFirewallAppContainer)); 275 | list.Add(cur); 276 | arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); 277 | } 278 | 279 | handlePdwCntPublicACs.Free(); 280 | handlePpACs.Free(); 281 | 282 | return list; 283 | } 284 | #endregion Private Methods 285 | } 286 | } -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /OpaqueMail.ProxySettings/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/Form1.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | AAABAAIAEBAAAAAAIABoBAAAJgAAACAgAAAAACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAEAE 124 | AAAAAAAAAAAAAAAAAAAAAAAA////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 125 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 126 | /wH///8B////Af///wH///8B////Af///wEHx2aDDchpgwnHZ4MBxmKDAcZigwGuVoMBo1GDAaNRgwF1 127 | OoMBdTqDAWYygwFKJIMBSiSDAUokgwFKJIMBSiSDOdOF/2bdof9E1Yz/AcZi/wHGYv8Arlb/AaNR/wGj 128 | Uf8BdTr/AXU6/wFmMv8BSiT/AUok/wFKJP8BSiT/AUok/znThf9n3aL/RNWM/wHGYv8BxmL/AK5W/wGj 129 | Uf8Bo1H/AXU6/wF1Ov8BZjL/AUok/wFKJP8BSiT/AUok/wFKJP9c25r/puvI/4vluP9X2Zf/V9mX/x3J 130 | cv8BwF//AcBf/wGcTf8BnE3/AY1F/wFuNv8Bbjb/AVYq/wFKJP8BSiT/Y9yf/7Lu0P+Z6MD/Z92i/2fd 131 | ov8iznf/AcZi/wHGYv8Bo1H/AaNR/wGUSf8BdTr/AXU6/wFYK/8BSiT/AUok/2reo/+/8dj/puvJ/3Tg 132 | qv904Kr/M9GB/wrIaP+L5bf/P8yE/wGqVP8Bm0z/AX0+/wF9Pv8BYC//AVEo/wFRKP+O5rn//////+X5 133 | 7/+y7tD/q+zM/1jamP/L89////////z+/f+D47L/Bbxf/wGjUf8Bo1H/AIRB/wF1Ov8BdTr/jua5//// 134 | ///l+e//mejA/23fpf/t+/T//////////////////////8Xy2/8hwG//AaRR/wCEQf8BdTr/AXU6/47m 135 | uf//////p+vJ/5Dmuv/9/v7/////////////////////////////////8Pv1/1nVlv8AnE3/AYxF/wGM 136 | Rf+J5bb/i+W3/73w1//////////////////////////////////////////////////+////oOnE/w22 137 | YP8Bo1H/HM1z/5vowf+17tH/te7R/7Xu0f+17tH/te7R/7Xu0f+17tH/te7R/7Xu0f+17tH/te7R/7Xu 138 | 0f+R5rv/DL9k/wHGYicBxmInAcZiJwHGYicBxmInAcZiJwHGYicBxmInAcZiJwHGYicBxmInAcZiJwHG 139 | YicBxmInAcZiJwHGYif///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 140 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 141 | /wH///8B////Af///wH///8B////AQAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA 142 | //8AAP//AAD//wAA//8AAP//AAD//wAA//8oAAAAIAAAAEAAAAABACAAAAAAAIAQAAAAAAAAAAAAAAAA 143 | AAAAAAAA////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 144 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 145 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 146 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 147 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 148 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 149 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 150 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 151 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEBxmIHAcZiBwHGYgcBxmIHAcZiBwHG 152 | YgcBxmIHAcZiBwHGYgcBxmIHAbpcBwGjUQcBo1EHAaNRBwGjUQcBo1EHAXU6BwF1OgcBdToHAXU6BwF1 153 | OgcBWCwHAUokBwFKJAcBSiQHAUokBwFKJAcBSiQHAUokBwFKJAcBSiQHAUokBwLHY/8OyWr/Dslq/w7J 154 | av8OyWr/Bcdl/wHGYv8BxmL/AcZi/wHGYv8Bulz/AaNR/wGjUf8Bo1H/AaNR/wGjUf8BdTr/AXU6/wF1 155 | Ov8BdTr/AXU6/wFYK/8BSiT/AUok/wFKJP8BSiT/AUok/wFKJP8BSiT/AUok/wFKJP8BSiT/DMlp/2bd 156 | of9m3aH/Zt2h/2bdof8iznf/AcZi/wHGYv8BxmL/AcZi/wC6XP8Bo1H/AaNR/wGjUf8Bo1H/AaNR/wF1 157 | Ov8BdTr/AXU6/wF1Ov8BdTr/AVgr/wFKJP8BSiT/AUok/wFKJP8BSiT/AUok/wFKJP8BSiT/AUok/wFK 158 | JP8MyWn/Z92i/2fdov9n3aL/Z92i/yLOd/8BxmL/AcZi/wHGYv8BxmL/Abpc/wGjUf8Bo1H/AaNR/wGj 159 | Uf8Bo1H/AXU6/wF1Ov8BdTr/AXU6/wF1Ov8BWCv/AUok/wFKJP8BSiT/AUok/wFKJP8BSiT/AUok/wFK 160 | JP8BSiT/AUok/wzJaf9m3aL/Z92i/2fdov9n3aH/Is53/wHGYv8BxmL/AcZi/wHGYv8Aulz/AaNR/wGj 161 | Uf8Bo1H/AaNR/wGjUf8BdTr/AXU6/wF1Ov8BdTr/AXU6/wFYK/8BSiT/AUok/wFKJP8BSiT/AUok/wFK 162 | JP8BSiT/AUok/wFKJP8BSiT/DMlp/2fdov9n3aL/Z92i/2fdov8iznf/AcZi/wHGYv8BxmL/AcZi/wG6 163 | XP8Bo1H/AaNR/wGjUf8Bo1H/AaNR/wF1Ov8BdTr/AXU6/wF1Ov8BdTr/AVgr/wFKJP8BSiT/AUok/wFK 164 | JP8BSiT/AUok/wFKJP8BSiT/AUok/wFKJP8Rymz/munB/5rpwf+a6cH/munB/2Pcn/9H1o3/R9aN/0fW 165 | jf9H1o3/L819/wG8Xf8Bu13/Abtd/wG7Xf8Bu1z/AZVK/wGVSv8BlUr/AZVK/wGVSv8Bdzr/AWgz/wFo 166 | M/8BaDP/AWgz/wFdLv8BSiT/AUok/wFKJP8BSiT/AUok/xTLbv+y7tD/su7Q/7Lu0P+y7tD/gOKx/2fd 167 | ov9n3aL/Z92i/2fdov9F1Yz/Acdi/wHGYv8BxmL/AcZi/wHGYv8Bo1H/AaNR/wGjUf8Bo1H/AaNR/wGF 168 | Qf8BdTr/AXU6/wF1Ov8BdTr/AWcy/wFKJP8BSiT/AUok/wFKJP8BSiT/FMtu/7Lu0P+y7tD/su7Q/7Lu 169 | 0P+A4rH/Z92i/2fdov9n3aL/Z92i/0XWjP8BxmL/AcZi/wHGYv8BxmL/AcZi/wGjUf8Bo1H/AaNR/wGj 170 | Uf8Bo1H/AYVB/wF1Ov8BdTr/AXU6/wF1Ov8BZzL/AUok/wFKJP8BSiT/AUok/wFKJP8Uy27/su7Q/7Lu 171 | 0P+y7tD/su7Q/4Disf9n3aL/Z92i/2fdov9n3aL/RNWM/wDHYv8BxmL/AcZi/wHGYv8BxmL/AaVS/wGj 172 | Uf8Bo1H/AaNR/wGjUf8BhUH/AXU6/wF1Ov8BdTr/AXU6/wFnMv8BSiT/AUok/wFKJP8BSiT/AUok/xTL 173 | bv+y7tD/su7Q/7Lu0P+y7tD/gOKx/2fdov9n3aL/Z92i/2fdov9F1oz/AcZi/wHGYv8BxmL/B8hm/2Hc 174 | nf8IxGT/AatU/wGjUf8Bo1H/AaNR/wGFQf8BdTr/AXU6/wF1Ov8BdTr/AWcy/wFKJP8BSiT/AUok/wFK 175 | JP8BSiT/F8xw/8304f/N9OH/zfTh/8304f+b6cL/geOy/4Hjsv+B47L/geOy/2Lcn/8lznj/Cchn/x/N 176 | df/I893//////8304P8oz3r/AbVZ/wGwV/8BsFf/AZRJ/wGGQv8BhkL/AYZC/wGGQv8Bdzr/AVks/wFZ 177 | LP8BWSz/AVks/wFZLP8dzXP//////////////////////8v04P+y7tD/su7Q/7Lu0P+y7tD/lei+/yfP 178 | ev9I147/6/vz//////////////////T8+P9k3Z//AcZi/wHGYv8Ar1b/AaNR/wGjUf8Bo1H/AaNR/wCU 179 | Sf8BdTr/AXU6/wF1Ov8BdTr/AXU6/x3Nc///////////////////////y/Tg/7Lu0P+y7tD/su7Q/5no 180 | wP8lz3j/geOx//z+/f////////////////////////////////+q7Mv/Esps/wGzWP8Bo1H/AaNR/wGj 181 | Uf8Bo1H/AZRJ/wF1Ov8BdTr/AXU6/wF1Ov8BdTr/Hc1z///////////////////////L9OD/su7Q/7Lu 182 | 0P964q3/Ic52/7nv1P/////////////////////////////////////////////////g+Oz/PdSH/wG4 183 | W/8BpFH/AaNR/wGjUf8AlEn/AXU6/wF1Ov8BdTr/AXU6/wF1Ov8dzXP//////////////////////8v0 184 | 4P+v7c7/UdmU/zrUhf/h+O3///////////////////////////////////////////////////////// 185 | ///7/v3/gOOx/wXCYf8BqVT/AaNR/wCUSf8BdTr/AXU6/wF1Ov8BdTr/AXU6/x3Nc/////////////// 186 | ////////uvDV/yzQff9u36X/+f77//////////////////////////////////////////////////// 187 | ////////////////////////w/La/yDNdf8Bslj/AJVJ/wF2Ov8Bdjr/AXY6/wF2Ov8Bdjr/Hc1z//// 188 | /////////////77x1/8lz3n/qOzJ//////////////////////////////////////////////////// 189 | ////////////////////////////////////////7/v1/1fal/8BwF//AaZS/wGjUf8Bo1H/AaNR/wGj 190 | Uf8dzXP///////3//v+H5bX/L9F//9b25v////////////////////////////////////////////// 191 | /////////////////////////////////////////////////////////v///53pw/8Mxmf/Aa1V/wGj 192 | Uf8Bo1H/AaNR/x3Nc//u+/T/TtiS/1vbmv/z/Pj///////////////////////////////////////// 193 | /////////////////////////////////////////////////////////////////////////////9j2 194 | 5/8z0oH/AbZa/wGkUf8Bo1H/Dspq/yrQe/+W6L7//v////////////////////////////////////// 195 | //////////////////////////////////////////////////////////////////////////////// 196 | //////////////n9+/9z4Kn/A8Bf/wGoU/8Ax2L/OtOG/2zepP9s3qT/bN6k/2zepP9s3qT/bN6k/2ze 197 | pP9s3qT/bN6k/2zepP9s3qT/bN6k/2zepP9s3qT/bN6k/2zepP9s3qT/bN6k/2zepP9s3qT/bN6k/2ze 198 | pP9s3qT/bN6k/2zepP9s3qT/bN6k/2zepP8t0H3/AcVh/wHGYk8BxmJPAcZiTwHGYk8BxmJPAcZiTwHG 199 | Yk8BxmJPAcZiTwHGYk8BxmJPAcZiTwHGYk8BxmJPAcZiTwHGYk8BxmJPAcZiTwHGYk8BxmJPAcZiTwHG 200 | Yk8BxmJPAcZiTwHGYk8BxmJPAcZiTwHGYk8BxmJPAcZiTwHGYk8BxmJP////Af///wH///8B////Af// 201 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 202 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 203 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 204 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 205 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 206 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 207 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 208 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 209 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 210 | /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// 211 | /wH///8B////Af///wH///8B////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 212 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 213 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 214 | 215 | 216 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/OpaqueMail.TestClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C1BC8A46-7219-4831-A917-2BD87CF8D972} 8 | WinExe 9 | Properties 10 | OpaqueMail.TestClient 11 | OpaqueMail.TestClient 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | OpaqueMail32.ico 36 | 37 | 38 | true 39 | 40 | 41 | OpaqueMail.pfx 42 | 43 | 44 | 45 | ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Form 62 | 63 | 64 | Form1.cs 65 | 66 | 67 | 68 | 69 | Form1.cs 70 | Designer 71 | 72 | 73 | ResXFileCodeGenerator 74 | Resources.Designer.cs 75 | Designer 76 | 77 | 78 | True 79 | Resources.resx 80 | 81 | 82 | 83 | 84 | SettingsSingleFileGenerator 85 | Settings.Designer.cs 86 | 87 | 88 | True 89 | Settings.settings 90 | True 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | {9f1402f2-d701-43a5-9ad6-cfa926c31dce} 99 | OpaqueMail.CertHelper 100 | 101 | 102 | {bf21d27f-72ad-492e-8219-6c82c2330c72} 103 | OpaqueMail 104 | 105 | 106 | 107 | 108 | 109 | 110 | 117 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/OpaqueMail32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bertjohnson/OpaqueMail/63d55f213a0dd6cf91ddd44e00b63526b083ac17/OpaqueMail.TestClient/OpaqueMail32.ico -------------------------------------------------------------------------------- /OpaqueMail.TestClient/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System; 17 | using System.Windows.Forms; 18 | 19 | namespace OpaqueMail.TestClient 20 | { 21 | /// 22 | /// Main program thread of OpaqueMail test client. 23 | /// 24 | static class Program 25 | { 26 | /// 27 | /// The main entry point for the application. 28 | /// 29 | [STAThread] 30 | static void Main() 31 | { 32 | Application.EnableVisualStyles(); 33 | Application.SetCompatibleTextRenderingDefault(false); 34 | Application.Run(new Form1()); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /OpaqueMail.TestClient/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Reflection; 17 | using System.Runtime.InteropServices; 18 | 19 | // General Information about an assembly is controlled through the following 20 | // set of attributes. Change these attribute values to modify the information 21 | // associated with an assembly. 22 | [assembly: AssemblyTitle("OpaqueMail.TestClient")] 23 | [assembly: AssemblyDescription(".NET email library with full support for IMAP, POP3, SMTP, and S/MIME encryption.")] 24 | [assembly: AssemblyConfiguration("")] 25 | [assembly: AssemblyCompany("Bert Johnson")] 26 | [assembly: AssemblyProduct("OpaqueMail")] 27 | [assembly: AssemblyCopyright("Copyright © 2013-2017 Bert Johnson")] 28 | [assembly: AssemblyTrademark("")] 29 | [assembly: AssemblyCulture("")] 30 | 31 | // Setting ComVisible to false makes the types in this assembly not visible 32 | // to COM components. If you need to access a type in this assembly from 33 | // COM, set the ComVisible attribute to true on that type. 34 | [assembly: ComVisible(false)] 35 | 36 | // The following GUID is for the ID of the typelib if this project is exposed to COM 37 | [assembly: Guid("5eba3ce6-92e5-453e-91d5-19b740931c73")] 38 | 39 | // Version information for an assembly consists of the following four values: 40 | // 41 | // Major Version 42 | // Minor Version 43 | // Build Number 44 | // Revision 45 | // 46 | // You can specify all the values or you can default the Build and Revision Numbers 47 | // by using the '*' as shown below: 48 | // [assembly: AssemblyVersion("1.0.*")] 49 | [assembly: AssemblyVersion("2.5.4")] 50 | [assembly: AssemblyFileVersion("2.5.4")] 51 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18046 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace OpaqueMail.TestClient.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpaqueMail.TestClient.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18046 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace OpaqueMail.TestClient.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OpaqueMail.TestClient/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /OpaqueMail.doxygen.header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $projectname: $title 9 | $title 10 | 11 | 12 | 13 | 14 | $treeview 15 | $search 16 | $mathjax 17 | 18 | $extrastylesheet 19 | 20 | 21 |
22 | 23 | 24 |
25 |
26 |

OpaqueMail OpaqueMail

27 | Secure .NET email library and proxy with full support for SMTP, IMAP, POP3, and S/MIME. Free and open source. 28 |
29 | 30 | 31 | 34 | 37 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /OpaqueMail.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bertjohnson/OpaqueMail/63d55f213a0dd6cf91ddd44e00b63526b083ac17/OpaqueMail.nupkg -------------------------------------------------------------------------------- /OpaqueMail.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpaqueMail", "OpaqueMail\OpaqueMail.csproj", "{BF21D27F-72AD-492E-8219-6C82C2330C72}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpaqueMail.TestClient", "OpaqueMail.TestClient\OpaqueMail.TestClient.csproj", "{C1BC8A46-7219-4831-A917-2BD87CF8D972}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1E3374C3-7C9B-4FAA-B1C6-B3609E903428}" 11 | ProjectSection(SolutionItems) = preProject 12 | CHANGELOG.md = CHANGELOG.md 13 | LICENSE.md = LICENSE.md 14 | OpaqueMail.doxygen = OpaqueMail.doxygen 15 | OpaqueMail.doxygen.header.html = OpaqueMail.doxygen.header.html 16 | OpaqueMail.nupkg = OpaqueMail.nupkg 17 | README.md = README.md 18 | EndProjectSection 19 | EndProject 20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpaqueMail.CertHelper", "OpaqueMail.CertHelper\OpaqueMail.CertHelper.csproj", "{9F1402F2-D701-43A5-9AD6-CFA926C31DCE}" 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpaqueMail.Proxy", "OpaqueMail.Proxy\OpaqueMail.Proxy.csproj", "{FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}" 23 | EndProject 24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpaqueMail.ProxyService", "OpaqueMail.ProxyService\OpaqueMail.ProxyService.csproj", "{C8F12621-2E22-48FD-8E52-71F1B059179E}" 25 | EndProject 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpaqueMail.ProxySettings", "OpaqueMail.ProxySettings\OpaqueMail.ProxySettings.csproj", "{EE9F6184-F918-4FC0-9018-3019DFB8A408}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | CD_ROM|Any CPU = CD_ROM|Any CPU 31 | CD_ROM|ARM = CD_ROM|ARM 32 | CD_ROM|x64 = CD_ROM|x64 33 | CD_ROM|x86 = CD_ROM|x86 34 | Debug|Any CPU = Debug|Any CPU 35 | Debug|ARM = Debug|ARM 36 | Debug|x64 = Debug|x64 37 | Debug|x86 = Debug|x86 38 | DVD-5|Any CPU = DVD-5|Any CPU 39 | DVD-5|ARM = DVD-5|ARM 40 | DVD-5|x64 = DVD-5|x64 41 | DVD-5|x86 = DVD-5|x86 42 | Release|Any CPU = Release|Any CPU 43 | Release|ARM = Release|ARM 44 | Release|x64 = Release|x64 45 | Release|x86 = Release|x86 46 | SingleImage|Any CPU = SingleImage|Any CPU 47 | SingleImage|ARM = SingleImage|ARM 48 | SingleImage|x64 = SingleImage|x64 49 | SingleImage|x86 = SingleImage|x86 50 | EndGlobalSection 51 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 52 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU 53 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.CD_ROM|Any CPU.Build.0 = Release|Any CPU 54 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.CD_ROM|ARM.ActiveCfg = Release|Any CPU 55 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.CD_ROM|x64.ActiveCfg = Release|Any CPU 56 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.CD_ROM|x86.ActiveCfg = Release|Any CPU 57 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 58 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Debug|Any CPU.Build.0 = Debug|Any CPU 59 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Debug|ARM.ActiveCfg = Debug|Any CPU 60 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Debug|x64.ActiveCfg = Debug|Any CPU 61 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Debug|x86.ActiveCfg = Debug|Any CPU 62 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU 63 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.DVD-5|Any CPU.Build.0 = Debug|Any CPU 64 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.DVD-5|ARM.ActiveCfg = Debug|Any CPU 65 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.DVD-5|x64.ActiveCfg = Debug|Any CPU 66 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.DVD-5|x86.ActiveCfg = Debug|Any CPU 67 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Release|Any CPU.ActiveCfg = Release|Any CPU 68 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Release|Any CPU.Build.0 = Release|Any CPU 69 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Release|ARM.ActiveCfg = Release|Any CPU 70 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Release|x64.ActiveCfg = Release|Any CPU 71 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.Release|x86.ActiveCfg = Release|Any CPU 72 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU 73 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.SingleImage|Any CPU.Build.0 = Release|Any CPU 74 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.SingleImage|ARM.ActiveCfg = Release|Any CPU 75 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.SingleImage|x64.ActiveCfg = Release|Any CPU 76 | {BF21D27F-72AD-492E-8219-6C82C2330C72}.SingleImage|x86.ActiveCfg = Release|Any CPU 77 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU 78 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.CD_ROM|Any CPU.Build.0 = Release|Any CPU 79 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.CD_ROM|ARM.ActiveCfg = Release|Any CPU 80 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.CD_ROM|x64.ActiveCfg = Release|Any CPU 81 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.CD_ROM|x86.ActiveCfg = Release|Any CPU 82 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 83 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Debug|Any CPU.Build.0 = Debug|Any CPU 84 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Debug|ARM.ActiveCfg = Debug|Any CPU 85 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Debug|x64.ActiveCfg = Debug|Any CPU 86 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Debug|x86.ActiveCfg = Debug|Any CPU 87 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU 88 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.DVD-5|Any CPU.Build.0 = Debug|Any CPU 89 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.DVD-5|ARM.ActiveCfg = Debug|Any CPU 90 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.DVD-5|x64.ActiveCfg = Debug|Any CPU 91 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.DVD-5|x86.ActiveCfg = Debug|Any CPU 92 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Release|Any CPU.ActiveCfg = Release|Any CPU 93 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Release|Any CPU.Build.0 = Release|Any CPU 94 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Release|ARM.ActiveCfg = Release|Any CPU 95 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Release|x64.ActiveCfg = Release|Any CPU 96 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.Release|x86.ActiveCfg = Release|Any CPU 97 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU 98 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.SingleImage|Any CPU.Build.0 = Release|Any CPU 99 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.SingleImage|ARM.ActiveCfg = Release|Any CPU 100 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.SingleImage|x64.ActiveCfg = Release|Any CPU 101 | {C1BC8A46-7219-4831-A917-2BD87CF8D972}.SingleImage|x86.ActiveCfg = Release|Any CPU 102 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU 103 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.CD_ROM|Any CPU.Build.0 = Release|Any CPU 104 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.CD_ROM|ARM.ActiveCfg = Release|Any CPU 105 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.CD_ROM|x64.ActiveCfg = Release|Any CPU 106 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.CD_ROM|x86.ActiveCfg = Release|Any CPU 107 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 108 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Debug|Any CPU.Build.0 = Debug|Any CPU 109 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Debug|ARM.ActiveCfg = Debug|Any CPU 110 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Debug|x64.ActiveCfg = Debug|Any CPU 111 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Debug|x86.ActiveCfg = Debug|Any CPU 112 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU 113 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.DVD-5|Any CPU.Build.0 = Debug|Any CPU 114 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.DVD-5|ARM.ActiveCfg = Debug|Any CPU 115 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.DVD-5|x64.ActiveCfg = Debug|Any CPU 116 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.DVD-5|x86.ActiveCfg = Debug|Any CPU 117 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Release|Any CPU.ActiveCfg = Release|Any CPU 118 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Release|Any CPU.Build.0 = Release|Any CPU 119 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Release|ARM.ActiveCfg = Release|Any CPU 120 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Release|x64.ActiveCfg = Release|Any CPU 121 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.Release|x86.ActiveCfg = Release|Any CPU 122 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU 123 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.SingleImage|Any CPU.Build.0 = Release|Any CPU 124 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.SingleImage|ARM.ActiveCfg = Release|Any CPU 125 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.SingleImage|x64.ActiveCfg = Release|Any CPU 126 | {9F1402F2-D701-43A5-9AD6-CFA926C31DCE}.SingleImage|x86.ActiveCfg = Release|Any CPU 127 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU 128 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.CD_ROM|Any CPU.Build.0 = Release|Any CPU 129 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.CD_ROM|ARM.ActiveCfg = Release|Any CPU 130 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.CD_ROM|x64.ActiveCfg = Release|Any CPU 131 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.CD_ROM|x86.ActiveCfg = Release|Any CPU 132 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 133 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Debug|Any CPU.Build.0 = Debug|Any CPU 134 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Debug|ARM.ActiveCfg = Debug|Any CPU 135 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Debug|x64.ActiveCfg = Debug|Any CPU 136 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Debug|x86.ActiveCfg = Debug|Any CPU 137 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU 138 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.DVD-5|Any CPU.Build.0 = Debug|Any CPU 139 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.DVD-5|ARM.ActiveCfg = Debug|Any CPU 140 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.DVD-5|x64.ActiveCfg = Debug|Any CPU 141 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.DVD-5|x86.ActiveCfg = Debug|Any CPU 142 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Release|Any CPU.ActiveCfg = Release|Any CPU 143 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Release|Any CPU.Build.0 = Release|Any CPU 144 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Release|ARM.ActiveCfg = Release|Any CPU 145 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Release|x64.ActiveCfg = Release|Any CPU 146 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.Release|x86.ActiveCfg = Release|Any CPU 147 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU 148 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.SingleImage|Any CPU.Build.0 = Release|Any CPU 149 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.SingleImage|ARM.ActiveCfg = Release|Any CPU 150 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.SingleImage|x64.ActiveCfg = Release|Any CPU 151 | {FBDCF97D-7EF1-470D-A13F-04CAB5911D6B}.SingleImage|x86.ActiveCfg = Release|Any CPU 152 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU 153 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.CD_ROM|Any CPU.Build.0 = Release|Any CPU 154 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.CD_ROM|ARM.ActiveCfg = Release|Any CPU 155 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.CD_ROM|x64.ActiveCfg = Release|Any CPU 156 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.CD_ROM|x86.ActiveCfg = Release|Any CPU 157 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 158 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Debug|Any CPU.Build.0 = Debug|Any CPU 159 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Debug|ARM.ActiveCfg = Debug|Any CPU 160 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Debug|x64.ActiveCfg = Debug|Any CPU 161 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Debug|x86.ActiveCfg = Debug|Any CPU 162 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU 163 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.DVD-5|Any CPU.Build.0 = Debug|Any CPU 164 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.DVD-5|ARM.ActiveCfg = Debug|Any CPU 165 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.DVD-5|x64.ActiveCfg = Debug|Any CPU 166 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.DVD-5|x86.ActiveCfg = Debug|Any CPU 167 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Release|Any CPU.ActiveCfg = Release|Any CPU 168 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Release|Any CPU.Build.0 = Release|Any CPU 169 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Release|ARM.ActiveCfg = Release|Any CPU 170 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Release|x64.ActiveCfg = Release|Any CPU 171 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.Release|x86.ActiveCfg = Release|Any CPU 172 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU 173 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.SingleImage|Any CPU.Build.0 = Release|Any CPU 174 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.SingleImage|ARM.ActiveCfg = Release|Any CPU 175 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.SingleImage|x64.ActiveCfg = Release|Any CPU 176 | {C8F12621-2E22-48FD-8E52-71F1B059179E}.SingleImage|x86.ActiveCfg = Release|Any CPU 177 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU 178 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.CD_ROM|Any CPU.Build.0 = Release|Any CPU 179 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.CD_ROM|ARM.ActiveCfg = Release|Any CPU 180 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.CD_ROM|x64.ActiveCfg = Release|Any CPU 181 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.CD_ROM|x86.ActiveCfg = Release|Any CPU 182 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 183 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Debug|Any CPU.Build.0 = Debug|Any CPU 184 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Debug|ARM.ActiveCfg = Debug|Any CPU 185 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Debug|x64.ActiveCfg = Debug|Any CPU 186 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Debug|x86.ActiveCfg = Debug|Any CPU 187 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU 188 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.DVD-5|Any CPU.Build.0 = Debug|Any CPU 189 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.DVD-5|ARM.ActiveCfg = Debug|Any CPU 190 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.DVD-5|x64.ActiveCfg = Debug|Any CPU 191 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.DVD-5|x86.ActiveCfg = Debug|Any CPU 192 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Release|Any CPU.ActiveCfg = Release|Any CPU 193 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Release|Any CPU.Build.0 = Release|Any CPU 194 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Release|ARM.ActiveCfg = Release|Any CPU 195 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Release|x64.ActiveCfg = Release|Any CPU 196 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.Release|x86.ActiveCfg = Release|Any CPU 197 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU 198 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.SingleImage|Any CPU.Build.0 = Release|Any CPU 199 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.SingleImage|ARM.ActiveCfg = Release|Any CPU 200 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.SingleImage|x64.ActiveCfg = Release|Any CPU 201 | {EE9F6184-F918-4FC0-9018-3019DFB8A408}.SingleImage|x86.ActiveCfg = Release|Any CPU 202 | EndGlobalSection 203 | GlobalSection(SolutionProperties) = preSolution 204 | HideSolutionNode = FALSE 205 | EndGlobalSection 206 | EndGlobal 207 | -------------------------------------------------------------------------------- /OpaqueMail/AlternateView.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Collections.ObjectModel; 17 | using System.IO; 18 | using System.Text; 19 | 20 | namespace OpaqueMail 21 | { 22 | /// Represents the format to view an email message. 23 | public class AlternateView : Attachment 24 | { 25 | #region Public Members 26 | public TransferEncoding TransferEncoding { get; set; } 27 | #endregion Public Members 28 | 29 | #region Constructors 30 | public AlternateView() : base() 31 | { 32 | } 33 | 34 | /// Initializes a new instance of with the specified file name. 35 | /// The name of the file that contains the content for this alternate view. 36 | /// 37 | /// is null. 38 | /// The caller does not have the required permission. 39 | /// An I/O error occurred, such as a disk error. 40 | /// The access requested is not permitted by the operating system for the specified file handle, such as when access is Write or ReadWrite and the file handle is set for read-only access. 41 | public AlternateView(string fileName) : base(fileName) 42 | { 43 | } 44 | 45 | /// Initializes a new instance of with the specified file name and media type. 46 | /// The name of the file that contains the content for this alternate view. 47 | /// The MIME media type of the content. 48 | /// 49 | /// is null. 50 | /// 51 | /// is not a valid value. 52 | /// The caller does not have the required permission. 53 | /// An I/O error occurred, such as a disk error. 54 | /// The access requested is not permitted by the operating system for the specified file handle, such as when access is Write or ReadWrite and the file handle is set for read-only access. 55 | public AlternateView(string fileName, string mediaType) : base(fileName, mediaType) 56 | { 57 | } 58 | 59 | /// Initializes a new instance of with the specified file name and content type. 60 | /// The name of the file that contains the content for this alternate view. 61 | /// The type of the content. 62 | /// 63 | /// is null. 64 | /// 65 | /// is not a valid value. 66 | /// The caller does not have the required permission. 67 | /// An I/O error occurred, such as a disk error. 68 | /// The access requested is not permitted by the operating system for the specified file handle, such as when access is Write or ReadWrite and the file handle is set for read-only access. 69 | public AlternateView(string fileName, ContentType contentType) 70 | { 71 | } 72 | 73 | /// Initializes a new instance of with the specified . 74 | /// A stream that contains the content for this view. 75 | /// 76 | /// is null. 77 | public AlternateView(Stream contentStream) : base(contentStream) 78 | { 79 | } 80 | 81 | /// Initializes a new instance of with the specified and media type. 82 | /// A stream that contains the content for this attachment. 83 | /// The MIME media type of the content. 84 | /// 85 | /// is null. 86 | /// 87 | /// is not a valid value. 88 | public AlternateView(Stream contentStream, string mediaType) : base(contentStream, "", mediaType) 89 | { 90 | } 91 | 92 | /// Initializes a new instance of with the specified and . 93 | /// A stream that contains the content for this attachment. 94 | /// The type of the content. 95 | /// 96 | /// is null. 97 | /// 98 | /// is not a valid value. 99 | public AlternateView(Stream contentStream, ContentType contentType) : base(contentStream, contentType) 100 | { 101 | } 102 | #endregion Constructors 103 | 104 | #region Public Methods 105 | /// Creates a of an email message using the content specified in a . 106 | /// An object that represents an alternate view of an email message. 107 | /// The that contains the content of the email message. 108 | /// 109 | /// is null. 110 | public static AlternateView CreateAlternateViewFromString(string content) 111 | { 112 | AlternateView alternateView = new AlternateView(); 113 | alternateView.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); 114 | return alternateView; 115 | } 116 | 117 | /// Creates an of an email message using the content specified in a , the specified text encoding, and MIME media type of the content. 118 | /// An object that represents an alternate view of an email message. 119 | /// A that contains the content for this attachment. 120 | /// An . This value can be null. 121 | /// The MIME media type of the content. 122 | /// 123 | /// is null. 124 | public static AlternateView CreateAlternateViewFromString(string content, Encoding contentEncoding, string mediaType) 125 | { 126 | AlternateView alternateView = new AlternateView(); 127 | alternateView.ContentStream = new MemoryStream(contentEncoding.GetBytes(content)); 128 | alternateView.MediaType = mediaType; 129 | return alternateView; 130 | } 131 | 132 | /// Creates an of an email message using the content specified in a and the specified MIME media type of the content. 133 | /// An object that represents an alternate view of an email message. 134 | /// A that contains the content for this attachment. 135 | /// A that describes the data in . 136 | /// 137 | /// is null. 138 | public static AlternateView CreateAlternateViewFromString(string content, ContentType contentType) 139 | { 140 | AlternateView alternateView = new AlternateView(); 141 | alternateView.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); 142 | alternateView.MediaType = contentType.MediaType; 143 | return alternateView; 144 | } 145 | #endregion Public Methods 146 | } 147 | 148 | public class AlternateViewCollection : Collection 149 | { 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /OpaqueMail/Attachment.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Collections.ObjectModel; 17 | using System.IO; 18 | using System.Text; 19 | 20 | namespace OpaqueMail 21 | { 22 | public class Attachment 23 | { 24 | public string Boundary { get; set; } 25 | public string ContentId { get; set; } 26 | public string MediaType { get; set; } 27 | public string Name { get; set; } 28 | public Encoding NameEncoding { get; set; } 29 | public Stream ContentStream { get; set; } 30 | 31 | public Attachment() 32 | { 33 | ContentStream = new MemoryStream(); 34 | } 35 | 36 | public Attachment(string fileName) 37 | { 38 | FileInfo fi = new FileInfo(fileName); 39 | ContentStream = new MemoryStream(File.ReadAllBytes(fileName)); 40 | ContentStream.Seek(0, SeekOrigin.Begin); 41 | Name = fi.Name; 42 | } 43 | 44 | public Attachment(string fileName, string mediaType) 45 | { 46 | FileInfo fi = new FileInfo(fileName); 47 | ContentStream = new MemoryStream(File.ReadAllBytes(fileName)); 48 | ContentStream.Seek(0, SeekOrigin.Begin); 49 | Name = fi.Name; 50 | MediaType = mediaType; 51 | } 52 | 53 | public Attachment(string fileName, ContentType contentType) 54 | { 55 | FileInfo fi = new FileInfo(fileName); 56 | ContentStream = new MemoryStream(File.ReadAllBytes(fileName)); 57 | ContentStream.Seek(0, SeekOrigin.Begin); 58 | Name = fi.Name; 59 | 60 | MediaType = contentType.MediaType; 61 | Boundary = contentType.Boundary; 62 | } 63 | 64 | public Attachment(Stream contentStream) 65 | : this() 66 | { 67 | contentStream.CopyTo(ContentStream); 68 | ContentStream.Seek(0, SeekOrigin.Begin); 69 | } 70 | 71 | public Attachment(Stream contentStream, string name) 72 | : this() 73 | { 74 | Name = name; 75 | contentStream.CopyTo(ContentStream); 76 | ContentStream.Seek(0, SeekOrigin.Begin); 77 | } 78 | 79 | public Attachment(Stream contentStream, string name, string mediaType) 80 | : this() 81 | { 82 | Name = name; 83 | contentStream.CopyTo(ContentStream); 84 | ContentStream.Seek(0, SeekOrigin.Begin); 85 | MediaType = mediaType; 86 | } 87 | 88 | public Attachment(Stream contentStream, ContentType contentType) 89 | : this() 90 | { 91 | contentStream.CopyTo(ContentStream); 92 | ContentStream.Seek(0, SeekOrigin.Begin); 93 | Name = contentType.Name; 94 | MediaType = contentType.MediaType; 95 | Boundary = contentType.Boundary; 96 | } 97 | 98 | /// Releases the unmanaged resources used by the and optionally releases the managed resources. 99 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources. 100 | protected void Dispose(bool disposing) 101 | { 102 | if (ContentStream != null) 103 | ContentStream.Dispose(); 104 | } 105 | } 106 | 107 | public class AttachmentCollection : Collection 108 | { 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /OpaqueMail/Constants.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Linq; 19 | using System.Text; 20 | using System.Threading.Tasks; 21 | 22 | namespace OpaqueMail 23 | { 24 | /// 25 | /// Define constants used by other OpaqueMail classes. 26 | /// 27 | public static class Constants 28 | { 29 | /// 30 | /// Extra large buffer size for bit shuffling. 31 | /// 32 | public const int HUGEBUFFERSIZE = 16777216; 33 | 34 | /// 35 | /// Large buffer size for bit shuffling. 36 | /// 37 | public const int LARGEBUFFERSIZE = 1048576; 38 | 39 | /// 40 | /// Small buffer size for bit shuffling. 41 | /// 42 | public const int SMALLBUFFERSIZE = 65536; 43 | 44 | /// 45 | /// Tiny buffer size for bit shuffling. 46 | /// 47 | public const int TINYBUFFERSIZE = 2048; 48 | 49 | /// 50 | /// Tiny buffer size for string concatenation. 51 | /// 52 | public const int TINYSBSIZE = 256; 53 | 54 | /// 55 | /// Small buffer size for string concatenation. 56 | /// 57 | public const int SMALLSBSIZE = 2048; 58 | 59 | /// 60 | /// Medium buffer size for string concatenation. 61 | /// 62 | public const int MEDIUMSBSIZE = 32768; 63 | 64 | /// 65 | /// Large buffer size for string concatenation. 66 | /// 67 | public const int LARGESBSIZE = 1048576; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /OpaqueMail/LockAsync.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Threading; 19 | using System.Threading.Tasks; 20 | 21 | namespace OpaqueMail 22 | { 23 | /// 24 | /// Thread-safe asynchronous lock. 25 | /// 26 | /// 27 | /// See AsyncSemaphore and AsyncLock code by Stephen Toub. http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspx 28 | /// 29 | public class AsyncLock 30 | { 31 | private readonly AsyncSemaphore semaphore; 32 | private readonly Task releaser; 33 | 34 | public AsyncLock() 35 | { 36 | semaphore = new AsyncSemaphore(1); 37 | releaser = Task.FromResult(new Releaser(this)); 38 | } 39 | 40 | public Task LockAsync() 41 | { 42 | Task wait = semaphore.WaitAsync(); 43 | return wait.IsCompleted ? releaser : wait.ContinueWith((_, state) => new Releaser((AsyncLock)state), this, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); 44 | } 45 | 46 | /// 47 | /// Helper class for unlocking. 48 | /// 49 | public struct Releaser : IDisposable 50 | { 51 | private readonly AsyncLock lockToRelease; 52 | 53 | internal Releaser(AsyncLock toRelease) 54 | { 55 | lockToRelease = toRelease; 56 | } 57 | 58 | public void Dispose() 59 | { 60 | if (lockToRelease != null) 61 | lockToRelease.semaphore.Release(); 62 | } 63 | } 64 | } 65 | 66 | /// 67 | /// Thread-safe asynchronous semaphore. 68 | /// 69 | /// 70 | /// See AsyncSemaphore and AsyncLock code by Stephen Toub. http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspx 71 | /// 72 | public class AsyncSemaphore 73 | { 74 | private readonly static Task completed = Task.FromResult(true); 75 | private readonly Queue> waiters = new Queue>(); 76 | private int semaphoreCount; 77 | 78 | public AsyncSemaphore(int initialCount) 79 | { 80 | if (initialCount < 0) 81 | throw new ArgumentOutOfRangeException("Initial semaphore count out of range."); 82 | 83 | semaphoreCount = initialCount; 84 | } 85 | 86 | public Task WaitAsync() 87 | { 88 | lock (waiters) 89 | { 90 | if (semaphoreCount > 0) 91 | { 92 | --semaphoreCount; 93 | return completed; 94 | } 95 | else 96 | { 97 | TaskCompletionSource waiter = new TaskCompletionSource(); 98 | waiters.Enqueue(waiter); 99 | return waiter.Task; 100 | } 101 | } 102 | } 103 | 104 | public void Release() 105 | { 106 | TaskCompletionSource toRelease = null; 107 | 108 | lock (waiters) 109 | { 110 | if (waiters.Count > 0) 111 | toRelease = waiters.Dequeue(); 112 | else 113 | ++semaphoreCount; 114 | } 115 | 116 | if (toRelease != null) 117 | toRelease.SetResult(true); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /OpaqueMail/MailMessage.Smime.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Security.Cryptography.X509Certificates; 17 | 18 | namespace OpaqueMail 19 | { 20 | /// 21 | /// Represents an email message that was either received using the ImapClient or Pop3Client classes or will be sent using the SmtpClient class. 22 | /// Includes OpaqueMail extensions to facilitate handling of secure PGP and S/MIME messages. 23 | /// 24 | public partial class MailMessage 25 | { 26 | #region Public Members 27 | /// Encrypt the email's envelope. When SmimeSign is true, encryption is the second S/MIME operation. 28 | public bool SmimeEncryptedEnvelope { get; set; } 29 | /// Determine how the S/MIME envelope will be encrypted. 30 | /// Type of subject identifier to use. 31 | /// The default of "IssuerAndSerialNumber" is recommended for most use cases. 32 | public SmimeEncryptionOptionFlags SmimeEncryptionOptionFlags { get; set; } 33 | /// Whether S/MIME settings for encryption and signing are explicitly required or only preferred. 34 | public SmimeSettingsMode SmimeSettingsMode { get; set; } 35 | /// Sign the email. When true, signing is the first S/MIME operation. 36 | public bool SmimeSigned { get; set; } 37 | /// 38 | /// Certificate used when signing messages. 39 | /// Requires private key. 40 | /// 41 | public X509Certificate2 SmimeSigningCertificate { get; set; } 42 | /// Certificate chain used to sign the message. 43 | public X509Certificate2Collection SmimeSigningCertificateChain { get; set; } 44 | /// Determine how the S/MIME message will be signed. 45 | public SmimeSigningOptionFlags SmimeSigningOptionFlags { get; set; } 46 | /// Triple-wrap the email by signing, then encrypting the envelope, then signing the encrypted envelope. 47 | public bool SmimeTripleWrapped { get; set; } 48 | #endregion Public Members 49 | 50 | #region Protected Members 51 | /// Text delimiting S/MIME message parts related to signatures. 52 | protected string SmimeSignedCmsBoundaryName = "OpaqueMail-signature-boundary"; 53 | /// Text delimiting MIME message parts in triple wrapped messages. 54 | protected string SmimeTripleSignedCmsBoundaryName = "OpaqueMail-triple-signature-boundary"; 55 | #endregion Protected Members 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /OpaqueMail/Mailbox.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | 19 | namespace OpaqueMail 20 | { 21 | /// 22 | /// Represents an IMAP mailbox. 23 | /// 24 | public class Mailbox 25 | { 26 | /// List of FETCH commands returned by QRESYNC. 27 | public List FetchList { get; set; } 28 | /// Standard IMAP flags associated with this mailbox. 29 | public HashSet Flags { get; set; } 30 | /// Mailbox hierarchy delimiting string. 31 | public string HierarchyDelimiter { get; set; } 32 | /// Name of the mailbox. 33 | public string Name { get; set; } 34 | /// True if ModSeq is explicitly unavailable. 35 | public bool NoModSeq { get; set; } 36 | /// Permanent IMAP flags associated with this mailbox. 37 | public HashSet PermanentFlags { get; set; } 38 | /// List of message IDs that have disappeared since the last QRESYNC. 39 | public string VanishedList { get; set; } 40 | 41 | /// Number of messages in the mailbox. Null if COUNT was not parsed. 42 | public int? Count { get; set; } 43 | /// Highest ModSeq in the mailbox. Null if HIGHESTMODSEQ was not parsed. 44 | public int? HighestModSeq { get; set; } 45 | /// Number of recent messages in the mailbox. Null if RECENT was not parsed. 46 | public int? Recent { get; set; } 47 | /// Expected next UID for the mailbox. Null if UIDNEXT was not parsed. 48 | public int? UidNext { get; set; } 49 | /// UID validity for the mailbox. Null if UIDVALIDITY was not parsed. 50 | public int? UidValidity { get; set; } 51 | 52 | #region Constructors 53 | /// 54 | /// Default constructor. 55 | /// 56 | public Mailbox() 57 | { 58 | FetchList = new List(); 59 | Flags = new HashSet(); 60 | NoModSeq = false; 61 | PermanentFlags = new HashSet(); 62 | 63 | Count = null; 64 | HighestModSeq = null; 65 | Recent = null; 66 | UidNext = null; 67 | UidValidity = null; 68 | } 69 | 70 | /// 71 | /// Parse IMAP output from an EXAMINE or SELECT command. 72 | /// 73 | /// Name of the mailbox. 74 | /// Raw IMAP output of an EXAMINE or SELECT command. 75 | public Mailbox(string name, string imapResponse) 76 | : this() 77 | { 78 | // Escape modifed UTF-7 encoding for ampersands or Unicode characters. 79 | Name = Functions.FromModifiedUTF7(name); 80 | 81 | string[] responseLines = imapResponse.Replace("\r", "").Split('\n'); 82 | foreach (string responseLine in responseLines) 83 | { 84 | if (responseLine.StartsWith("* FLAGS (")) 85 | { 86 | string[] flags = responseLine.Substring(9, responseLine.Length - 10).Split(' '); 87 | foreach (string flag in flags) 88 | { 89 | if (!Flags.Contains(flag)) 90 | Flags.Add(flag); 91 | } 92 | } 93 | else if (responseLine.StartsWith("* OK [NOMODSEQ]")) 94 | NoModSeq = true; 95 | else if (responseLine.StartsWith("* OK [HIGHESTMODSEQ ")) 96 | { 97 | string highestModSeq = responseLine.Substring(20, responseLine.IndexOf("]") - 20); 98 | int highestModSeqValue; 99 | int.TryParse(highestModSeq, out highestModSeqValue); 100 | HighestModSeq = highestModSeqValue; 101 | } 102 | else if (responseLine.StartsWith("* OK [PERMANENTFLAGS (")) 103 | { 104 | string[] permanentFlags = responseLine.Substring(22, responseLine.IndexOf("]") - 22).Split(' '); 105 | foreach (string permanentFlag in permanentFlags) 106 | { 107 | if (!PermanentFlags.Contains(permanentFlag)) 108 | PermanentFlags.Add(permanentFlag); 109 | } 110 | } 111 | else if (responseLine.StartsWith("* OK [UIDNEXT ")) 112 | { 113 | string uidNext = responseLine.Substring(14, responseLine.IndexOf("]") - 14); 114 | int uidNextValue; 115 | int.TryParse(uidNext, out uidNextValue); 116 | UidNext = uidNextValue; 117 | } 118 | else if (responseLine.StartsWith("* OK [UIDVALIDITY ")) 119 | { 120 | string uidValidity = responseLine.Substring(18, responseLine.IndexOf("]") - 18); 121 | int UidValidityValue; 122 | int.TryParse(uidValidity, out UidValidityValue); 123 | UidValidity = UidValidityValue; 124 | } 125 | else if (responseLine.StartsWith("* VANISHED ")) 126 | VanishedList = responseLine.Substring(11); 127 | else if (responseLine.IndexOf(" FETCH ", StringComparison.Ordinal) > -1) 128 | FetchList.Add(responseLine); 129 | else if (responseLine.EndsWith(" EXISTS")) 130 | { 131 | string existsCount = responseLine.Substring(2, responseLine.Length - 9); 132 | int existsCountValue; 133 | int.TryParse(existsCount, out existsCountValue); 134 | Count = existsCountValue; 135 | } 136 | else if (responseLine.EndsWith(" RECENT")) 137 | { 138 | string recentCount = responseLine.Substring(2, responseLine.Length - 9); 139 | int recentCountValue; 140 | int.TryParse(recentCount, out recentCountValue); 141 | Recent = recentCountValue; 142 | } 143 | } 144 | } 145 | 146 | /// 147 | /// Parse IMAP output from a LIST, LSUB, or XLIST command. 148 | /// 149 | /// Raw output line from a LIST, LSUB, or XLIST command. 150 | /// 151 | public static Mailbox CreateFromList(string lineFromListCommand) 152 | { 153 | // Ensure the list of flags is contained on this line. 154 | int startsFlagList = lineFromListCommand.IndexOf("("); 155 | int endFlagList = lineFromListCommand.IndexOf(")", startsFlagList + 1); 156 | if (startsFlagList > -1 && endFlagList > -1) 157 | { 158 | Mailbox mailbox = new Mailbox(); 159 | 160 | string[] flags = lineFromListCommand.Substring(startsFlagList + 1, endFlagList - startsFlagList - 1).Split(' '); 161 | foreach (string flag in flags) 162 | { 163 | if (!mailbox.Flags.Contains(flag)) 164 | mailbox.Flags.Add(flag); 165 | } 166 | 167 | // Ensure the hierarchy delimiter and name are returned. 168 | string[] remainingParts = lineFromListCommand.Substring(endFlagList + 2).Split(new char[] { ' ' }, 2); 169 | if (remainingParts.Length == 2) 170 | { 171 | mailbox.HierarchyDelimiter = remainingParts[0].Replace("\"", ""); 172 | 173 | // Escape modifed UTF-7 encoding for ampersands or Unicode characters. 174 | mailbox.Name = Functions.FromModifiedUTF7(remainingParts[1].Replace("\"", "")); 175 | 176 | return mailbox; 177 | } 178 | } 179 | 180 | // No valid mailbox listing found, so return null. 181 | return null; 182 | } 183 | #endregion Constructors 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /OpaqueMail/OpaqueMail.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {BF21D27F-72AD-492E-8219-6C82C2330C72} 8 | Library 9 | Properties 10 | OpaqueMail 11 | OpaqueMail 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | true 34 | 35 | 36 | OpaqueMail.pfx 37 | 38 | 39 | 40 | ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll 41 | True 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 87 | -------------------------------------------------------------------------------- /OpaqueMail/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System.Reflection; 17 | using System.Runtime.CompilerServices; 18 | using System.Runtime.InteropServices; 19 | 20 | // General Information about an assembly is controlled through the following 21 | // set of attributes. Change these attribute values to modify the information 22 | // associated with an assembly. 23 | [assembly: AssemblyTitle("OpaqueMail")] 24 | [assembly: AssemblyDescription(".NET email library with full support for IMAP, POP3, SMTP, and S/MIME encryption.")] 25 | [assembly: AssemblyConfiguration("")] 26 | [assembly: AssemblyCompany("Bert Johnson")] 27 | [assembly: AssemblyProduct("OpaqueMail")] 28 | [assembly: AssemblyCopyright("Copyright © 2013-2017 Bert Johnson")] 29 | [assembly: AssemblyTrademark("")] 30 | [assembly: AssemblyCulture("")] 31 | 32 | // Setting ComVisible to false makes the types in this assembly not visible 33 | // to COM components. If you need to access a type in this assembly from 34 | // COM, set the ComVisible attribute to true on that type. 35 | [assembly: ComVisible(false)] 36 | 37 | // The following GUID is for the ID of the typelib if this project is exposed to COM 38 | [assembly: Guid("0ee540e1-57f7-4188-81b1-4dede5ff78fc")] 39 | 40 | // Version information for an assembly consists of the following four values: 41 | // 42 | // Major Version 43 | // Minor Version 44 | // Build Number 45 | // Revision 46 | // 47 | // You can specify all the values or you can default the Build and Revision Numbers 48 | // by using the '*' as shown below: 49 | // [assembly: AssemblyVersion("1.0.*")] 50 | [assembly: AssemblyVersion("2.5.4")] 51 | [assembly: AssemblyFileVersion("2.5.4")] 52 | -------------------------------------------------------------------------------- /OpaqueMail/Smtp/SmtpClient.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * OpaqueMail (https://opaquemail.org/). 3 | * 4 | * Licensed according to the MIT License (http://mit-license.org/). 5 | * 6 | * Copyright © Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 7 | * 8 | * 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: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * 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. 13 | * 14 | */ 15 | 16 | using System; 17 | using System.IO; 18 | using System.Net; 19 | using System.Net.Security; 20 | using System.Net.Sockets; 21 | using System.Security.Authentication; 22 | using System.Security.Cryptography; 23 | using System.Security.Cryptography.Pkcs; 24 | using System.Text; 25 | using System.Threading.Tasks; 26 | 27 | namespace OpaqueMail 28 | { 29 | /// 30 | /// Allows applications to send email by using the Simple Mail Transport Protocol (SMTP). 31 | /// Includes OpaqueMail extensions to facilitate sending of secure S/MIME messages. 32 | /// 33 | public partial class SmtpClient : System.Net.Mail.SmtpClient 34 | { 35 | #region Public Members 36 | /// Allowed protocols when EnableSSL is true. 37 | public SslProtocols SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; 38 | #endregion Public Members 39 | 40 | #region Private Members 41 | /// Buffer used during various S/MIME operations. 42 | private byte[] buffer = new byte[Constants.HUGEBUFFERSIZE]; 43 | #endregion Private Members 44 | 45 | #region Constructors 46 | /// 47 | /// Initializes a new instance of the OpaqueMail.SmtpClient class by using configuration file settings. 48 | /// 49 | public SmtpClient() 50 | : base() 51 | { 52 | SmimeAlgorithmIdentifier = new AlgorithmIdentifier(new Oid("2.16.840.1.101.3.4.1.42")); 53 | SmimeValidCertificates = null; 54 | 55 | RandomizeBoundaryNames(); 56 | 57 | EnableSsl = true; 58 | } 59 | /// 60 | /// Initializes a new instance of the OpaqueMail.SmtpClient class that sends email by using the specified SMTP server. 61 | /// 62 | /// Name or IP of the host used for SMTP transactions. 63 | public SmtpClient(string host) 64 | : base(host) 65 | { 66 | SmimeAlgorithmIdentifier = new AlgorithmIdentifier(new Oid("2.16.840.1.101.3.4.1.42")); 67 | SmimeValidCertificates = null; 68 | 69 | RandomizeBoundaryNames(); 70 | } 71 | /// 72 | /// Initializes a new instance of the OpaqueMail.SmtpClient class that sends email by using the specified SMTP server and port. 73 | /// 74 | /// Name or IP of the host used for SMTP transactions. 75 | /// Port to be used by the host. 76 | public SmtpClient(string host, int port) 77 | : base(host, port) 78 | { 79 | SmimeAlgorithmIdentifier = new AlgorithmIdentifier(new Oid("2.16.840.1.101.3.4.1.42")); 80 | SmimeValidCertificates = null; 81 | 82 | RandomizeBoundaryNames(); 83 | } 84 | #endregion Constructors 85 | 86 | #region Public Methods 87 | /// 88 | /// Sends the specified message to an SMTP server for delivery. 89 | /// 90 | /// An OpaqueMail.MailMessage that contains the message to send. 91 | public void Send(MailMessage message) 92 | { 93 | Task.Run(() => SendAsync(message)).Wait(); 94 | } 95 | 96 | /// 97 | /// Sends the specified message to an SMTP server for delivery. 98 | /// 99 | /// An OpaqueMail.MailMessage that contains the message to send. 100 | public async Task SendAsync(MailMessage message) 101 | { 102 | // If the message isn't encoded, do so now. 103 | if (string.IsNullOrEmpty(message.RawBody)) 104 | message.Prepare(); 105 | 106 | // Perform requested S/MIME signing and/or encryption. 107 | message.SmimePrepare(this); 108 | string rawBody = message.RawBody; 109 | 110 | // Connect to the SMTP server. 111 | TcpClient SmtpTcpClient = new TcpClient(); 112 | SmtpTcpClient.Connect(Host, Port); 113 | Stream SmtpStream = SmtpTcpClient.GetStream(); 114 | 115 | // Use stream readers and writers to simplify I/O. 116 | StreamReader reader = new StreamReader(SmtpStream); 117 | StreamWriter writer = new StreamWriter(SmtpStream); 118 | writer.AutoFlush = true; 119 | 120 | // Read the welcome message. 121 | string response = await reader.ReadLineAsync(); 122 | 123 | // Send EHLO and find out server capabilities. 124 | await writer.WriteLineAsync("EHLO " + Host); 125 | char[] charBuffer = new char[Constants.SMALLBUFFERSIZE]; 126 | int bytesRead = await reader.ReadAsync(charBuffer, 0, Constants.SMALLBUFFERSIZE); 127 | response = new string(charBuffer, 0, bytesRead); 128 | if (!response.StartsWith("2")) 129 | throw new SmtpException("Unable to connect to remote server '" + Host + "'. Sent 'EHLO' and received '" + response + "'."); 130 | 131 | // Stand up a TLS/SSL stream. 132 | if (EnableSsl) 133 | { 134 | await writer.WriteLineAsync("STARTTLS"); 135 | response = await reader.ReadLineAsync(); 136 | if (!response.StartsWith("2")) 137 | throw new SmtpException("Unable to start TLS/SSL protection with '" + Host + "'. Received '" + response + "'."); 138 | 139 | SmtpStream = new SslStream(SmtpStream); 140 | ((SslStream)SmtpStream).AuthenticateAsClient(Host, null, SslProtocols, true); 141 | 142 | reader = new StreamReader(SmtpStream); 143 | writer = new StreamWriter(SmtpStream); 144 | writer.AutoFlush = true; 145 | 146 | await writer.WriteLineAsync("EHLO " + Host); 147 | bytesRead = await reader.ReadAsync(charBuffer, 0, Constants.SMALLBUFFERSIZE); 148 | response = new string(charBuffer, 0, bytesRead); 149 | } 150 | 151 | // Authenticate using the AUTH LOGIN command. 152 | if (Credentials != null) 153 | { 154 | NetworkCredential cred = (NetworkCredential)Credentials; 155 | await writer.WriteLineAsync("AUTH LOGIN"); 156 | response = await reader.ReadLineAsync(); 157 | if (!response.StartsWith("3")) 158 | throw new SmtpException("Unable to authenticate with server '" + Host + "'. Received '" + response + "'."); 159 | await writer.WriteLineAsync(Functions.ToBase64String(cred.UserName)); 160 | string tempResponse = await reader.ReadLineAsync(); 161 | await writer.WriteLineAsync(Functions.ToBase64String(cred.Password)); 162 | response = await reader.ReadLineAsync(); 163 | if (!response.StartsWith("2")) 164 | throw new SmtpException("Unable to authenticate with server '" + Host + "'. Received '" + response + "'."); 165 | } 166 | 167 | // Build our raw headers block. 168 | StringBuilder rawHeaders = new StringBuilder(Constants.SMALLSBSIZE); 169 | 170 | // Specify who the message is from. 171 | rawHeaders.Append(Functions.SpanHeaderLines("From: " + Functions.EncodeMailHeader(Functions.ToMailAddressString(message.From))) + "\r\n"); 172 | await writer.WriteLineAsync("MAIL FROM:<" + message.From.Address + ">"); 173 | response = await reader.ReadLineAsync(); 174 | if (!response.StartsWith("2")) 175 | throw new SmtpException("Exception communicating with server '" + Host + "'. Sent 'MAIL FROM' and received '" + response + "'."); 176 | 177 | // Identify all recipients of the message. 178 | if (message.To.Count > 0) 179 | rawHeaders.Append(Functions.SpanHeaderLines("To: " + Functions.EncodeMailHeader(message.To.ToString())) + "\r\n"); 180 | foreach (MailAddress address in message.To) 181 | { 182 | await writer.WriteLineAsync("RCPT TO:<" + address.Address + ">"); 183 | response = await reader.ReadLineAsync(); 184 | if (!response.StartsWith("2")) 185 | throw new SmtpException("Exception communicating with server '" + Host + "'. Sent 'RCPT TO' and received '" + response + "'."); 186 | } 187 | 188 | if (message.CC.Count > 0) 189 | rawHeaders.Append(Functions.SpanHeaderLines("CC: " + Functions.EncodeMailHeader(message.CC.ToString())) + "\r\n"); 190 | foreach (MailAddress address in message.CC) 191 | { 192 | await writer.WriteLineAsync("RCPT TO:<" + address.Address + ">"); 193 | response = await reader.ReadLineAsync(); 194 | if (!response.StartsWith("2")) 195 | throw new SmtpException("Exception communicating with server '" + Host + "'. Sent 'RCPT TO' and received '" + response + "'."); 196 | } 197 | 198 | foreach (MailAddress address in message.Bcc) 199 | { 200 | await writer.WriteLineAsync("RCPT TO:<" + address.Address + ">"); 201 | response = await reader.ReadLineAsync(); 202 | if (!response.StartsWith("2")) 203 | throw new SmtpException("Exception communicating with server '" + Host + "'. Sent 'RCPT TO' and received '" + response + "'."); 204 | } 205 | 206 | // Ensure a content type is set. 207 | if (string.IsNullOrEmpty(message.ContentType)) 208 | { 209 | if (Functions.AppearsHTML(message.Body)) 210 | message.ContentType = "text/html"; 211 | else 212 | message.ContentType = "text/plain"; 213 | } 214 | message.Headers["Content-Type"] = message.ContentType + (!string.IsNullOrEmpty(message.CharSet) ? "; charset=\"" + message.CharSet + "\"" : ""); 215 | 216 | // If the body hasn't been processed, handle encoding of extended characters. 217 | if (string.IsNullOrEmpty(rawBody) && !string.IsNullOrEmpty(message.Body)) 218 | { 219 | bool extendedCharacterFound = false; 220 | foreach (char headerCharacter in message.Body.ToCharArray()) 221 | { 222 | if (headerCharacter > 127) 223 | { 224 | extendedCharacterFound = true; 225 | break; 226 | } 227 | } 228 | 229 | if (extendedCharacterFound) 230 | { 231 | message.ContentTransferEncoding = "base64"; 232 | message.Body = Functions.ToBase64String(message.Body); 233 | } 234 | 235 | rawBody = message.Body; 236 | } 237 | 238 | if (!string.IsNullOrEmpty(message.ContentTransferEncoding)) 239 | message.Headers["Content-Transfer-Encoding"] = message.ContentTransferEncoding; 240 | 241 | // Send the raw message. 242 | await writer.WriteLineAsync("DATA"); 243 | response = await reader.ReadLineAsync(); 244 | if (!response.StartsWith("3")) 245 | throw new SmtpException("Exception communicating with server '" + Host + "'. Sent 'DATA' and received '" + response + "'."); 246 | 247 | rawHeaders.Append(Functions.SpanHeaderLines("Subject: " + Functions.EncodeMailHeader(message.Subject, 32)) + "\r\n"); 248 | foreach (string rawHeader in message.Headers) 249 | { 250 | switch (rawHeader.ToUpper()) 251 | { 252 | case "BCC": 253 | case "CC": 254 | case "FROM": 255 | case "SUBJECT": 256 | case "TO": 257 | break; 258 | default: 259 | rawHeaders.Append(Functions.SpanHeaderLines(rawHeader + ": " + message.Headers[rawHeader]) + "\r\n"); 260 | break; 261 | } 262 | } 263 | 264 | await writer.WriteAsync(rawHeaders.ToString() + "\r\n" + rawBody + "\r\n.\r\n"); 265 | 266 | response = await reader.ReadLineAsync(); 267 | if (!response.StartsWith("2")) 268 | throw new SmtpException("Exception communicating with server '" + Host + "'. Sent message and received '" + response + "'."); 269 | 270 | // Clean up this connection. 271 | await writer.WriteLineAsync("QUIT"); 272 | 273 | writer.Dispose(); 274 | reader.Dispose(); 275 | 276 | SmtpStream.Dispose(); 277 | SmtpTcpClient.Close(); 278 | } 279 | #endregion Public Methods 280 | 281 | #region Private Methods 282 | /// 283 | /// Ensure boundary names are unique. 284 | /// 285 | private void RandomizeBoundaryNames() 286 | { 287 | string boundaryRandomness = ""; 288 | Random randomGenerator = new Random(); 289 | 290 | // Append 10 random characters. 291 | for (int i = 0; i < 10; i++) 292 | { 293 | int nextCharacter = randomGenerator.Next(1, 36); 294 | if (nextCharacter > 26) 295 | boundaryRandomness += (char)(47 + nextCharacter); 296 | else 297 | boundaryRandomness += (char)(64 + nextCharacter); 298 | } 299 | 300 | SmimeAlternativeViewBoundaryName += "-" + boundaryRandomness; 301 | SmimeBoundaryName += "-" + boundaryRandomness; 302 | SmimeSignedCmsBoundaryName += "-" + boundaryRandomness; 303 | SmimeTripleSignedCmsBoundaryName += "-" + boundaryRandomness; 304 | } 305 | #endregion Private Methods 306 | } 307 | 308 | /// 309 | /// Represents the exception that is thrown when the OpaqueMail.ImapClient is not able to complete an operation. 310 | /// 311 | public class SmtpException : Exception 312 | { 313 | /// 314 | /// Initializes a new instance of the OpaqueMail.SmtpException class. 315 | /// 316 | public SmtpException() : base() { } 317 | /// 318 | /// Initializes a new instance of the OpaqueMail.SmtpException class with the specified error message and inner exception. 319 | /// 320 | /// A System.String that describes the error that occurred. 321 | public SmtpException(string message) : base(message) { } 322 | /// 323 | /// Initializes a new instance of the OpaqueMail.SmtpException class with the specified error message and inner exception. 324 | /// 325 | /// A System.String that describes the error that occurred. 326 | /// The exception that is the cause of the current exception. 327 | public SmtpException(string message, Exception innerException) : base(message, innerException) { } 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /OpaqueMail/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Important 2 | **As of May 2017, this project is not actively maintained. A great alternative is [MailKit by jstedfast](https://github.com/jstedfast/MailKit).** 3 | 4 | OpaqueMail .NET Email Library 5 | ============================== 6 | 7 | .NET email library with full support for IMAP, POP3, and SMTP. 8 | 9 | Supports S/MIME and PGP message signing, encryption, and decryption to foster better email security and privacy. 10 | 11 | Follows IETF standards, implementing all IMAP4rev1, POP3, SMTP, and S/MIME 3.2 commands plus common extensions such as IDLE. Supports MIME, Unicode, and TNEF encoding. 12 | 13 | Includes a fully-featured test client that allows browsing and searching of IMAP and POP3 messages as well as sending of SMTP messages with encryption. Automatically embeds images into Text/HTML messages and strips Script tags. 14 | 15 | Features patterns similar to System.Net.Mail.MailMessage and System.Net.Mail.SmtpClient for simplified upgrades of existing code. Implements .NET 4.5 async and await. 16 | 17 | Thoroughly documented. Optimized for security, usability, and performance. 18 | 19 | Supporting documentation and tutorials available at https://github.com/bertjohnson/OpaqueMail/wiki/OpaqueMail-Library-Tutorial. 20 | 21 | Licensed according to the MIT License (http://mit-license.org/). 22 | 23 | Created by Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 24 | 25 | OpaqueMail Email Proxy 26 | ============================== 27 | 28 | SMTP proxy and message transfer agent (MTA) to add or remove S/MIME message signing, encryption, and authentication for outbound messages. Can operate in passthrough mode or augment messages to add or filter headers. 29 | 30 | Also serve as a passthrough IMAP and POP3 proxy to import S/MIME certificates, filter IPs, or export messages. 31 | 32 | Simplifies email protection for Outlook, Thunderbird, Windows Live Mail, Opera Mail, and other email clients. 33 | 34 | Can be used to secure and authenticate email programs that connect to SMTP servers anonymously (e.g. SharePoint). 35 | 36 | Runs as a Windows service. Inbound and outbound IPs, ports, logging, and TLS / SSL settings are all configurable via XML. 37 | 38 | Supporting documentation and tutorials available at https://github.com/bertjohnson/OpaqueMail/wiki/OpaqueMail-Proxy-Tutorial. 39 | 40 | Licensed according to the MIT License (http://mit-license.org/). 41 | 42 | Created by Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 43 | 44 | License 45 | ======= 46 | 47 | Copyright © 2013-2017 Bert Johnson (https://bertjohnson.com/) of Allcloud Inc. (https://allcloud.com/). 48 | 49 | 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: 50 | 51 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 52 | 53 | 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. 54 | -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | --------------------------------------------------------------------------------