Full Code of chenxuuu/Mail-Box-Net-Disk for AI

master dcb1222d01c5 cached
32 files
100.1 KB
23.7k tokens
31 symbols
1 requests
Download .txt
Repository: chenxuuu/Mail-Box-Net-Disk
Branch: master
Commit: dcb1222d01c5
Files: 32
Total size: 100.1 KB

Directory structure:
gitextract_ybb6kohb/

├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       ├── build.yml
│       └── buildGUI.yml
├── .gitignore
├── LICENSE
├── MailDisk-GUI/
│   ├── MailDisk-GUI/
│   │   ├── App.config
│   │   ├── App.xaml
│   │   ├── App.xaml.cs
│   │   ├── FodyWeavers.xml
│   │   ├── FodyWeavers.xsd
│   │   ├── MailDisk-GUI.csproj
│   │   ├── MainWindow.xaml
│   │   ├── MainWindow.xaml.cs
│   │   ├── Properties/
│   │   │   ├── AssemblyInfo.cs
│   │   │   ├── Resources.Designer.cs
│   │   │   ├── Resources.resx
│   │   │   ├── Settings.Designer.cs
│   │   │   └── Settings.settings
│   │   ├── languages/
│   │   │   ├── en-US.xaml
│   │   │   └── zh-CN.xaml
│   │   └── packages.config
│   └── MailDisk-GUI.sln
├── README.md
├── maildisk/
│   ├── maildisk/
│   │   ├── Program.cs
│   │   ├── apis/
│   │   │   ├── MailClient.cs
│   │   │   ├── Settings.cs
│   │   │   └── VisualDisk.cs
│   │   └── maildisk.csproj
│   └── maildisk.sln
└── pictures/
    ├── big.psd
    ├── mail.psd
    └── mailico.psd

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: chenxuuu
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .github/workflows/build.yml
================================================
name: build

