オープンシステム開発特論(PHPの演習)

MailDir形式の複数ファイルから必要なデータを取り出す課題を例に

ファイルからのデータの読み込みと処理1

  1. ディレクトリ関数を利用して,ディレクトリ内のファイル一覧を取得
  2. ファイルを開き,1行ずつデータを読み込む
  3. 1行データから目的の行を選び出す
  4. MIMEデーコード

プログラム例と次の課題

<?php

$dir = "/home/toyoki/Maildir/.edu.OpenSys11/cur/"; // 末尾のスラッシュは必須
mb_internal_encoding("UTF-8");

if (is_dir($dir)) {
  $dh = opendir($dir);
  if ($dh != false) {
    while (1) {
      $file = readdir($dh);
      if($file == false) break;
      // echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
      $filename[] = $dir . $file;
    }
    closedir($dh);
  }
}

/****** $filenameのひとつひとつの要素をとりだし、それを$fに代入して実行*****/
foreach($filename as $f) {
  /* 数字で始まっているファイルのみ扱う */
  /* 未実装: 課題 */

  $maildate=''; $suject = ''; $addr='';

  $handle = fopen($f,"r"); //ファイル$fを開く
  if($handle == false) {
    echo "ファイルが開けませんでした。" . $f;
  }
  echo "file: $f\n";

  while (!feof($handle)) {
    $buffer = fgets($handle);  // 一行ずつ読み込む
    $buffer = trim($buffer);   // 末尾の改行コードを取る
    $pos = strpos($buffer, "Subject:");
    if($pos === 0) {
      $buffer = mb_decode_mimeheader($buffer);              //MIMEデコード
      $subject = preg_replace("/^Subject: /", "", $buffer); //行頭の"Subject: "をとる

    } elseif(($pos = strpos($buffer, "Date:")) ===0) {
      // Date: 行は、$maildate に記憶
      $maildate = $buffer;
      //$maildate = preg_replace("/^Date: /", "", $buffer);

    } elseif(($pos = strpos($buffer, "From:")) ===0) {
    // From: 行は、$addrに記憶
      $addr = preg_replace("/^From: /", "", $buffer);
    }
  }
  /* 次回までの演習:
   * うまく抽出できないメールファイルの分析
   *  $maildateでソートし,一覧をファイルに出力する
   *  年月日,時刻文字列の処理は,マニュアル「日付・時刻関数」の節にある.
   *  ファイルシステム関数で,ファイルへの書き出しを行う.
   */
  echo $maildate . "," . $addr . "," . $subject . "\n";

  fclose($handle);
}

?>

これでうまく行ってないメールがある.その原因解析も課題

→ Subjectが2行にわかれている場合

Date文字列の処理

(11/22)

年月日,時刻でのソート

"Date:"に記された年月日,日時の文字列は

Tue, 7 Feb 2012 15:39:22 +0900

のようになっている.これを一度unixtime (1970/01/01 00:00:00からの秒数)に直し,それでソートする.年月日,時刻からunixtimeを計算する関数はmktime()である.

Dateの文字列をまずは,explodeで分解するとつぎのような配列になる.

Array ( [0] => Date: [1] => Tue, [2] => 7 [3] => Feb [4] => 2012 [5] => 15:39:22 [6] => +0900 )

5番目の要素をさらにコロンで分解すると時,分,秒が得られる.それらをmkdate()関数の引数に与えてunixtimeを得る.

mktime()の逆,つまりunixtimeから書式化された年月日,時刻を得るには,date()関数を利用する.

関数の定義と利用

http://cosmos.js.yamanashi.ac.jp/~toyoki/lectures/bwp/function.html をみて実習する.

mail

関数の利用

ファイルに格納されたメール(テキスト)を読み込み,必要な情報を抽出するには,mailparse関数を利用するのが便利である.

http://www.php.net/manual/ja/ref.mailparse.php

MimeMailParser

上のmailpaseを直接利用するより,それを活用した次のクラスコードを利用するのが良さそうだ.(11/22)

https://code.google.com/p/php-mime-mail-parser/source/browse/trunk/MimeMailParser.class.php

解説,参考プログラムはMimeMailParser.html

なお,メール形式の規則はRFC文書に定義されており,最新版は

http://www.hde.co.jp/rfc/rfc5322_ja.txt

である.(2013/11現在)

ファイルへの出力

ファイルへの書き込みは

  $handle_out = fopen("出力ファイル名","w");

  fputs($handle_out, "出力文字列");
  fprintf($handle_out,"Cと同様の書式", 変数名の列);

  $fclose($handle_out);