メールの保存 †最近 PC が立て続けに故障して、電子メールを Webメール(Active!mail)主体にした。 ところが運用上の容量制限があるので、定期的に消去せざるを得ない。 年次報告のこととか考えると、せめて1年分は保存したい ところだ。 この Active!mail にはフォルダの export機能があって これでローカルPCに取り込んで、あとはファイルの バックアップをすればよい。 さて、保存・バックアップはできたが、問題がある。 もとに戻すには importすれば よいのだが、容量制限のために泣く泣くexport しているので、 容量に余裕を作らない限りもとへ戻せるはずもなく、 古いメールは、なんとかして保存したローカルPC上で読みたい。 できれば、保存したメールのバックアップを USB などに入れて、 どこでも差した PC の上で読みたい。 というわけで、この Active!mail の保存ファイルの形式を 調べてみた。実はなんと言うことはない、UNIX の mbox 形式の ファイルだ。ただ、この mbox 形式というのが曲者で、標準化 されてないので、亜流がいろいろあることだ。まあでも普通に 扱う分にはそれほど困らないだろうということで、ここから 単一のメールを取りだす(何番目のメールと指定する。指定 しないと From行のリストを打ち出す)プログラムを書いてみた。 mbox の各メールは eml という形式で、このプログラムの 出力は標準出力なので、xxx.eml などという名前のファイルに redirect してやればよい。 残る問題はこの eml を 読むプログラムであるが、Windows Vista までなら Outlook Express、 Windows 7 の場合は Windows Live Mail で読める。 というわけで、mbox形式のファイルから単体メール(eml)を取りだす プログラム、無くさないようにソースを残しておこう。 // m2.cpp #include <iostream> #include <fstream> #include <sstream> #include <string> int m_getline(std::string& s, std::istream& is) { // returns linesize (excluding EOL), -1 if error. s.clear(); char c; while(is.get(c)) { if(c == '\n') break; s.push_back(c); } if ((s.size() == 0) && !is) return (-1); return (int)s.size(); } bool m_fromline(std::string& s) { if (s.size() < 5) return false; if (s.compare(0,5,"From ") == 0) return true; return false; } int main(int argc, char* argv[]) { if ((argc < 2) || (argc > 3)) { std::cerr << "Usage: " << argv[0] << " mbx_file [mail_number]" << std::endl; return (-1); } std::ifstream ifs(argv[1]); if (!ifs) { std::cerr << "File open error: " << argv[1] << std::endl; return (-2); } int mailnumber = 0; if (argc == 3) { std::stringstream ss(argv[2]); ss >> mailnumber; } int nth = 0; bool prevline_empty = true; std::string line; while(m_getline(line, ifs) >= 0) { if (prevline_empty && m_fromline(line)) { ++nth; if (mailnumber == 0) std::cout << "[" << nth << "] " << line << std::endl; else if (mailnumber == nth) break; } if (line.size() == 0) prevline_empty = true; else prevline_empty = false; } if (mailnumber == 0) return 0; std::cout << line << std::endl; prevline_empty = false; while(m_getline(line, ifs) >= 0) { if (prevline_empty && m_fromline(line)) break; if (line.size() == 0) { prevline_empty = true; std::cout << std::endl; } else { prevline_empty = false; std::cout << line << std::endl; } } return 0; } 何と98行もあるぞ。 |