Recent Entries
Archives
Search


Links
Powered by
Movable Type 2.64

2003年08月28日

PHPでimapで添付ファイル

ちょっとMSNメッセンジャー周辺で話題にでたので… PHPでというか、uw-imapdでimapの添付メール(attachment)取得を行った場合に、生JISで添付ファイル名がつけられているものを正しく取り扱えない場合があります。というか、取り扱えません。uw-imapd自身が添付ファイル名部分のパースに失敗するためです。
[PHP-jp 12088]
#ほかの imapdの実装それぞれでどうだかは不明 で、解決策としてはimap_fetchbodyで全体分捕ってきて自前で解析するしかないということになります。最近のPEARライブラリには入ってるかもしれませんが…
function mail_Q_decode($str) {
  $i = 0;
  $l = strlen($str);
  while ($i < $l) {
    while ($str[$i] != '=' && $i < $l) {
      $r .= $str[$i++];
    }
    if ($i == $l) break;
    while ($str[$i] == '=' && $i < $l) {
      $r .= chr($str[$i+1]*16+$str[$i+2]);
      $i += 3;
    }
    if ($i >= $l) break;
  }
  return $r;
}

function mail_decode_BQ($s, $tocharset) {
  while ($s) {
  if (!is_string($idx = strpos($s, "=?")) || $idx) {
    $sf = substr($s, 0, $idx);
    $sr = substr($s, $idx +2);
    if (!is_string($idy = strpos($sr, "?=")) || $idy) {
      $sri = substr($sr, 0, $idy);
      $srj = substr($sr, $idy +2);
//      echo "sri=".$sri."\n";
//      echo "srj=".$srj."\n";
      $funcname = "stripslashes";
      if (eregi('^Shift_jis(.*)\?([BQ])\?(.*)$', $sri, $bs)) {
        $fromcode = "SJIS";
      }else if (eregi('^iso-2022-jp(.*)\?([BQ])\?(.*)$', $sri, $bs)) {
        $fromcode = "JIS";
      }else if (eregi('^iso-8859-(.*)\?([BQ])\?(.*)$', $sri, $bs)) {
        $fromcode = "pass";
      }
      if ($bs[2] == 'B') $funcname = "base64_decode";
      if ($bs[2] == 'Q') $funcname = "mail_Q_decode";

      $ts = i18n_convert($funcname($bs[3]), $tocharset, $fromcode);
    }else{
// krudge;
      $ts = $sri;
    }
    $r .= ($sf.$ts);
    $s = $srj;
  }else{
    $r .= $s;
    break;
  }
  }
  return $r;
}

function mail_contenttype(&$p, &$types) {
  while ((list($k, $v) = each($p)) && isset($v[0]) && $v[0]) {
//    echo "d[".$k."]".$v."\n";
    if ($v[0] == 'c' || $v[0] == 'C') {
      if (eregi("^CONTENT-TYPE:(.*)", $v, $r)) {
        $rf = ltrim($r[1]);
        while((list($k, $v) = each($p)) && isset($v[0]) && (ereg("[ \011]", $v[0
]))){
//         echo "C[".$k."]".$v."\n";
          $rf .= ("\015\012".$v);
        }
        if (ereg("(^[-a-z/A-Z0-9]+)", $rf, $tp)) {
          $types = $tp[1];
        }
        $rf = substr($rf, strpos($rf, ';', strlen($types)) + 1);
        if (!isset($v[0]) || !$v[0]) {
//          echo "f[".$k."]".$v."\n";
          return $rf;
        }
      }
    }
  }
//  echo "e[".$k."]".$v."\n";
  return $rf;
}

