/// <summary>
        /// ファイルから読込(宛先、送信元は読み込まない)
        /// </summary>
        /// <param name="filename">ファイル名</param>
        /// <returns>(件名, 本文)</returns>
        public static (string, string) LoadFromFile(string filename)
        {
            byte[] data = File.ReadAllBytes(filename);

            string subjectText = "";
            string bodyText    = "";

            // ボディ部の先頭を見つける
            int indexBody = 0;

            for (int i = 0; i < data.Length; ++i)
            {
                if (CharCodeUtils.IsCrLf(data, i) && CharCodeUtils.IsCrLf(data, i + 2))
                {
                    indexBody = i + 4;
                    break;
                }
            }
            if (indexBody == 0)
            {
                throw new Exception("形式が違います: ボディ部が存在しません。");
            }

            string headers = Encoding.ASCII.GetString(data, 0, indexBody);

            subjectText = GetSubjectText(headers);

            bodyText = GetBodyText(data, indexBody);

            return(subjectText, bodyText);
        }
Exemple #2
0
        /// <summary>
        /// 全角文字の文字コード(JIS)から文字を取得する
        /// </summary>
        /// <param name="jiscode">JIS コード</param>
        /// <returns>文字(1文字): 取得できない場合は null</returns>
        public static string GetCharFromJisCode(int jiscode)
        {
            (byte high, byte low) = CharCodeUtils.SplitHL(jiscode);

            if (0x21 <= high && high <= 0x7e)
            {
                // OK
            }
            else
            {
                return(null);
            }

            if (0x21 <= low && low <= 0x7e)
            {
                // OK
            }
            else
            {
                return(null);
            }

            byte[] bistr = new byte[] {
                JIS_BEGIN_ESCAPE_SEQUENCE[0],
                JIS_BEGIN_ESCAPE_SEQUENCE[1],
                JIS_BEGIN_ESCAPE_SEQUENCE[2],
                high, low,
                JIS_END_ESCAPE_SEQUENCE[0],
                JIS_END_ESCAPE_SEQUENCE[1],
                JIS_END_ESCAPE_SEQUENCE[2]
            };

            string result = null;

            try {
                result = jisEncoding.GetString(bistr);
            } catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }

            return(result);
        }
Exemple #3
0
        /// <summary>
        /// 本文を JIS エンコーディングした MemoryStream を返す
        /// NOTE: 半角カタカナは処理できないので渡さないこと
        /// </summary>
        /// <param name="bodyText">本文</param>
        /// <returns>エンコーディング内容を格納した MemoryStream</returns>
        private static MemoryStream GetBodyStream(string bodyText)
        {
            int maxBodyCols;

            if (DataBags.Config.ForceInsertLineFeed)
            {
                maxBodyCols = DataBags.Config.MaxBodyCols * 2;
            }
            else
            {
                maxBodyCols = int.MaxValue;
            }

            MemoryStream stream = new MemoryStream();

            int  cols  = 0;
            bool jisIn = false;

            for (int i = 0; i < bodyText.Length; ++i)
            {
                string sch = bodyText.Substring(i, 1);

                if (StringUtils.IsAsciiWithControl(sch))
                {
                    if (jisIn)
                    {
                        CharCodeUtils.WriteJisEndEscapeSequence(stream);
                    }

                    jisIn = false;

                    if (sch[0] == '\n')
                    {
                        CharCodeUtils.WriteCrLf(stream);
                        cols = 0;
                    }
                    else
                    {
                        char ascii = sch[0];
                        stream.WriteByte((byte)(ascii & 0xFF));
                        ++cols;
                    }
                }
                else
                {
                    if (!jisIn)
                    {
                        CharCodeUtils.WriteJisBeginEscapeSequence(stream);
                    }
                    jisIn = true;

                    int   jiscode;
                    Emoji emoji = DataBags.Emojis.GetFromUnicode(sch[0]);
                    if (emoji != null)
                    {
                        jiscode = emoji.Jiscode;
                    }
                    else
                    {
                        jiscode = CharCodeUtils.GetJisCodeFromChar(sch);
                        if (jiscode == 0)
                        {
                            jiscode = CharCodeUtils.JIS_WHITE_SPACE_CODE;
                        }
                    }

                    (byte high, byte low) = CharCodeUtils.SplitHL(jiscode);

                    stream.WriteByte(high);
                    stream.WriteByte(low);
                    cols += 2;
                }

                if (maxBodyCols <= cols)
                {
                    if (jisIn)
                    {
                        CharCodeUtils.WriteJisEndEscapeSequence(stream);
                    }
                    CharCodeUtils.WriteCrLfWithFlowed(stream);
                    if (jisIn)
                    {
                        CharCodeUtils.WriteJisBeginEscapeSequence(stream);
                    }

                    cols = 0;
                }
            }
            if (jisIn)
            {
                CharCodeUtils.WriteJisEndEscapeSequence(stream);
            }

            return(stream);
        }
