vadviktor
8/30/2012 - 2:31 PM

Gmail IMAP attacment downloader

Gmail IMAP attacment downloader

<?php
final class Gmail{
//********************************************************
  private $imap_username = '';
  private $imap_password = '';
  private $save_dir = '.';
//********************************************************
  private $imap_base_address = '{imap.gmail.com:993/imap/ssl}';

  public function go() {
    return new Gmail ( );
  }

  public function __construct() {
    $this->log ( '--- START ---' );
    $this->doJob();
  }

  public function __destruct(){
    $this->log ( '--- END ---' );
  }

  private function log($s) {
    print $s . "\n";
  }

  private function decodeMimeStr($string, $charset = "UTF-8") {
    $newString = '';
    $elements = imap_mime_header_decode ( $string );
    for($i = 0; $i < count ( $elements ); $i ++) {
      if ($elements [$i]->charset == 'default')
      $elements [$i]->charset = 'iso-8859-1';
      $newString .= iconv ( $elements [$i]->charset, $charset, $elements [$i]->text );
    }
    return $newString;
  }

  private function _save_attachment($tmpname, $fname, $encoding) {
    $_pre = date ( "YmdHis", time () ) . "_";
    $name = $_pre . $fname;
    $fullname = "{$this->save_dir}/{$name}";

    $new_file = fopen ( $fullname, 'wb' );
    switch ( $encoding )
    {
      case 1 :
        fwrite( $new_file, quoted_printable_decode(imap_8bit(file_get_contents($tmpname, FILE_TEXT))));
        break;
      case 3 :
        fwrite( $new_file, base64_decode( file_get_contents( $tmpname, FILE_TEXT ) ) );
        break;
      case 0 :
      case 4 :
        fwrite( $new_file, quoted_printable_decode( file_get_contents( $tmpname, FILE_TEXT ) ) );
        break;
    }
    fclose ( $new_file );
    unlink ( $tmpname );
    $this->log ( "ATTACHMENT NAME: {$fname}" );
  }

  // Sub function for create_part_array(). Only called by create_part_array() and itself.
  private function add_part_to_array($obj, $partno, & $part_array) {
    $part_array [] = array (

    'part_number' => $partno, 'part_object' => $obj );
    if ($obj->type == 2) { // Check to see if the part is an attached email message, as in the RFC-822 type
      //print_r($obj);
      if (sizeof ( $obj->parts ) > 0) { // Check to see if the email has parts
        foreach ( $obj->parts as $count => $part ) {
          // Iterate here again to compensate for the broken way that imap_fetchbody() handles attachments
          if (sizeof ( $part->parts ) > 0) {
            foreach ( $part->parts as $count2 => $part2 ) {
              $this->add_part_to_array ( $part2, $partno . "." . ($count2 + 1), $part_array );
            }
          } else { // Attached email does not have a seperate mime attachment for text
            $part_array [] = array (

            'part_number' => $partno . '.' . ($count + 1), 'part_object' => $obj );
          }
        }
      } else { // Not sure if this is possible
        $part_array [] = array ('part_number' => $prefix . '.1', 'part_object' => $obj );
      }
    } else { // If there are more sub-parts, expand them out.
      if (sizeof ( $obj->parts ) > 0) {
        foreach ( $obj->parts as $count => $p ) {
          $this->add_part_to_array ( $p, $partno . "." . ($count + 1), $part_array );
        }
      }
    }
  }

  private function create_part_array($structure, $prefix = "") {
    //print_r($structure);
    if (sizeof ( $structure->parts ) > 0) { // There some sub parts
      foreach ( $structure->parts as $count => $part ) {
        $this->add_part_to_array ( $part, $prefix . ($count + 1), $part_array );
      }
    } else { // Email does not have a seperate mime attachment for text
      $part_array [] = array (

      'part_number' => $prefix . '1', 'part_object' => $obj );
    }
    return $part_array;
  }

  private function doJob() {
    if ($mbox = imap_open ( $this->imap_base_address . 'All Mail', $this->imap_username, $this->imap_password ))
    {

      $this->log ( 'MBOX SORTING' );

      $sorted_mbox = imap_sort ( $mbox, "SORTARRIVAL", 1 );

      foreach ( $sorted_mbox as $msgno ) {
        $this->log ( 'READ NEW MAIL' );

        //get info by searching the emails
        $header = imap_headerinfo ( $mbox, $msgno );
        $from = $header->from;
        $email = $from [0]->mailbox . '@' . $from [0]->host;
        $subject = htmlspecialchars ( $this->decodeMimeStr ( $header->Subject ), ENT_QUOTES );

        $this->log ( "E-MAIL: {$email}; SUBJECT: {$subject}" );

        //attach message parts
        $struct = imap_fetchstructure ( $mbox, $msgno );
        $parts = $this->create_part_array ( $struct );

        if(count($parts) > 0)
        {
          $this->log ( "EXTRACTING ATTACHMENTS" );
          foreach ( $parts as $part ) {
            if($part['part_object']->subtype != 'ALTERNATIVE'
            && $part['part_object']->subtype != 'RELATED'
            && $part['part_object']->subtype != 'PLAIN'
            && $part['part_object']->subtype != 'HTML'
            ) {
              if (gettype ( $part ['part_object']->parameters ) == 'array')
              ){
                $fname = $this->decodeMimeStr ( $part ['part_object']->parameters [0]->value );

                //save and attach file to iktatokönyv
                $_pre = date ( "YmdHis", time () ) . "_";
                $tmpname = "/tmp/{$_pre}{$fname}";
                if (imap_savebody ( $mbox, $tmpname, $msgno, $part ['part_number'], FT_PEEK )) {
                  $this->_save_attachment ( $tmpname, $fname, $part['part_object']->encoding);
                }
              }
            }
          }
        }
      }
      $this->log ( "CLOSE MBOX" );
      imap_close ( $mbox );
    }
  }
}

Gmail::go ();
?>