private static void TranslateVENV(InputFileBuffer reader, DirectoryInfo outFileDir) { if (!reader.StartsWith("BEGIN:VENV")) { throw new Exception(string.Format("BEGIN:VENVが見つかりません。: pos={0}", reader.Position)); } reader.Drop(10); reader.DropNewLine(); if (reader.StartsWith("BEGIN:VENV")) { TranslateVENV(reader, outFileDir); } else if (reader.StartsWith("BEGIN:VCARD")) { TranslateVCARD(reader); } else if (reader.StartsWith("BEGIN:VBODY")) { TranslateVBODY(reader, outFileDir); } else { throw new Exception(string.Format("未知のヘッダです。({1}): pos={0}", reader.Position, Encoding.ASCII.GetString(reader.ReadLine()))); } if (!reader.StartsWith("END:VENV")) { throw new Exception(string.Format("END:VENVが見つかりません。: pos={0}", reader.Position)); } reader.Drop(8); reader.DropNewLine(); }
private static void TranslateVMSG(InputFileBuffer reader, DirectoryInfo outFileDir) { if (!reader.StartsWith("BEGIN:VMSG")) { throw new Exception(string.Format("BEGIN:VMSGが見つかりません。: pos={0}", reader.Position)); } reader.Drop(10); reader.DropNewLine(); while (!reader.IsEof()) { if (reader.StartsWith("END:VMSG")) { break; } else if (reader.StartsWith("BEGIN:VENV")) { TranslateVENV(reader, outFileDir); } else if (reader.StartsWith("BEGIN:VCARD")) { TranslateVCARD(reader); } else { var data = reader.ReadLine(); //System.Diagnostics.Debug.WriteLine("skipped: " + Encoding.ASCII.GetString(data)); } } if (!reader.StartsWith("END:VMSG")) { throw new Exception(string.Format("END:VMSGが見つかりません。: pos={0}", reader.Position)); } reader.Drop(8); reader.DropNewLine(); }
private static void TranslateVCARD(InputFileBuffer reader) { if (!reader.StartsWith("BEGIN:VCARD")) { throw new Exception(string.Format("BEGIN:VCARDが見つかりません。: pos={0}", reader.Position)); } reader.Drop(11); reader.DropNewLine(); while (!reader.IsEof()) { if (reader.StartsWith("END:VCARD")) { break; } else { // NOP } } if (!reader.StartsWith("END:VCARD")) { throw new Exception(string.Format("END:VCARDが見つかりません。: pos={0}", reader.Position)); } reader.Drop(9); reader.DropNewLine(); }
static void Main(string[] args) { var dir = new DirectoryInfo("."); foreach (var inFile in dir.EnumerateFiles("*.vmg")) { using (var inStream = inFile.OpenRead()) using (var inBuffer = new BufferedStream(inStream)) { var reader = new InputFileBuffer(inBuffer); while (!reader.IsEof()) { TranslateVMSG(reader, inFile.Directory); } } } }
private static void TranslateVBODY(InputFileBuffer reader, DirectoryInfo outFileDir) { if (!reader.StartsWith("BEGIN:VBODY")) { throw new Exception(string.Format("BEGIN:VBODYが見つかりません。: pos={0}", reader.Position)); } reader.Drop(11); reader.DropNewLine(); var headers = new List <string>(); while (!reader.IsEof()) { // 最初の空行までヘッダとみなす var header = Encoding.ASCII.GetString(reader.ReadLine()); if (header.Trim() == "") { break; } headers.Add(header); } if (reader.IsEof()) { throw new Exception(string.Format("END:VBODYが見つかりません。: pos={0}", reader.Position)); } if (!headers.Any(header => header.StartsWith("Message-Id:"))) { // Message-Id ヘッダが存在しない場合は、 From ヘッダと Date ヘッダの内容から作る。 var fromMailAddress = headers .Where(s => s.StartsWith("From:")) .Select(s => s.Substring(5).Trim()) .Select(s => { var m = _mailAddressPattern1.Match(s); if (!m.Success) { m = _mailAddressPattern2.Match(s); } if (!m.Success) { return(null); } else { return(m.Groups["mailAddress"].Value); } }) .Where(s => s != null) .FirstOrDefault(); var date = headers .Where(s => s.StartsWith("Date:")) .Select(s => s.Substring(5).Trim()) .Select(s => { DateTime dateTime; return(DateTime.TryParse(s, out dateTime) ? dateTime : (DateTime?)null); }) .Where(dateTime => dateTime != null) .FirstOrDefault(); if (fromMailAddress == null || date == null) { throw new Exception("FromヘッダまたはDateヘッダがありません。"); } headers.Insert(0, string.Format("Message-Id: {0}.{1}\r\n", date.Value.ToString("yyyyMMddHHmmss"), fromMailAddress)); } var messageId = headers .Where(s => s.StartsWith("Message-Id:")) .Select(s => s.Substring(11).Trim()) .First(); var outFile = new FileInfo(Path.Combine(outFileDir.FullName, messageId + ".eml")); using (var outStream = outFile.Create()) { var writer = new OutputFileBuffer(outStream); // ヘッダの出力 foreach (var header in headers) { writer.Write(header); } // ヘッダの後の空行の出力 writer.Write("\r\n"); // "END:VBODY" が見つかるまでコピー while (!reader.IsEof()) { // メール本文中に "END:VBODY" が書かれていても .vmg ファイルでは "/END:VBODY" にエスケープされているので以下の条件には HIT しない。 if (reader.StartsWith("END:VBODY")) { break; } var data = reader.ReadLine(); var line = Encoding.ASCII.GetString(data); if (_endVBodyEscapePattern.IsMatch(line)) { // "/END:VBODY" が見つかった場合は、エスケープを解除するために先頭の '/' を除去する。 writer.Write(line.Substring(1)); } else { writer.Write(data); } //System.Diagnostics.Debug.WriteLine("copied: " + Encoding.ASCII.GetString(data)); } } if (!reader.StartsWith("END:VBODY")) { throw new Exception(string.Format("END:VBODYが見つかりません。: pos={0}", reader.Position)); } reader.Drop(9); reader.DropNewLine(); }