Exemple #4
0
        /// <summary>
        /// 件名を固定長に分け、BASE64 エンコーディングして返す
        /// NOTE: 改行は処理できないので渡さないこと
        /// NOTE: 半角カタカナは処理できないので渡さないこと
        /// </summary>
        /// <param name="subjectText">件名</param>
        /// <param name="maxCols">件名を分けるための長さ</param>
        /// <returns>複数の BASE64 文字列の一覧</returns>
        private static List <string> GetBase64EncodingBlocks(string subjectText, int maxCols)
        {
            List <string> base64EncodingBlocks = new List <string>();

            MemoryStream stream = new MemoryStream();

            int  cols  = 0;
            bool jisIn = false;

            for (int i = 0; i < subjectText.Length; ++i)
            {
                string sch = subjectText.Substring(i, 1);

                if (StringUtils.IsAsciiWithControl(sch))
                {
                    if (jisIn)
                    {
                        CharCodeUtils.WriteJisEndEscapeSequence(stream);
                    }

                    jisIn = false;

                    char ascii = sch[0];
                    stream.WriteByte((byte)(ascii & 0xFF));
                    ++cols;
                }
                else
                {
                    if (!jisIn)
                    {
                        CharCodeUtils.WriteJisBeginEscapeSequence(stream);
                    }
                    jisIn = true;

                    int   jiscode;
                    Emoji emoji = DataBags.Emojis.GetFromUnicode(sch[0]);
                    if (emoji != null)
                    {
                        jiscode = emoji.Jiscode;
                    }
                    else
                    {
                        jiscode = CharCodeUtils.GetJisCodeFromChar(sch);
                        if (jiscode == 0)
                        {
                            jiscode = CharCodeUtils.JIS_WHITE_SPACE_CODE;
                        }
                    }

                    (byte high, byte low) = CharCodeUtils.SplitHL(jiscode);

                    stream.WriteByte(high);
                    stream.WriteByte(low);
                    ++cols;
                }

                if (maxCols <= cols)
                {
                    if (jisIn)
                    {
                        CharCodeUtils.WriteJisEndEscapeSequence(stream);
                    }
                    base64EncodingBlocks.Add(GetBase64EncodingBlock(stream));
                    stream = new MemoryStream();
                    if (jisIn)
                    {
                        CharCodeUtils.WriteJisBeginEscapeSequence(stream);
                    }

                    cols = 0;
                }
            }
            if (jisIn)
            {
                CharCodeUtils.WriteJisEndEscapeSequence(stream);
            }
            if (0 < stream.Length)
            {
                base64EncodingBlocks.Add(GetBase64EncodingBlock(stream));
            }

            return(base64EncodingBlocks);
        }
        /// <summary>
        /// ヘッダ文字列から件名を取得する
        /// NOTE: 自分で出力した形式にしか対応していない
        /// </summary>
        /// <param name="headers">ヘッダ文字列</param>
        /// <returns>件名</returns>
        private static string GetSubjectText(string headers)
        {
            int startIndex = headers.IndexOf(MailMessage.SUBJECT, 0, StringComparison.CurrentCultureIgnoreCase);

            if (startIndex < 0)
            {
                return("");
            }

            startIndex += MailMessage.SUBJECT.Length;

            int index    = startIndex;
            int endIndex = startIndex;

            while (true)
            {
                index = headers.IndexOf("\r\n", index);
                if (index < 0)
                {
                    break;
                }
                if (headers.Length <= index + 2)
                {
                    break;
                }
                endIndex = index;
                if (headers[index + 2] != ' ' && headers[index + 2] != '\t')
                {
                    break;
                }
                index += 2;
            }
            if (endIndex == startIndex)
            {
                return("");
            }

            string subject = headers.Substring(startIndex, endIndex - startIndex);
            Regex  regex   = new Regex(@"=\?(?<charset>.*?)\?(?<encoding>.)\?(?<value>.*?)\?=");

            StringBuilder result = new StringBuilder();

            MatchCollection matchCollection = regex.Matches(subject);

            foreach (Match match in matchCollection)
            {
                if (match.Success)
                {
                    string charset  = match.Groups["charset"].Value.ToLower();
                    string encoding = match.Groups["encoding"].Value.ToLower();
                    string val      = match.Groups["value"].Value;

                    if (charset == "iso-2022-jp" && encoding == "b")
                    {
                        // OK
                    }
                    else
                    {
                        // 未対応
                        return("");
                    }

                    byte[] dataPart = Convert.FromBase64String(val);
                    bool   inJpn    = false;

                    int dataPartLength = dataPart.Length;

                    for (int i = 0; i < dataPartLength;)
                    {
                        if (CharCodeUtils.IsBeginEscapeSequence(dataPart, i))
                        {
                            inJpn = true;
                            i    += 3;
                            continue;
                        }
                        if (CharCodeUtils.IsEndEscapeSequence(dataPart, i))
                        {
                            inJpn = false;
                            i    += 3;
                            continue;
                        }
                        if (inJpn)
                        {
                            if (i <= dataPartLength - 2)
                            {
                                int   jiscode = CharCodeUtils.MergeHL(dataPart[i], dataPart[i + 1]);
                                Emoji emoji   = DataBags.Emojis.GetFromJiscode(jiscode);
                                if (emoji != null)
                                {
                                    result.Append(emoji.Unicode);
                                }
                                else
                                {
                                    string sch = CharCodeUtils.GetCharFromJisCode(jiscode);
                                    if (sch != null)
                                    {
                                        result.Append(sch);
                                    }
                                }

                                i += 2;
                            }
                            else
                            {
                                i += 1;
                            }
                        }
                        else
                        {
                            char ascii = (char)dataPart[i];
                            result.Append(ascii);
                            i += 1;
                        }
                    }
                }
            }

            return(result.ToString());
        }
        /// <summary>
        /// ボディ部データから本文を取得する
        /// NOTE: 自分で出力した形式にしか対応していない
        /// </summary>
        /// <param name="data">ボディ部データ</param>
        /// <param name="offset">オフセット</param>
        /// <returns>本文</returns>
        private static string GetBodyText(byte[] data, int offset)
        {
            bool inJpn = false;

            int dataLength = data.Length;

            StringBuilder result = new StringBuilder();

            for (int i = offset; i < dataLength;)
            {
                if (CharCodeUtils.IsCrLf(data, i))
                {
                    inJpn = false;
                    i    += 2;
                    result.Append("\r\n");
                    continue;
                }
                if (CharCodeUtils.IsBeginEscapeSequence(data, i))
                {
                    inJpn = true;
                    i    += 3;
                    continue;
                }
                if (CharCodeUtils.IsEndEscapeSequence(data, i))
                {
                    inJpn = false;
                    i    += 3;
                    continue;
                }
                if (inJpn)
                {
                    if (i <= dataLength - 2)
                    {
                        int   jiscode = CharCodeUtils.MergeHL(data[i], data[i + 1]);
                        Emoji emoji   = DataBags.Emojis.GetFromJiscode(jiscode);
                        if (emoji != null)
                        {
                            result.Append(emoji.Unicode);
                        }
                        else
                        {
                            string sch = CharCodeUtils.GetCharFromJisCode(jiscode);
                            if (sch != null)
                            {
                                result.Append(sch);
                            }
                        }

                        i += 2;
                    }
                    else
                    {
                        i += 1;
                    }
                }
                else
                {
                    char ascii = (char)data[i];
                    result.Append(ascii);
                    i += 1;
                }
            }

            return(result.ToString());
        }