function mail_parse_attr($rf) {
  $ATTR = array();
  if (!$rf) {
    return;
  }
  $i = 0;
  while( $i < strlen($rf)) {
    while (ereg("[ \011\015\012]", $rf[$i])) $i++;
    if ($i >= strlen($rf)) break;
    $pa = "";
    while (ereg("[-a-zA-Z0-9+]", $rf[$i])) {
      $pa .= $rf[$i++];
      if ($i >= strlen($rf)) break 2;
    }
    $pa = strtoupper($pa);
    $ATTR[$pa] = "";
    while (ereg("[ \011\015\012]", $rf[$i])) $i++;
    if ($i >= strlen($rf)) break;
    if ($rf[$i] == '=')     $i++;
    else if ($rf[$i] == ';') { $i++; continue;}
    else {
      break;
    }
    $va = "";
    while (ereg("[ \011\015\012]", $rf[$i])) $i++;
    if ($rf[$i] == chr(042)) {
      $i++;
      while ($rf[$i] != chr(042)) {
        while ($rf[$i] == chr(033) && $rf[$i+1] == '$') {
          $va .= "\033$";
          $i += 2;
          if ($i >= strlen($rf)) break 2;
          while (("" != $rf[$i]) && $rf[$i] != chr(033)) {
            $va .= $rf[$i];
            $i++;
          }
          if ($i >= strlen($rf)) break 2;
          if ($rf[$i] == chr(033) && $rf[$i+1] == chr(050)) {
            $va .= "\033\050";
            $i += 2;
          }
          if ($i >= strlen($rf)) break 2;
        }
        if ($rf[$i] == '\\') {
          $i++;
          $va .= $rf[$i];
          $i++;
        }
        if ($i >= strlen($rf)) break;
        if ($rf[$i] == chr(015)) {
          while (ereg("[ \011\015\012]", $rf[$i])) $i++;
        }
        if ($i >= strlen($rf)) break;
        if ($rf[$i] != chr(042)) {
          $va .= $rf[$i];
          $i++;
        }
        if ($i >= strlen($rf)) break;
      }
      $ATTR[$pa] = $va;
//      echo "[".$va."]\n";
      $i++;
    }
  }
  return $ATTR;
}

function mail_parse_mime(&$p, $boundary, &$at, $lv) {
  $lc = 0;
  while (list($k, $v) = each($p)) {
//    echo "[".$k."]".$v."\n";
    if ("--".$boundary == $v) {
      $lc++;
//      echo "FIND=[".$k."]".$v."\n";
      $rf = mail_contenttype($p, $type);
//      echo "NEWRF=".$rf."\n";
      $boundary2 = "";
      if ($rf[0]) {
        $attrs = mail_parse_attr($rf);
        reset($attrs);
        $at[substr($lv.".".$lc,1)] = $attrs;
        if (isset($attrs['BOUNDARY'])) {
          $boundary2 = $attrs['BOUNDARY'];
        }
      }
//      echo "TYPE2=".$type."\n";
      if ($boundary2) {
//        echo "BOUNDARY2=".$boundary2."\n";
        mail_parse_mime($p, $boundary2, $at, $lv.".".$lc );
      }else{
        if (!strcasecmp("message/rfc822", $type)) {
//          echo "---\n";
          $rf = mail_contenttype($p, $type);
          $boundary3 = "";
          if ($rf[0]) {
            $attrs = mail_parse_attr($rf);
            reset($attrs);
            $at[substr($lv.".".$lc.".1",1)] = $attrs;
            if (isset($attrs['BOUNDARY'])) {
              $boundary3 = $attrs['BOUNDARY'];
            }
          }
          if ($boundary3) {
//            echo "RFC822BD=".$boundary3."\n";
            mail_parse_mime($p, $boundary3, $at, $lv.".".$lc);
          }
//        }else{
//          $at[substr($lv.".".$lc."1",1)] = array();
        }
      }

    }
    if ("--".$boundary."--" == $v) {
//      echo "EXIT=[".$k."]\n";
      return;
    }
  }
}

function mail_fullstructurefetch($mbox, $num, $flags = FT_UID) {
  $attr = array();
  $p = explode("\015\012", imap_fetchbody($mbox, $num, 0, $flags));
  $rf = mail_contenttype($p, $type);
  $attrs = mail_parse_attr($rf);
  $boundary = $attrs['BOUNDARY'];
  $p = explode("\015\012", imap_body($mbox, $num, $flags));
  mail_parse_mime($p, $boundary, $attr, "");
  $attr[0] = "";
  return $attr;
}

Posted by minemaz at 2003年08月28日 23:57
トラックバック
このエントリーのトラックバックURL:
http://www.lancard.com/mt/mt-tb.cgi/11

Comments
Post a comment









Remember personal info?