.NET 的 IMAP 文件夹路径编码 (IMAP UTF-7)?

2024-03-31

IMAP 规范(RFC 2060 http://www.faqs.org/rfcs/rfc2060.html、5.1.3。邮箱国际命名约定)描述了如何处理文件夹名称中的非 ASCII 字符。它定义了一个modifiedUTF-7编码:

按照惯例,国际邮箱 名称是使用指定的 UTF-7 编码的修改版本 [UTF-7] 中描述。目的 这些修改是为了纠正 UTF-7 存在以下问题:

  1. UTF-7使用“+”字符进行移位;这与 邮箱名称中常见的“+”用法,特别是 USENET 新闻组名称。

  2. UTF-7的编码是BASE64,使用“/”字符;这 与使用“/”作为流行的层次结构分隔符相冲突。

  3. UTF-7 禁止未编码的使用“\”;这与 使用“\”作为流行的层次结构分隔符。

  4. UTF-7禁止未编码的“~”的使用;这与 在某些服务器中使用“~”作为主目录指示符。

  5. UTF-7 允许用多种替代形式来表示同一字符串;特别是,可打印的 US-ASCII 字符可以以编码形式表示。

在修改后的 UTF-7 中,除“&”之外的可打印 US-ASCII 字符均代表其自身; 即八位字节值为 0x20-0x25 的字符 和0x27-0x7e。人物 ”&” (0x26) 由两个八位字节序列“&-”表示。

所有其他字符(八位字节值 0x00-0x1f、0x7f-0xff 和所有 Unicode 16 位八位字节)均表示 在修改后的 BASE64 中,进一步 对 [UTF-7] 的修改是“,” 用来代替“/”。
修改后的 BASE64 不得用于表示 任何打印 US-ASCII 字符 可以代表它自己。

“&”用于转移修改 BASE64 和“-”转回 US-ASCII。所有名称均以 US-ASCII 开头, 并且必须以 US-ASCII 结尾(即 以 Unicode 16 位结尾的名称 八位字节必须以“-”结尾)。

在我开始实施之前,我的问题是:是否有一些.NET 代码/库在那里(甚至在框架中)可以完成这项工作?我找不到 .NET 资源(仅其他语言/框架的实现 http://search.cpan.org/~pmakholm/Encode-IMAPUTF7-1.01/lib/Encode/IMAPUTF7.pm).

谢谢你!


//
// ImapEncoding.cs
//
// Author: Jeffrey Stedfast <[email protected] /cdn-cgi/l/email-protection>
//
// Copyright (c) 2013-2019 Microsoft Corp. (www.microsoft.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

using System.Text;

namespace MailKit.Net.Imap {
    static class ImapEncoding
    {
        const string utf7_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";

        static readonly byte[] utf7_rank = {
            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
            255,255,255,255,255,255,255,255,255,255,255, 62, 63,255,255,255,
             52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,255,255,255,
            255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
             15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
            255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
             41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
        };

        public static string Decode (string text)
        {
            var decoded = new StringBuilder ();
            bool shifted = false;
            int bits = 0, v = 0;
            int index = 0;
            char c;

            while (index < text.Length) {
                c = text[index++];

                if (shifted) {
                    if (c == '-') {
                        // shifted back out of modified UTF-7
                        shifted = false;
                        bits = v = 0;
                    } else if (c > 127) {
                        // invalid UTF-7
                        return text;
                    } else {
                        byte rank = utf7_rank[(byte) c];

                        if (rank == 0xff) {
                            // invalid UTF-7
                            return text;
                        }

                        v = (v << 6) | rank;
                        bits += 6;

                        if (bits >= 16) {
                            char u = (char) ((v >> (bits - 16)) & 0xffff);
                            decoded.Append (u);
                            bits -= 16;
                        }
                    }
                } else if (c == '&' && index < text.Length) {
                    if (text[index] == '-') {
                        decoded.Append ('&');
                        index++;
                    } else {
                        // shifted into modified UTF-7
                        shifted = true;
                    }
                } else {
                    decoded.Append (c);
                }
            }

            return decoded.ToString ();
        }

        static void Utf7ShiftOut (StringBuilder output, int u, int bits)
        {
            if (bits > 0) {
                int x = (u << (6 - bits)) & 0x3f;
                output.Append (utf7_alphabet[x]);
            }

            output.Append ('-');
        }

        public static string Encode (string text)
        {
            var encoded = new StringBuilder ();
            bool shifted = false;
            int bits = 0, u = 0;

            for (int index = 0; index < text.Length; index++) {
                char c = text[index];

                if (c >= 0x20 && c < 0x7f) {
                    // characters with octet values 0x20-0x25 and 0x27-0x7e
                    // represent themselves while 0x26 ("&") is represented
                    // by the two-octet sequence "&-"

                    if (shifted) {
                        Utf7ShiftOut (encoded, u, bits);
                        shifted = false;
                        bits = 0;
                    }

                    if (c == 0x26)
                        encoded.Append ("&-");
                    else
                        encoded.Append (c);
                } else {
                    // base64 encode
                    if (!shifted) {
                        encoded.Append ('&');
                        shifted = true;
                    }

                    u = (u << 16) | (c & 0xffff);
                    bits += 16;

                    while (bits >= 6) {
                        int x = (u >> (bits - 6)) & 0x3f;
                        encoded.Append (utf7_alphabet[x]);
                        bits -= 6;
                    }
                }
            }

            if (shifted)
                Utf7ShiftOut (encoded, u, bits);

            return encoded.ToString ();
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

.NET 的 IMAP 文件夹路径编码 (IMAP UTF-7)? 的相关文章

  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • 在.rdlc报告的底部设置一个文本框

    我在 rdlc 报告中使用 tablix 有一个文本框 其中包含文本 签名 我想将此文本框放置在报告最后一页的底部 就在页脚之前 我已经用谷歌搜索了这个解决方案 但没有找到满意的结果 我的环境是VS2010 framework 4 0 有什
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • 如何将图像路径保存到Live Tile的WP8本地文件夹

    我正在更新我的 Windows Phone 应用程序以使用新的 WP8 文件存储 API 本地文件夹 而不是 WP7 API 隔离存储文件 旧的工作方法 这是我如何成功地将图像保存到 共享 ShellContent文件夹使用隔离存储文件方法
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • 从路径中获取文件夹名称

    我有一些路c server folderName1 another name something another folder 我如何从那里提取最后一个文件夹名称 我尝试了几件事 但没有成功 我只是不想寻找最后的 然后就去休息了 Thank
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • 将文本叠加在图像背景上并转换为 PDF

    使用 NET 我想以编程方式创建一个 PDF 它仅包含一个背景图像 其上有两个具有不同字体和位置的标签 我已阅读过有关现有 PDF 库的信息 但不知道 如果适用 哪一个对于如此简单的任务来说最简单 有人愿意指导我吗 P D 我不想使用生成的
  • WCF:将随机数添加到 UsernameToken

    我正在尝试连接到用 Java 编写的 Web 服务 但有些东西我无法弄清楚 使用 WCF 和 customBinding 几乎一切似乎都很好 除了 SOAP 消息的一部分 因为它缺少 Nonce 和 Created 部分节点 显然我错过了一
  • 有没有办法禁用 .NET 标签的“双击复制”功能?

    这真的很烦人 我使用标签作为列表项用户控件的一部分 用户可以单击它来选择列表项 然后双击它来重命名它 但是 如果剪贴板中有名称 双击标签会将其替换为标签文本 我还检查了应用程序中的其他标签 双击它们也会将其复制到剪贴板 我没有在这个程序中编
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a
  • mysql-connector-c++ - “get_driver_instance”不是“sql::mysql”的成员

    我是 C 的初学者 我认为学习的唯一方法就是接触一些代码 我正在尝试构建一个连接到 mysql 数据库的程序 我在 Linux 上使用 g 没有想法 我运行 make 这是我的错误 hello cpp 38 error get driver
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46
  • ASP.NET MVC 6 (ASP.NET 5) 中的 Application_PreSendRequestHeaders 和 Application_BeginRequest

    如何在 ASP NET 5 MVC6 中使用这些方法 在 MVC5 中 我在 Global asax 中使用了它 现在呢 也许是入门班 protected void Application PreSendRequestHeaders obj

随机推荐