on:
  push:
    paths:
      - 'maildisk/**'
      - '.github/workflows/build.yml'
  pull_request:
    paths:
      - 'maildisk/**'
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'
        required: true
        default: 'warning'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: environment prepare
        run: |
          sudo apt-get update
          sudo apt-get install -y apt-transport-https
          sudo apt-get update
          sudo apt-get install -y dotnet-sdk-5.0
          sudo apt-get install -y p7zip-full
      - name: build
        run: |
          cd maildisk
          dotnet publish -r win-x86 -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
          dotnet publish -r win-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
          dotnet publish -r win-arm -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
          dotnet publish -r win-arm64 -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
          dotnet publish -r linux-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
          dotnet publish -r linux-arm -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
          dotnet publish -r linux-arm64 -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
          dotnet publish -r osx-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
      - name: create packages
        run: |
          mkdir maildisk-pkg
          mv maildisk/maildisk/bin/Debug/net5.0/win-x86/publish/* maildisk-pkg/
          7z a win-x86.7z maildisk-pkg/*
          rm maildisk-pkg/*
          mv maildisk/maildisk/bin/Debug/net5.0/win-x64/publish/* maildisk-pkg/
          7z a win-x64.7z maildisk-pkg/*
          rm maildisk-pkg/*
          mv maildisk/maildisk/bin/Debug/net5.0/win-arm/publish/* maildisk-pkg/
          7z a win-arm.7z maildisk-pkg/*
          rm maildisk-pkg/*
          mv maildisk/maildisk/bin/Debug/net5.0/win-arm64/publish/* maildisk-pkg/
          7z a win-arm64.7z maildisk-pkg/*
          rm maildisk-pkg/*
          mv maildisk/maildisk/bin/Debug/net5.0/linux-x64/publish/* maildisk-pkg/
          7z a linux-x64.7z maildisk-pkg/*
          rm maildisk-pkg/*
          mv maildisk/maildisk/bin/Debug/net5.0/linux-arm/publish/* maildisk-pkg/
          7z a linux-arm.7z maildisk-pkg/*
          rm maildisk-pkg/*
          mv maildisk/maildisk/bin/Debug/net5.0/linux-arm64/publish/* maildisk-pkg/
          7z a linux-arm64.7z maildisk-pkg/*
          rm maildisk-pkg/*
          mv maildisk/maildisk/bin/Debug/net5.0/osx-x64/publish/* maildisk-pkg/
          7z a osx-x64.7z maildisk-pkg/*
      - uses: actions/upload-artifact@v2
        with:
          name: artifact
          path: |
            win-x86.7z
            win-x64.7z
            win-arm.7z
            win-arm64.7z
            linux-x64.7z
            linux-arm.7z
            linux-arm64.7z
            osx-x64.7z


================================================
FILE: .github/workflows/buildGUI.yml
================================================
name: Build GUI client

on:
  push:
    paths:
      - 'MailDisk-GUI/**'
      - '.github/workflows/buildGUI.yml'
  pull_request:
    paths:
      - 'MailDisk-GUI/**'
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'
        required: true
        default: 'warning'

jobs:
  build:
    runs-on: windows-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Add msbuild to PATH
        uses: microsoft/setup-msbuild@v1.0.2
      - name: Build
        run: |
          cd MailDisk-GUI
          nuget restore
          msbuild MailDisk-GUI.sln /p:Configuration=Release /p:DeployOnBuild=true /p:PublishProfile=FolderProfile
      - name: Upload Artifact
        uses: actions/upload-artifact@v2
        with:
          name: MailDisk-GUI
          path: MailDisk-GUI/MailDisk-GUI/bin/Release


================================================
FILE: .gitignore
================================================
# Created by https://www.gitignore.io/api/visualstudio

### VisualStudio ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Typescript v1 declaration files
typings/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# End of https://www.gitignore.io/api/visualstudio

================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.

"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.

2. Grant of Copyright License.

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.

3. Grant of Patent License.

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.

4. Redistribution.

You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:

You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.

5. Submission of Contributions.

Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.

6. Trademarks.

This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.

7. Disclaimer of Warranty.

Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.

8. Limitation of Liability.

In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability.

While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work

To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "{}" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.

   Copyright 2017 晨旭

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
   
   
The MIT License

Copyright (c) 2012-2014 Torben Könke

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

================================================
FILE: MailDisk-GUI/MailDisk-GUI/App.config
================================================
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
    </startup>
</configuration>

================================================
FILE: MailDisk-GUI/MailDisk-GUI/App.xaml
================================================
<Application x:Class="MailDisk_GUI.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:MailDisk_GUI"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary Source="pack://application:,,,/languages/zh-cn.xaml"/>
    </Application.Resources>
</Application>


================================================
FILE: MailDisk-GUI/MailDisk-GUI/App.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace MailDisk_GUI
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
    }
}


================================================
FILE: MailDisk-GUI/MailDisk-GUI/FodyWeavers.xml
================================================
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <PropertyChanged />
  <Costura />
</Weavers>

================================================
FILE: MailDisk-GUI/MailDisk-GUI/FodyWeavers.xsd
================================================
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
  <xs:element name="Weavers">
    <xs:complexType>
      <xs:all>
        <xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
          <xs:complexType>
            <xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="TriggerDependentProperties" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Used to control if the Dependent properties feature is enabled.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="EnableIsChangedProperty" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Used to control if the IsChanged property feature is enabled.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="EventInvokerNames" type="xs:string">
              <xs:annotation>
                <xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="CheckForEquality" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="SuppressWarnings" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Used to turn off build warnings from this weaver.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="SuppressOnPropertyNameChangedWarning" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Used to turn off build warnings about mismatched On_PropertyName_Changed methods.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
          </xs:complexType>
        </xs:element>
        <xs:element name="Costura" minOccurs="0" maxOccurs="1">
          <xs:complexType>
            <xs:all>
              <xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
                <xs:annotation>
                  <xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
                </xs:annotation>
              </xs:element>
              <xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
                <xs:annotation>
                  <xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
                </xs:annotation>
              </xs:element>
              <xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
                <xs:annotation>
                  <xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
                </xs:annotation>
              </xs:element>
              <xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
                <xs:annotation>
                  <xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
                </xs:annotation>
              </xs:element>
              <xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
                <xs:annotation>
                  <xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
                </xs:annotation>
              </xs:element>
            </xs:all>
            <xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="DisableCompression" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="DisableCleanup" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="LoadAtModuleInit" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
              <xs:annotation>
                <xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="ExcludeAssemblies" type="xs:string">
              <xs:annotation>
                <xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="IncludeAssemblies" type="xs:string">
              <xs:annotation>
                <xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="Unmanaged32Assemblies" type="xs:string">
              <xs:annotation>
                <xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="Unmanaged64Assemblies" type="xs:string">
              <xs:annotation>
                <xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
            <xs:attribute name="PreloadOrder" type="xs:string">
              <xs:annotation>
                <xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
              </xs:annotation>
            </xs:attribute>
          </xs:complexType>
        </xs:element>
      </xs:all>
      <xs:attribute name="VerifyAssembly" type="xs:boolean">
        <xs:annotation>
          <xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
        </xs:annotation>
      </xs:attribute>
      <xs:attribute name="VerifyIgnoreCodes" type="xs:string">
        <xs:annotation>
          <xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
        </xs:annotation>
      </xs:attribute>
      <xs:attribute name="GenerateXsd" type="xs:boolean">
        <xs:annotation>
          <xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
        </xs:annotation>
      </xs:attribute>
    </xs:complexType>
  </xs:element>
</xs:schema>

================================================
FILE: MailDisk-GUI/MailDisk-GUI/MailDisk-GUI.csproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="..\packages\PropertyChanged.Fody.3.3.1\build\PropertyChanged.Fody.props" Condition="Exists('..\packages\PropertyChanged.Fody.3.3.1\build\PropertyChanged.Fody.props')" />
  <Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" />
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{B21FA876-FD48-42F0-8B2B-A08B24671DB9}</ProjectGuid>
    <OutputType>WinExe</OutputType>
    <RootNamespace>MailDisk_GUI</RootNamespace>
    <AssemblyName>MailDisk-GUI</AssemblyName>
    <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <WarningLevel>4</WarningLevel>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <Deterministic>true</Deterministic>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup>
    <ApplicationIcon>mailico.ico</ApplicationIcon>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
      <HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath>
    </Reference>
    <Reference Include="FontAwesome.WPF, Version=4.7.0.37774, Culture=neutral, PublicKeyToken=0758b07a11a4f466, processorArchitecture=MSIL">
      <HintPath>..\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="PropertyChanged, Version=3.3.1.0, Culture=neutral, PublicKeyToken=ee3ee20bcf148ddd, processorArchitecture=MSIL">
      <HintPath>..\packages\PropertyChanged.Fody.3.3.1\lib\net40\PropertyChanged.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xaml">
      <RequiredTargetFramework>4.0</RequiredTargetFramework>
    </Reference>
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>
  <ItemGroup>
    <ApplicationDefinition Include="App.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </ApplicationDefinition>
    <Page Include="languages\en-US.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Page Include="languages\zh-CN.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </Page>
    <Page Include="MainWindow.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="MainWindow.xaml.cs">
      <DependentUpon>MainWindow.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs">
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
    </EmbeddedResource>
    <None Include="packages.config" />
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
    </None>
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
  </ItemGroup>
  <ItemGroup>
    <Resource Include="mailico.ico" />
  </ItemGroup>
  <ItemGroup />
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" />
    <Error Condition="!Exists('..\packages\Fody.6.3.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.3.0\build\Fody.targets'))" />
    <Error Condition="!Exists('..\packages\PropertyChanged.Fody.3.3.1\build\PropertyChanged.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\PropertyChanged.Fody.3.3.1\build\PropertyChanged.Fody.props'))" />
  </Target>
  <Import Project="..\packages\Fody.6.3.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.3.0\build\Fody.targets')" />
  <PropertyGroup>
    <LangVersion>9.0</LangVersion>
  </PropertyGroup>
</Project>


================================================
FILE: MailDisk-GUI/MailDisk-GUI/MainWindow.xaml
================================================
<Window x:Class="MailDisk_GUI.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MailDisk_GUI"
        xmlns:fa="http://schemas.fontawesome.io/icons/"
        mc:Ignorable="d"
        Title="{DynamicResource AppName}" Height="450" Width="800">
    <Window.Resources>
        <Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
            <Setter Property="Padding" Value="2"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Background" Value="White"/>
            <Setter Property="BorderBrush" Value="#FFACACAC"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabControl}">
                        <Grid x:Name="templateRoot" ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition x:Name="ColumnDefinition0"/>
                                <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
                                <RowDefinition x:Name="RowDefinition1" Height="*"/>
                            </Grid.RowDefinitions>
                            <UniformGrid x:Name="HeaderPanel" Rows="1" Background="Transparent" Grid.Column="0" IsItemsHost="True" Margin="0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
                            <Line X1="0" X2="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" Stroke="White" StrokeThickness="0.1" VerticalAlignment="Bottom" Margin="0 0 0 1" SnapsToDevicePixels="True"/>
                            <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
                                <ContentPresenter x:Name="PART_SelectedContentHost" ContentTemplate="{TemplateBinding SelectedContentTemplate}" Content="{TemplateBinding SelectedContent}" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentSource="SelectedContent" Margin="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="TabStripPlacement" Value="Bottom">
                                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
                                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
                            </Trigger>
                            <Trigger Property="TabStripPlacement" Value="Left">
                                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
                                <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
                                <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
                                <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
                                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                            </Trigger>
                            <Trigger Property="TabStripPlacement" Value="Right">
                                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
                                <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
                                <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
                                <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
                                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <TabControl Style="{StaticResource TabControlStyle}">
        <TabItem>
            <TabItem.Header>
                <WrapPanel>
                    <Grid>
                        <fa:FontAwesome Icon="FolderOpen" Foreground="Yellow" VerticalAlignment="Center"/>
                        <fa:FontAwesome Icon="FolderOutlinepenOutline" Foreground="Black" VerticalAlignment="Center" FontWeight="Bold"/>
                    </Grid>
                    <TextBlock Text="{DynamicResource Files}" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
                </WrapPanel>
            </TabItem.Header>
        </TabItem>
        <TabItem>
            <TabItem.Header>
                <WrapPanel>
                    <Grid>
                        <fa:FontAwesome Icon="CloudUpload" Foreground="Blue" VerticalAlignment="Center"/>
                    </Grid>
                    <TextBlock Text="{DynamicResource Jobs}" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
                </WrapPanel>
            </TabItem.Header>
        </TabItem>
        <TabItem>
            <TabItem.Header>
                <WrapPanel>
                    <Grid>
                        <fa:FontAwesome Icon="Gears" Foreground="Green" VerticalAlignment="Center"/>
                    </Grid>
                    <TextBlock Text="{DynamicResource Settings}" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
                </WrapPanel>
            </TabItem.Header>
        </TabItem>
        <TabItem>
            <TabItem.Header>
                <WrapPanel>
                    <Grid>
                        <fa:FontAwesome Icon="InfoCircle" Foreground="Gray" VerticalAlignment="Center"/>
                    </Grid>
                    <TextBlock Text="{DynamicResource About}" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
                </WrapPanel>
            </TabItem.Header>
        </TabItem>
    </TabControl>
</Window>


================================================
FILE: MailDisk-GUI/MailDisk-GUI/MainWindow.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MailDisk_GUI
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}


================================================
FILE: MailDisk-GUI/MailDisk-GUI/Properties/AssemblyInfo.cs
================================================
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;

// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("MailDisk-GUI")]
[assembly: AssemblyDescription("邮箱网盘")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("chenxublog.com")]
[assembly: AssemblyProduct("MailDisk-GUI")]
[assembly: AssemblyCopyright("Copyright © chenxuuu")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]

//若要开始生成可本地化的应用程序,请设置
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
//例如,如果您在源文件中使用的是美国英语,
//使用的是美国英语,请将 <UICulture> 设置为 en-US。  然后取消
//对以下 NeutralResourceLanguage 特性的注释。  更新
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。

//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]


[assembly: ThemeInfo(
    ResourceDictionaryLocation.None, //主题特定资源词典所处位置
                                     //(未在页面中找到资源时使用,
                                     //或应用程序资源字典中找到时使用)
    ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
                                              //(未在页面中找到资源时使用,
                                              //、应用程序或任何主题专用资源字典中找到时使用)
)]


// 程序集的版本信息由下列四个值组成: 
//
//      主版本
//      次版本
//      生成号
//      修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]


================================================
FILE: MailDisk-GUI/MailDisk-GUI/Properties/Resources.Designer.cs
================================================
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本: 4.0.30319.42000
//
//     对此文件的更改可能导致不正确的行为,如果
//     重新生成代码,则所做更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------


namespace MailDisk_GUI.Properties
{
    /// <summary>
    ///   强类型资源类,用于查找本地化字符串等。
    /// </summary>
    // 此类是由 StronglyTypedResourceBuilder
    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
    // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
    // (以 /str 作为命令选项),或重新生成 VS 项目。
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    internal class Resources
    {

        private static global::System.Resources.ResourceManager resourceMan;

        private static global::System.Globalization.CultureInfo resourceCulture;

        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal Resources()
        {
        }

        /// <summary>
        ///   返回此类使用的缓存 ResourceManager 实例。
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Resources.ResourceManager ResourceManager
        {
            get
            {
                if ((resourceMan == null))
                {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MailDisk_GUI.Properties.Resources", typeof(Resources).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }

        /// <summary>
        ///   重写当前线程的 CurrentUICulture 属性,对
        ///   使用此强类型资源类的所有资源查找执行重写。
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Globalization.CultureInfo Culture
        {
            get
            {
                return resourceCulture;
            }
            set
            {
                resourceCulture = value;
            }
        }
    }
}


================================================
FILE: MailDisk-GUI/MailDisk-GUI/Properties/Resources.resx
================================================
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!-- 
    Microsoft ResX Schema 
    
    Version 2.0
    
    The primary goals of this format is to allow a simple XML format 
    that is mostly human readable. The generation and parsing of the 
    various data types are done through the TypeConverter classes 
    associated with the data types.
    
    Example:
    
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
                
    There are any number of "resheader" rows that contain simple 
    name/value pairs.
    
    Each data row contains a name, and value. The row also contains a 
    type or mimetype. Type corresponds to a .NET class that support 
    text/value conversion through the TypeConverter architecture. 
    Classes that don't support this are serialized and stored with the 
    mimetype set.
    
    The mimetype is used for serialized objects, and tells the 
    ResXResourceReader how to depersist the object. This is currently not 
    extensible. For a given mimetype the value must be set accordingly:
    
    Note - application/x-microsoft.net.object.binary.base64 is the format 
    that the ResXResourceWriter will generate, however the reader can 
    read any of the formats listed below.
    
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with 
            : System.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array 
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
</root>

================================================
FILE: MailDisk-GUI/MailDisk-GUI/Properties/Settings.Designer.cs
================================================
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


namespace MailDisk_GUI.Properties
{
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
    {

        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

        public static Settings Default
        {
            get
            {
                return defaultInstance;
            }
        }
    }
}


================================================
FILE: MailDisk-GUI/MailDisk-GUI/Properties/Settings.settings
================================================
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
  <Profiles>
    <Profile Name="(Default)" />
  </Profiles>
  <Settings />
</SettingsFile>

================================================
FILE: MailDisk-GUI/MailDisk-GUI/languages/en-US.xaml
================================================
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:MailDisk_GUI.languages" 
                    xmlns:system="clr-namespace:System;assembly=mscorlib">
    <system:String x:Key="AppName">MailDisk</system:String>
    <system:String x:Key="Files">Files</system:String>
    <system:String x:Key="Jobs">Jobs</system:String>
    <system:String x:Key="Settings">Settings</system:String>
    <system:String x:Key="About">About</system:String>
</ResourceDictionary>

================================================
FILE: MailDisk-GUI/MailDisk-GUI/languages/zh-CN.xaml
================================================
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:MailDisk_GUI.languages" 
                    xmlns:system="clr-namespace:System;assembly=mscorlib">
    <system:String x:Key="AppName">邮箱网盘</system:String>
    <system:String x:Key="Files">文件</system:String>
    <system:String x:Key="Jobs">任务</system:String>
    <system:String x:Key="Settings">设置</system:String>
    <system:String x:Key="About">关于</system:String>
</ResourceDictionary>

================================================
FILE: MailDisk-GUI/MailDisk-GUI/packages.config
================================================
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Costura.Fody" version="4.1.0" targetFramework="net462" />
  <package id="Fody" version="6.3.0" targetFramework="net462" developmentDependency="true" />
  <package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net462" />
  <package id="Newtonsoft.Json" version="13.0.1" targetFramework="net462" />
  <package id="PropertyChanged.Fody" version="3.3.1" targetFramework="net462" />
</packages>

================================================
FILE: MailDisk-GUI/MailDisk-GUI.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MailDisk-GUI", "MailDisk-GUI\MailDisk-GUI.csproj", "{B21FA876-FD48-42F0-8B2B-A08B24671DB9}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{B21FA876-FD48-42F0-8B2B-A08B24671DB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{B21FA876-FD48-42F0-8B2B-A08B24671DB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{B21FA876-FD48-42F0-8B2B-A08B24671DB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{B21FA876-FD48-42F0-8B2B-A08B24671DB9}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {99ABBE37-373C-4151-9CC1-8F0A99D7C420}
	EndGlobalSection
EndGlobal


================================================
FILE: README.md
================================================
# 邮箱网盘

![build](https://github.com/chenxuuu/Mail-Box-Net-Disk/workflows/build/badge.svg)
![Build GUI client](https://github.com/chenxuuu/Mail-Box-Net-Disk/workflows/Build%20GUI%20client/badge.svg)

利用邮箱实现网盘功能的工具。

本项目有两个仓库,不过建议在GitHub进行star/pr操作:

GitHub:[https://github.com/chenxuuu/Mail-Box-Net-Disk](https://github.com/chenxuuu/Mail-Box-Net-Disk)

git.osc:[https://gitee.com/chenxuuu/Mail-Box-Net-Disk](https://gitee.com/chenxuuu/Mail-Box-Net-Disk)

## 下载

每次发布版本,会自动在GitHub的release页更新:[点击前往](https://github.com/chenxuuu/Mail-Box-Net-Disk/releases/latest)

## 原理

利用邮箱附件作为文件存储空间,实现文件的上传下载功能

## 功能

- [x] 支持smtp/imap协议的邮箱
- [x] 读取文件夹列表/新建文件夹
- [x] 上传小于限制大小的文件
- [x] 读取已存在的文件
- [x] 上传大文件自动分卷
- [x] 识别分卷上传的文件,下载自动合并
- [x] 优化文件搜索速度
- [x] 完成命令行工具成品
- [x] 支持文件夹上传
- [x] 支持文件夹下载
- [ ] win系统下的gui管理工具
- [ ] 其他系统下的gui管理工具

## 命令列表

```cmd
maildisk -h 查看命令帮助

         -s
         更改邮箱参数设置

         -lf
         列出邮箱的所有邮件文件夹

         -cf <邮件文件夹名>
         新建一个邮件文件夹

         -l <邮件文件夹>
         列出所有该邮件文件夹下的文件

         -c <邮件文件夹>
         清除所有该邮件文件夹下不完整的分卷文件

         -u <邮件文件夹> <本地文件> <云端文件>
         上传文件

         -d <邮件文件夹> <本地文件> <云端文件>
         下载文件

         -uf <邮件文件夹> <本地文件夹> <云端虚拟文件夹路径>
         上传文件夹,并清理不完整分卷的邮件
         注意:如果云端存在该文件,则不会上传

         -df <邮件文件夹> <本地文件夹> <云端虚拟文件夹路径>
         下载文件夹

         所有文件和路径都不能包含'<'符号
```

## 加入该项目

如果你愿意忍受我写的智障代码,那么欢迎pr

## 其他

该项目的代码可以随意引用,但请保留指向该项目的说明文字


================================================
FILE: maildisk/maildisk/Program.cs
================================================
using MailKit;
using MailKit.Net.Imap;
using MailKit.Search;
using System;
using maildisk.apis;
using System.IO;
using System.Text;

namespace maildisk
{
    class Program
    {
        static void Main(string[] args)
        {
            if(args.Length > 0)
            switch(args[0])
            {
                case "-h":
                        Console.WriteLine(@"
***********
*Mail Disk*
***********
You can use these commands:

-h: 
show commands we support.

-s:
set your imap settings.

-lf:
list all folders on mail server.

-cf <folder name>:
create new folder on mail server.

-l <email folder>:
show files in this folder.

-c <email folder>:
clear all wrong files in this folder.

-u <email folder> <local file> <file name on cloud>:
upload a file to net disk.

-d <email folder> <local file> <file name on cloud>:
download a file from net disk.

-uf <email folder> <local folder> <folder name on cloud>:
upload a folder to net disk and clear all wrong files in this email folder.
Notice: if file is exist on cloud, it will not be uploaded.

-df <email folder> <local folder> <folder name on cloud>:
download a folder from net disk.
Notice: local file must be not exist.

All file and path should not contain '<'".Replace("\r\n","\r\n\t"));
                        return;

                    case "-s":
                        Settings.Set();
                        return;

                    case "-lf":
                        var lfdisk = Settings.GetDisk();
                        if (lfdisk == null) return;
                        Console.WriteLine("getting all folders ...");
                        var all = lfdisk.GetFolders();
                        Console.WriteLine("here's all folders:");
                        foreach(var f in all)
                        {
                            Console.WriteLine(f.FullName);
                        }
                        return;

                    case "-cf":
                        var cfdisk = Settings.GetDisk();
                        if (cfdisk == null) return;
                        if(args.Length < 2) { Console.WriteLine("please enter a folder name");return; }
                        Console.WriteLine($"creating folder {args[1]} ...");
                        cfdisk.CreatFolder(args[1]);
                        return;

                    case "-l":
                        var ldisk = Settings.GetDisk();
                        if (ldisk == null) return;
                        if (args.Length < 2) { Console.WriteLine("please enter a folder name"); return; }
                        Console.WriteLine($"fetching file list with folder {args[1]} ...");
                        var lfiles = ldisk.GetFileList(args[1]);
                        Console.WriteLine($"\r\n\r\ndone! list of files:");
                        foreach (var s in lfiles)
                        {
                            Console.WriteLine(s);
                        }
                        return;

                    case "-c":
                        var cdisk = Settings.GetDisk();
                        if (cdisk == null) return;
                        if (args.Length < 2) { Console.WriteLine("please enter a folder name"); return; }
                        Console.WriteLine($"fetching file list with folder {args[1]} ...");
                        cdisk.GetFileList(args[1], true);
                        Console.WriteLine($"\r\n\r\ndone!");
                        return;

                    case "-u":
                        var udisk = Settings.GetDisk();
                        if (udisk == null) return;
                        if (args.Length < 4) { Console.WriteLine("wrong args count"); return; }
                        Console.WriteLine($"uploading file {args[2]} to {args[1]} as {args[3]} ...");
                        if(args[3].IndexOf("<")>=0)
                        {
                            Console.WriteLine($"error! file name do not contain '<'");
                            return;
                        }
                        udisk.UploadBigFile(args[3], args[1], args[2], (int)Settings.maxBlock * 1024 * 1024);
                        return;

                    case "-d":
                        var ddisk = Settings.GetDisk();
                        if (ddisk == null) return;
                        if (args.Length < 4) { Console.WriteLine("wrong args count"); return; }
                        Console.WriteLine($"Download file {args[3]} from {args[1]} as {args[2]} ...");
                        if (args[3].IndexOf("<") >= 0)
                        {
                            Console.WriteLine($"error! file name do not contain '<'");
                            return;
                        }
                        ddisk.DownloadFile(args[1], args[3], args[2]);
                        return;

                    case "-uf":
                        var ufdisk = Settings.GetDisk();
                        if (ufdisk == null) return;
                        if (args.Length < 4) { Console.WriteLine("wrong args count"); return; }
                        Console.WriteLine($"upload folder {args[3]} to {args[1]} as {args[2]} ...");
                        if (args[3].IndexOf("<") >= 0)
                        {
                            Console.WriteLine($"error! folder name do not contain '<'");
                            return;
                        }
                        ufdisk.RefreshFiles(args[1]);
                        ufdisk.UploadFolder(args[3], args[1], args[2], (int)Settings.maxBlock * 1024 * 1024);
                        Console.WriteLine("done! all files uploaded!");
                        return;

                    case "-df":
                        var dfdisk = Settings.GetDisk();
                        if (dfdisk == null) return;
                        if (args.Length < 4) { Console.WriteLine("wrong args count"); return; }
                        Console.WriteLine($"Download folder {args[3]} from {args[1]} as {args[2]} ...");
                        if (args[3].IndexOf("<") >= 0)
                        {
                            Console.WriteLine($"error! folder name do not contain '<'");
                            return;
                        }
                        dfdisk.DownloadFolder(args[3], args[1], args[2]);
                        Console.WriteLine("done! all files downloaded!");
                        return;

                    default:
                        break;
            }
            Console.WriteLine(@"no commond matched
use -h to show commands we support");
            return;
        }
    }
}


================================================
FILE: maildisk/maildisk/apis/MailClient.cs
================================================
using MailKit;
using MailKit.Net.Imap;
using MailKit.Search;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace maildisk.apis
{
    class MailClient
    {
        private string address;
        private ImapClient client = new ImapClient();

        /// <summary>
        /// new mail client
        /// </summary>
        /// <param name="server">server address</param>
        /// <param name="port">server port</param>
        /// <param name="useSsl">server use ssl or not</param>
        /// <param name="account">your account</param>
        /// <param name="password">your password</param>
        /// <param name="address">your email address</param>
        public MailClient(string server, int port, bool useSsl, string account, string password, string address)
        {
            client.ServerCertificateValidationCallback = (s, c, h, e) => true;
            client.Connect(server, port, useSsl);
            client.Authenticate(account, password);
            this.address = address;
#if DEBUG
            Console.WriteLine($"[mail create]mail client created, on {server}:{port}" +
                $", ssl:{useSsl}, {account}, {address}");
#endif
        }

        /// <summary>
        /// get all folders in this mail
        /// </summary>
        /// <param name="path">path, default is empty</param>
        /// <returns>folder list</returns>
        public IMailFolder[] GetFolders(string path = "")
        {
            ArrayList folders = new ArrayList();
            
            var personal = client.GetFolder(path);

            foreach (var folder in personal.GetSubfolders(false))
            {
                if (folder.GetSubfolders(false).Count > 0)
                {
#if DEBUG
                    Console.WriteLine($"[folder open] {path + folder.Name}");
#endif
                    folders.AddRange(GetFolders(folder.FullName));
                }
                else
                {
                    folders.Add(folder);
#if DEBUG
                    Console.WriteLine($"[folder get] {folder.FullName}");
#endif
                }
            }
            return (IMailFolder[])folders.ToArray(typeof(IMailFolder));
        }

        /// <summary>
        /// get one folder
        /// </summary>
        /// <param name="path">path, default is empty</param>
        /// <returns>folder</returns>
        public IMailFolder GetFolder(string path)
        {
            return client.GetFolder(path);
        }


        /// <summary>
        /// get not read mails, and mark as seen
        /// </summary>
        /// <returns>mails' IMessageSummary</returns>
        public IList<IMessageSummary> GetNotSeen()
        {
            ArrayList mails = new ArrayList();
            var inbox = client.Inbox;
            inbox.Open(FolderAccess.ReadWrite);
            var uids = inbox.Search(SearchQuery.NotSeen);
            inbox.AddFlags(uids, MessageFlags.Seen, true);
#if DEBUG
            Console.WriteLine($"[GetNotSeen] mails count {uids.Count}");
#endif
            return inbox.Fetch(uids,
                    MessageSummaryItems.Full | MessageSummaryItems.UniqueId);
        }

    }
}


================================================
FILE: maildisk/maildisk/apis/Settings.cs
================================================
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace maildisk.apis
{
    class Settings
    {
        public static long maxBlock = 0;

        private static string GetBasePath()
        {
            using var processModule = Process.GetCurrentProcess().MainModule;
            return Path.GetDirectoryName(processModule?.FileName);
        }

        /// <summary>
        /// check setting file exist
        /// </summary>
        /// <returns>file exist</returns>
        public static bool CheckSetings()
        {
            return File.Exists(GetBasePath() + "/mail.json");
        }

        /// <summary>
        /// create settings file
        /// </summary>
        public static void Set()
        {
            Console.WriteLine("Notice: If you're using QQMail, pleause create a login code on mail.qq.com\r\n");
            JObject o = new JObject();
            Console.Write("Enter the imap server address:");
            o["imap"] = Console.ReadLine();

            Console.Write("Enter the imap server port(default 993):");
            try { o["port"] = int.Parse(Console.ReadLine()); }
            catch { o["port"] = 993; }

            Console.Write("Use ssl?(y/n):");
            o["ssl"] = Console.ReadLine() == "y" ? true : false;

            Console.Write("Account:");
            o["account"] = Console.ReadLine();

            Console.Write("Password:");
            o["password"] = Console.ReadLine();

            Console.Write("E-mail address:");
            o["address"] = Console.ReadLine();

            Console.Write("Max size for each file(MiB):");
            o["block"] = Console.ReadLine();

            File.WriteAllText(GetBasePath() + "/mail.json", o.ToString());

            Console.WriteLine("\r\ndone! enjoy!");
        }

        /// <summary>
        /// return a VisualDisk
        /// </summary>
        /// <returns>VisualDisk</returns>
        public static VisualDisk GetDisk()
        {
            if (CheckSetings())
            {
                string s = File.ReadAllText(GetBasePath() + "/mail.json");
                JObject jo = (JObject)JsonConvert.DeserializeObject(s);
                var disk = new VisualDisk(
                    (string)jo["imap"],
                    (int)jo["port"],
                    (bool)jo["ssl"],
                    (string)jo["account"],
                    (string)jo["password"],
                    (string)jo["address"]);
                maxBlock = (long)jo["block"];
                return disk;
            }
            else
            {
                Console.WriteLine("settings not found\r\npleause use -s command to set imap settings");
                return null;
            }
        }
    }
}


================================================
FILE: maildisk/maildisk/apis/VisualDisk.cs
================================================
using MailKit;
using MailKit.Net.Imap;
using MailKit.Net.Smtp;
using MailKit.Search;
using MimeKit;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace maildisk.apis
{
    class VisualDisk
    {
        private string address;
        private string account;
        private string password;
        private string imapServer;
        private int imapPort;
        private bool imapSsl;
        private string lastFolder;

        public VisualDisk(string imapServer, int port, bool useSsl, string account, string password, string address)
        {
            this.imapServer = imapServer;
            this.imapPort = port;
            this.imapSsl = useSsl;
            this.address = address;
            this.account = account;
            this.password = password;
            //auto mark as seen task
            Task.Run(() => {
                while(true)
                {
                    try
                    {
                        if (lastFolder != null)
                        {
                            var client = GetImapClient();
                            var f = client.GetFolder(lastFolder);
                            f.Open(FolderAccess.ReadWrite);
                            var uids = f.Search(SearchQuery.NotSeen);
                            foreach (var u in uids)
                            {
                                f.AddFlags(u, MessageFlags.Seen, true);

                                Console.WriteLine($"[disk check]add a seen flag");

                            }
                            client.Disconnect(true);
                        }
                    }
                    catch(Exception e)
                    {
                        Console.WriteLine($"[disk check]fetch error: {e.Message}");
                    }
                    Task.Delay(30 * 1000).Wait();
                }
            });
        }

        /// <summary>
        /// get a imap client
        /// </summary>
        /// <returns>imap client</returns>
        public ImapClient GetImapClient()
        {
            ImapClient client = new ImapClient();
            client.ServerCertificateValidationCallback = (s, c, h, e) => true;
            client.Connect(imapServer, imapPort, imapSsl);
            client.Authenticate(account, password);
            //判断是否 添加ID COMMOND命令
            if ((client.Capabilities | ImapCapabilities.Id) == client.Capabilities)
            {
                var clientImplementation = new ImapImplementation
                {
                    Name = "Foxmail",
                    Version = "9.156"
                };
                var serverImplementation = client.Identify(clientImplementation);
            }
            return client;
        }

        /// <summary>
        /// upload a file
        /// </summary>
        /// <param name="fileName">file name on cloud disk</param>
        /// <param name="folderPath">folder on email</param>
        /// <param name="filePath">local file path</param>
        /// <returns>file upload success or not</returns>
        private bool Upload(string fileName, string folderPath, Stream file)
        {

            Console.WriteLine($"[disk upload]upload {fileName} to mail folder {folderPath}, size:{file.Length}");

            var client = GetImapClient();
            var message = new MimeMessage();
            message.From.Add(MailboxAddress.Parse(address));
            message.To.Add(MailboxAddress.Parse(address));
            message.Subject = "[mailDisk]" + fileName;
            var body = new TextPart("plain")
            {
                Text =
                "This mail was send by mail disk\r\n" +
                "please do not delete"
            };

            var attachment = new MimePart()
            {
                Content = new MimeContent(file, ContentEncoding.Default),
                ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
                ContentTransferEncoding = ContentEncoding.Base64,
                FileName = "attachment.netdiskfile"
            };

            var multipart = new Multipart("mixed");
            multipart.Add(body);
            multipart.Add(attachment);
            message.Body = multipart;

            Console.WriteLine("[disk upload]appending...");

            var folder = GetImapClient().GetFolder(folderPath);
            folder.Open(FolderAccess.ReadWrite);
            var uid = folder.Append(message);
            lastFolder = folderPath;


            Console.WriteLine($"[disk upload]upload success");

            client.Disconnect(true);
            return true;
        }

        /// <summary>
        /// get file list with folder
        /// </summary>
        /// <param name="folderPath">folder</param>
        /// <returns>files' name</returns>
        public string[] GetFileList(string folderPath, bool deleteMissing = false)
        {
            ArrayList mails = new ArrayList();
            var client = GetImapClient();
            var folder = client.GetFolder(folderPath);
            folder.Open(FolderAccess.ReadWrite);
            Console.WriteLine($"find {folder.Count} mails in this folder");
            for(int i = 0;i < folder.Count; i += 100)
            {
                Console.WriteLine($"fatching mails {i}/{folder.Count}");
                int max = i + 100;
                if (max >= folder.Count)
                    max = folder.Count - 1;
                foreach (var m in folder.Fetch(i, max, MessageSummaryItems.Full | MessageSummaryItems.UniqueId))
                {
                    if(m.Envelope.Subject.IndexOf("[mailDisk]") == 0)
                        mails.Add(m.Envelope.Subject.Substring("[mailDisk]".Length));
                }
                if (max == folder.Count)
                    break;
            }
            Console.WriteLine($"mails in {folder.Count} fatched ok.");

            ArrayList files = new ArrayList();
            foreach(string f in mails)
            {
                if (f.IndexOf("<")>=0)
                {
                    MatchCollection mc = Regex.Matches(f, @"(.+?)<1/(\d+?)>");
                    if (mc.Count > 0 && mc[0].Groups.Count == 3)
                    {
                        Console.WriteLine($"find file {mc[0].Groups[1]} with {mc[0].Groups[2]} parts,checking...");
                        bool result = true;//check is it have all files
                        int sum = int.Parse(mc[0].Groups[2].ToString());
                        for(int i=1;i<=sum;i++)
                        {
                            if(!mails.Contains($"{mc[0].Groups[1]}<{i}/{sum}>"))
                            {
                                result = false;
                                break;
                            }
                        }
                        if(result)
                        {
                            files.Add(mc[0].Groups[1].ToString());
                            Console.WriteLine($"file {mc[0].Groups[1]} check ok");
                        }
                        else
                            Console.WriteLine($"file {mc[0].Groups[1]}'s parts are missing");
                    }
                        
                }
                else
                {
                    files.Add(f);
                }
            }
            if(deleteMissing)
            {
                Console.WriteLine("start cleaning all missing mails");
                for (int i = 0; i < folder.Count; i += 100)
                {
                    Console.WriteLine($"fatching mails {i}/{folder.Count}");
                    int max = i + 100;
                    if (max >= folder.Count)
                        max = folder.Count - 1;
                    foreach (var m in folder.Fetch(i, max, MessageSummaryItems.Full | MessageSummaryItems.UniqueId))
                    {
                        if (m.Envelope.Subject.IndexOf("[mailDisk]") == 0)
                        {
                            string name = m.Envelope.Subject.Substring("[mailDisk]".Length);
                            Console.WriteLine($"checking file {name}");
                            MatchCollection mc = Regex.Matches(name, @"(.+?)<(\d+?)/(\d+?)>");
                            if (mc.Count > 0 && mc[0].Groups.Count == 4)
                                name = mc[0].Groups[1].ToString();
                            if (!files.Contains(name))
                            {
                                Console.WriteLine($"file {name} is not right, mark as deleted");
                                folder.AddFlags(m.UniqueId, MessageFlags.Deleted, true);
                            }
                        }
                    }
                    if (max == folder.Count)
                        break;
                }
                folder.Expunge();
            }
            client.Disconnect(true);
            return (string[])files.ToArray(typeof(string));
        }

        /// <summary>
        /// download file
        /// </summary>
        /// <param name="folderPath">mail folder</param>
        /// <param name="fileName">file save name</param>
        public void DownloadFile(string folderPath, string fileName, string local, 
            ImapClient client = null, 
            IList<IMessageSummary> all = null,
            IMailFolder folder = null)
        {
            if(File.Exists(local))
            {
                Console.WriteLine($"error! file {local} already exist!");
                return;
            }
            if(client == null)
                client = GetImapClient();

            var invalidFileName = Path.GetInvalidFileNameChars();
            fileName = invalidFileName.Aggregate(fileName, (o, r) => (o.Replace(r.ToString(), string.Empty)));

            if (all == null)
            {
                folder = client.GetFolder(folderPath);
                folder.Open(FolderAccess.ReadOnly);
                var uids = folder.Search(SearchQuery.SubjectContains($"[mailDisk]{fileName}"));

                Console.WriteLine($"find {uids.Count} matchs in this folder");
                Console.WriteLine($"fatching mails");
                all = folder.Fetch(uids, MessageSummaryItems.Full | MessageSummaryItems.UniqueId);
            }
            bool singleFile = true;
            int fileSum = 0;
            bool hasFile = false;
            foreach(var m in all)
            {
                string subject = m.Envelope.Subject.Substring("[mailDisk]".Length);
                if (subject.IndexOf(fileName) == 0 && (subject.Length == fileName.Length || subject.Substring(fileName.Length, 1) == "<"))
                {
                    if(subject.Length == fileName.Length)
                    {
                        hasFile = true;
                        break;
                    }
                    MatchCollection mc = Regex.Matches(subject, @"<1/(\d+?)>");
                    if (mc.Count > 0 && mc[0].Groups.Count == 2)
                    {
                        fileSum = int.Parse(mc[0].Groups[1].ToString());
                        singleFile = false;
                        hasFile = true;
                        break;
                    }
                }
            }

            if(!hasFile)
            {
                Console.WriteLine($"error! file not exist!");
                return;
            }

            if(singleFile)
            {
                foreach (var m in all)
                {
                    if(m.Envelope.Subject.IndexOf($"[mailDisk]{fileName}") == 0)
                    {
                        while(true)
                        {
                            try
                            {
                                using (var output = File.Create(local))
                                {
                                    var r = Download(folder, m.UniqueId);
                                    r.Position = 0;
                                    r.CopyTo(output);
                                    break;
                                }
                            }
                            catch(Exception e)
                            {
                                Console.WriteLine($"[disk Download]fail, retry, infomation:" + e.Message);
                            }
                        }
                    }
                }
            }
            else
            {
                ArrayList mails = new ArrayList();
                foreach (var m in all)
                {
                    string subject = m.Envelope.Subject.Substring("[mailDisk]".Length);
                    mails.Add(subject);
                }
                Console.WriteLine($"find file {fileName} with {fileSum} parts,checking...");
                bool result = true;//check is it have all files
                for (int i = 1; i <= fileSum; i++)
                {
                    if (!mails.Contains($"{fileName}<{i}/{fileSum}>"))
                    {
                        result = false;
                        break;
                    }
                }
                if (result)
                {
                    Console.WriteLine($"file {fileName} check ok, begin download...");
                    using (var output = File.Create(local))
                    {
                        for (int i = 1; i <= fileSum; i++)
                        {
                            foreach (var m in all)
                            {
                                if (m.Envelope.Subject.IndexOf($"[mailDisk]{fileName}<{i}/{fileSum}>") == 0)
                                {
                                    while (true)
                                    {
                                        try
                                        {
                                            Console.WriteLine($"downloading {fileName}<{i}/{fileSum}> ...");
                                            var r = Download(folder, m.UniqueId);
                                            r.Position = 0;
                                            r.CopyTo(output);
                                            break;
                                        }
                                        catch (Exception e)
                                        {
                                            Console.WriteLine($"[disk Download]fail, retry, infomation:" + e.Message);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    Console.WriteLine($"file {fileName}'s parts are missing, download fail");
                    return;
                } 
            }
            Console.WriteLine($"file {fileName} download success!");
        }

        /// <summary>
        /// download a mail's attachments
        /// </summary>
        /// <param name="folder">file folder</param>
        /// <param name="id">mail uid</param>
        /// <returns>file's stream</returns>
        private Stream Download(IMailFolder folder, UniqueId id)
        {
            Stream stream = new MemoryStream();
            MimeMessage message = folder.GetMessage(id);
            foreach (MimePart attachment in message.Attachments)
            {
                //下载附件
                using (var cancel = new CancellationTokenSource())
                {
                    attachment.Content.DecodeTo(stream, cancel.Token);
                    return stream;
                }
            }
            return stream;
        }
        


        /// <summary>
        /// upload big files, auto split by setting's size
        /// </summary>
        /// <param name="fileName">file name on cloud disk</param>
        /// <param name="folderPath">folder on email</param>
        /// <param name="filePath">local file path</param>
        /// <param name="blockSize">max size for each mail</param>
        /// <returns>file upload success or not</returns>
        public bool UploadBigFile(string fileName, string folderPath, string filePath, int blockSize)
        {
            if (!File.Exists(filePath))
            {
                Console.WriteLine($"error! file {filePath} not exist!");
                return false;
            }
            fileName = fileName.Replace("\\", "/");
            while(fileName.IndexOf("/") == 0)//remove the "/" head
            {
                fileName = fileName.Substring(1);
            }

            FileInfo fileInfo = new FileInfo(filePath);
            if (fileInfo.Length > blockSize)
            {

                Console.WriteLine($"[disk Upload]file need to be splited");

                var steps = (int)Math.Ceiling((double)fileInfo.Length / blockSize);
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryReader br = new BinaryReader(fs))
                    {
                        int couter = 1;
                        bool isReadingComplete = false;
                        while (!isReadingComplete)
                        {
                            string tempName = couter.ToString();

                            byte[] bytes = br.ReadBytes(blockSize);
                            Stream stream = new MemoryStream(bytes);

                            bool result = false;
                            while(!result)
                            {
                                try
                                {
                                    result = Upload(fileName + $"<{couter}/{steps}>", folderPath, stream);
                                }
                                catch(Exception e)
                                {
                                    Console.WriteLine($"[disk Upload]fail, retry, infomation:" + e.Message);
                                }
                            }

                            isReadingComplete = (bytes.Length != blockSize);
                            if (!isReadingComplete)
                            {
                                couter += 1;
                            }
                        }
                    }
                }
                return true;
            }
            else
            {
                bool result = false;
                while (!result)
                {
                    try
                    {
                        result = Upload(fileName, folderPath, File.OpenRead(filePath));
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"[disk Upload]fail, retry, infomation:" + e.Message);
                    }
                }
                return true;
            }
        }


        /// <summary>
        /// get all folders in this mail
        /// </summary>
        /// <param name="path">path, default is empty</param>
        /// <returns>folder list</returns>
        public IMailFolder[] GetFolders(string path = "")
        {
            ArrayList folders = new ArrayList();

            var personal = GetImapClient().GetFolder(path);

            foreach (var folder in personal.GetSubfolders(false))
            {
                if (folder.GetSubfolders(false).Count > 0)
                {
                    folders.Add(folder);
                    folders.AddRange(GetFolders(folder.FullName));
                }
                else
                {
                    folders.Add(folder);
                }
            }
            return (IMailFolder[])folders.ToArray(typeof(IMailFolder));
        }


        /// <summary>
        /// create a folder
        /// </summary>
        /// <param name="path">folder name and path</param>
        /// <returns>result</returns>
        public void CreatFolder(string path)
        {
            var client = GetImapClient();
            if(path.IndexOf("/") < 0)
            {
                var root = client.GetFolder("");
                root.Create(path, true);
            }
            else
            {
                int l = path.LastIndexOf("/");
                var folder = client.GetFolder(path.Substring(0,l));
                folder.Create(path.Substring(l+1), true);
            }
            Console.WriteLine($"[disk folder]folder {path} is created.");
        }

        private ArrayList tempFiles = new ArrayList();
        public void RefreshFiles(string folderPath)
        {
            tempFiles.AddRange(GetFileList(folderPath));
            foreach (var s in tempFiles)
            {
                Console.WriteLine(s);
            }
        }

        /// <summary>
        /// upload a folder
        /// </summary>
        /// <param name="cloudPath">cloud folder path</param>
        /// <param name="folderPath">mail folder</param>
        /// <param name="localPath">local folder path</param>
        /// <param name="blockSize">each mail size</param>
        public void UploadFolder(string cloudPath, string folderPath, string localPath, int blockSize)
        {
            while (cloudPath.LastIndexOf("/") == cloudPath.Length - 1)//remove last "/"
            {
                cloudPath = cloudPath.Substring(0, cloudPath.Length - 1);
            }
            Console.WriteLine($"[disk upload folder]upload {localPath} to {cloudPath}");
            if (!Directory.Exists(localPath))
            {
                Console.WriteLine($"error! folder {localPath} not exist!");
                return;
            }

            foreach (var f in Directory.GetDirectories(localPath))
            {
                int l = f.LastIndexOf("/");
                if(l == -1)
                    l = f.LastIndexOf("\\");
                UploadFolder(cloudPath + f.Substring(l), folderPath, f, blockSize);
            }
            foreach(var f in Directory.GetFiles(localPath))
            {
                int l = f.LastIndexOf("/");
                if (l == -1)
                    l = f.LastIndexOf("\\");

                string fileName = cloudPath + f.Substring(l);
                fileName = fileName.Replace("\\", "/");
                while (fileName.IndexOf("/") == 0)//remove the "/" head
                {
                    fileName = fileName.Substring(1);
                }

                if (tempFiles.Contains(fileName))
                    Console.WriteLine($"[disk upload folder] file {fileName} is" +
                        $" already exist in mail disk, skip upload.");
                else
                    UploadBigFile(fileName, folderPath, f, blockSize);
            }
        }

        /// <summary>
        /// download a floder
        /// </summary>
        /// <param name="cloudPath">cloud folder path</param>
        /// <param name="folderPath">mail folder</param>
        /// <param name="localPath">local folder path</param>
        public void DownloadFolder(string cloudPath, string folderPath, string localPath)
        {
            while (cloudPath.LastIndexOf("/") == cloudPath.Length - 1)//remove last "/"
            {
                cloudPath = cloudPath.Substring(0, cloudPath.Length - 1);
            }
            cloudPath += "/";
            localPath = localPath.Replace("\\", "/");
            if (localPath.LastIndexOf("/") != localPath.Length - 1)
                localPath += "/";
            Console.WriteLine($"[disk download folder]download {cloudPath} to {localPath}");

            var client = GetImapClient();
            var folder = client.GetFolder(folderPath);
            folder.Open(FolderAccess.ReadOnly);

            Console.WriteLine($"find {folder.Count} files in this folder");
            Console.WriteLine($"fatching mails");
            var all = folder.Fetch(0,-1, MessageSummaryItems.Full | MessageSummaryItems.UniqueId);

            foreach (string f in GetFileList(folderPath))
            {
                if(f.IndexOf(cloudPath) == 0)//match folder
                {
                    string localFile = localPath + f.Substring(cloudPath.Length);
                    localPath = localPath.Replace("\\", "/");
                    int l = localFile.LastIndexOf("/");
                    Directory.CreateDirectory(localFile.Substring(0, l));
                    DownloadFile(folderPath, f, localFile, client, all, folder);
                }
            }
        }
    }
}


================================================
FILE: maildisk/maildisk/maildisk.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <Authors>chenxuuu</Authors>
    <Company>chenxublog.com</Company>
    <Description>make your e-mail become a netdisk!</Description>
    <Version>1.0.2.3</Version>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MailKit" Version="2.10.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="Spectre.Console" Version="0.31.0" />
  </ItemGroup>
</Project>


================================================
FILE: maildisk/maildisk.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.168
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "maildisk", "maildisk\maildisk.csproj", "{40D245C7-6840-4A9B-AEA9-4F9503013CC0}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{40D245C7-6840-4A9B-AEA9-4F9503013CC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{40D245C7-6840-4A9B-AEA9-4F9503013CC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{40D245C7-6840-4A9B-AEA9-4F9503013CC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{40D245C7-6840-4A9B-AEA9-4F9503013CC0}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {6FBAA721-B24C-48A4-AA71-CA4D6CD539C2}
	EndGlobalSection
EndGlobal
Download .txt
gitextract_ybb6kohb/

├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       ├── build.yml
│       └── buildGUI.yml
├── .gitignore
├── LICENSE
├── MailDisk-GUI/
│   ├── MailDisk-GUI/
│   │   ├── App.config
│   │   ├── App.xaml
│   │   ├── App.xaml.cs
│   │   ├── FodyWeavers.xml
│   │   ├── FodyWeavers.xsd
│   │   ├── MailDisk-GUI.csproj
│   │   ├── MainWindow.xaml
│   │   ├── MainWindow.xaml.cs
│   │   ├── Properties/
│   │   │   ├── AssemblyInfo.cs
│   │   │   ├── Resources.Designer.cs
│   │   │   ├── Resources.resx
│   │   │   ├── Settings.Designer.cs
│   │   │   └── Settings.settings
│   │   ├── languages/
│   │   │   ├── en-US.xaml
│   │   │   └── zh-CN.xaml
│   │   └── packages.config
│   └── MailDisk-GUI.sln
├── README.md
├── maildisk/
│   ├── maildisk/
│   │   ├── Program.cs
│   │   ├── apis/
│   │   │   ├── MailClient.cs
│   │   │   ├── Settings.cs
│   │   │   └── VisualDisk.cs
│   │   └── maildisk.csproj
│   └── maildisk.sln
└── pictures/
    ├── big.psd
    ├── mail.psd
    └── mailico.psd
Download .txt
SYMBOL INDEX (31 symbols across 8 files)

FILE: MailDisk-GUI/MailDisk-GUI/App.xaml.cs
  class App (line 14) | public partial class App : Application

FILE: MailDisk-GUI/MailDisk-GUI/MainWindow.xaml.cs
  class MainWindow (line 21) | public partial class MainWindow : Window
    method MainWindow (line 23) | public MainWindow()

FILE: MailDisk-GUI/MailDisk-GUI/Properties/Resources.Designer.cs
  class Resources (line 21) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: MailDisk-GUI/MailDisk-GUI/Properties/Settings.Designer.cs
  class Settings (line 14) | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

FILE: maildisk/maildisk/Program.cs
  class Program (line 11) | class Program
    method Main (line 13) | static void Main(string[] args)

FILE: maildisk/maildisk/apis/MailClient.cs
  class MailClient (line 11) | class MailClient
    method MailClient (line 25) | public MailClient(string server, int port, bool useSsl, string account...
    method GetFolders (line 42) | public IMailFolder[] GetFolders(string path = "")
    method GetFolder (line 73) | public IMailFolder GetFolder(string path)
    method GetNotSeen (line 83) | public IList<IMessageSummary> GetNotSeen()

FILE: maildisk/maildisk/apis/Settings.cs
  class Settings (line 11) | class Settings
    method GetBasePath (line 15) | private static string GetBasePath()
    method CheckSetings (line 25) | public static bool CheckSetings()
    method Set (line 33) | public static void Set()
    method GetDisk (line 68) | public static VisualDisk GetDisk()

FILE: maildisk/maildisk/apis/VisualDisk.cs
  class VisualDisk (line 18) | class VisualDisk
    method VisualDisk (line 28) | public VisualDisk(string imapServer, int port, bool useSsl, string acc...
    method GetImapClient (line 71) | public ImapClient GetImapClient()
    method Upload (line 97) | private bool Upload(string fileName, string folderPath, Stream file)
    method GetFileList (line 146) | public string[] GetFileList(string folderPath, bool deleteMissing = fa...
    method DownloadFile (line 242) | public void DownloadFile(string folderPath, string fileName, string lo...
    method Download (line 388) | private Stream Download(IMailFolder folder, UniqueId id)
    method UploadBigFile (line 414) | public bool UploadBigFile(string fileName, string folderPath, string f...
    method GetFolders (line 494) | public IMailFolder[] GetFolders(string path = "")
    method CreatFolder (line 521) | public void CreatFolder(string path)
    method RefreshFiles (line 539) | public void RefreshFiles(string folderPath)
    method UploadFolder (line 555) | public void UploadFolder(string cloudPath, string folderPath, string l...
    method DownloadFolder (line 602) | public void DownloadFolder(string cloudPath, string folderPath, string...
Condensed preview — 32 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (112K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 681,
    "preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 3095,
    "preview": "name: build\n\non:\n  push:\n    paths:\n      - 'maildisk/**'\n      - '.github/workflows/build.yml'\n  pull_request:\n    path"
  },
  {
    "path": ".github/workflows/buildGUI.yml",
    "chars": 857,
    "preview": "name: Build GUI client\n\non:\n  push:\n    paths:\n      - 'MailDisk-GUI/**'\n      - '.github/workflows/buildGUI.yml'\n  pull"
  },
  {
    "path": ".gitignore",
    "chars": 5124,
    "preview": "# Created by https://www.gitignore.io/api/visualstudio\r\n\r\n### VisualStudio ###\r\n## Ignore Visual Studio temporary files,"
  },
  {
    "path": "LICENSE",
    "chars": 11333,
    "preview": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AN"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/App.config",
    "chars": 182,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<configuration>\n    <startup> \n        <supportedRuntime version=\"v4.0\" sku=\".N"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/App.xaml",
    "chars": 439,
    "preview": "<Application x:Class=\"MailDisk_GUI.App\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n "
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/App.xaml.cs",
    "chars": 310,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Configuration;\nusing System.Data;\nusing System.Linq;\nusing"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/FodyWeavers.xml",
    "chars": 159,
    "preview": "<Weavers xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n  <Prop"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/FodyWeavers.xsd",
    "chars": 9511,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n  <!-- This file was gen"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/MailDisk-GUI.csproj",
    "chars": 7039,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/MainWindow.xaml",
    "chars": 7976,
    "preview": "<Window x:Class=\"MailDisk_GUI.MainWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    "
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/MainWindow.xaml.cs",
    "chars": 617,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusin"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/Properties/AssemblyInfo.cs",
    "chars": 1618,
    "preview": "using System.Reflection;\nusing System.Resources;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServ"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/Properties/Resources.Designer.cs",
    "chars": 2442,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n/"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/Properties/Resources.resx",
    "chars": 5494,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/Properties/Settings.Designer.cs",
    "chars": 1066,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/Properties/Settings.settings",
    "chars": 193,
    "preview": "<?xml version='1.0' encoding='utf-8'?>\n<SettingsFile xmlns=\"uri:settings\" CurrentProfile=\"(Default)\">\n  <Profiles>\n    "
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/languages/en-US.xaml",
    "chars": 613,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http:"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/languages/zh-CN.xaml",
    "chars": 595,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http:"
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI/packages.config",
    "chars": 465,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Costura.Fody\" version=\"4.1.0\" targetFramework=\"net462\""
  },
  {
    "path": "MailDisk-GUI/MailDisk-GUI.sln",
    "chars": 1115,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.3071"
  },
  {
    "path": "README.md",
    "chars": 1490,
    "preview": "# 邮箱网盘\r\n\r\n![build](https://github.com/chenxuuu/Mail-Box-Net-Disk/workflows/build/badge.svg)\r\n![Build GUI client](https:/"
  },
  {
    "path": "maildisk/maildisk/Program.cs",
    "chars": 6816,
    "preview": "using MailKit;\r\nusing MailKit.Net.Imap;\r\nusing MailKit.Search;\r\nusing System;\r\nusing maildisk.apis;\r\nusing System.IO;\r\nu"
  },
  {
    "path": "maildisk/maildisk/apis/MailClient.cs",
    "chars": 3290,
    "preview": "using MailKit;\r\nusing MailKit.Net.Imap;\r\nusing MailKit.Search;\r\nusing System;\r\nusing System.Collections;\r\nusing System."
  },
  {
    "path": "maildisk/maildisk/apis/Settings.cs",
    "chars": 2920,
    "preview": "using Newtonsoft.Json;\r\nusing Newtonsoft.Json.Linq;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Diag"
  },
  {
    "path": "maildisk/maildisk/apis/VisualDisk.cs",
    "chars": 25344,
    "preview": "using MailKit;\r\nusing MailKit.Net.Imap;\r\nusing MailKit.Net.Smtp;\r\nusing MailKit.Search;\r\nusing MimeKit;\r\nusing System;\r\n"
  },
  {
    "path": "maildisk/maildisk/maildisk.csproj",
    "chars": 573,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\r\n\r\n  <PropertyGroup>\r\n    <OutputType>Exe</OutputType>\r\n    <TargetFramework>net5.0</"
  },
  {
    "path": "maildisk/maildisk.sln",
    "chars": 1120,
    "preview": "\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.28307.168"
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the chenxuuu/Mail-Box-Net-Disk GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 32 files (100.1 KB), approximately 23.7k tokens, and a symbol index with 31 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!