Advertisement
Guest User

Mail.ru mailbox downloader

a guest
Aug 23rd, 2015
8,226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 6.19 KB | None | 0 0
  1. <?php
  2. if ($_SERVER['argc'] < 3)
  3. {
  4.     error_log(sprintf("syntax: %s <username> <password>\n", $_SERVER['argv'][0]));
  5.     exit(1);
  6. }
  7.  
  8. define('PAGE_TIMEOUT', 30);
  9. define('DOWNLOAD_TIMEOUT', 1800);
  10.  
  11. $mru = new MailRuBoxGrabber();
  12. if (!$mru->login($_SERVER['argv'][1], $_SERVER['argv'][2], ''))
  13. {
  14.     error_log('login failed');
  15.     exit(1);
  16. }
  17. $mru->grab_all();
  18.  
  19. class MailRuBoxGrabber
  20. {
  21.     const BASE_URL = 'https://e.mail.ru/';
  22.     const API_MESSAGES_LIMIT = 50;
  23.     private $curl, $username;
  24.  
  25.     function __construct()
  26.     {
  27.         if (($this->curl = curl_init()) === FALSE)
  28.             die('curl_init() failed');
  29.         curl_setopt($this->curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  30.         curl_setopt($this->curl, CURLOPT_PROXY, '127.0.0.1:9050');
  31.         curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT, 10);
  32.         curl_setopt($this->curl, CURLOPT_TIMEOUT, PAGE_TIMEOUT);
  33.         curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, TRUE);
  34.         curl_setopt($this->curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0');
  35.         curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, TRUE);
  36.         curl_setopt($this->curl, CURLOPT_MAXREDIRS, 3);
  37.         curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
  38.         $cookie_file = pathinfo($_SERVER['argv'][0])['filename'] . '.cookies';
  39.         curl_setopt($this->curl, CURLOPT_COOKIEFILE, $cookie_file);
  40.         curl_setopt($this->curl, CURLOPT_COOKIEJAR, $cookie_file);
  41.     //  curl_setopt($this->curl, CURLOPT_COOKIESESSION, TRUE);
  42.     //  curl_setopt($this->curl, CURLOPT_VERBOSE, TRUE);
  43.     }
  44.  
  45.     function __destruct()
  46.     {
  47.         curl_close($this->curl);
  48.     }
  49.  
  50.     private function http_request($url)
  51.     {
  52.         curl_setopt($this->curl, CURLOPT_URL, $url);
  53.         $result = curl_exec($this->curl);
  54.         if ($result === FALSE)
  55.         {
  56.             error_log('request error: ' . curl_error($this->curl));
  57.             return NULL;
  58.         }
  59.         else
  60.             return $result;
  61.     }
  62.  
  63.     public function login($username, $password, $redirect)
  64.     {
  65.         curl_setopt($this->curl, CURLOPT_POST, TRUE);
  66.         curl_setopt($this->curl, CURLOPT_POSTFIELDS, sprintf('page=%s&Domain=mail.ru&Login=%s&Password=%s&new_auth_form=1', urlencode($redirect), urlencode($username), urlencode($password)));
  67.         if (($response = $this->http_request('https://auth.mail.ru/cgi-bin/auth?lang=ru_RU')) === NULL)
  68.             return FALSE;
  69.         if (curl_getinfo($this->curl, CURLINFO_HTTP_CODE) != '200')
  70.             return FALSE;
  71.         if (!preg_match('|<meta http-equiv="refresh" content="0;url=(\S+?)">|', $response, $sp))
  72.         {
  73.             error_log('unable to match <meta http-equiv="refresh" ...>');
  74.             return FALSE;
  75.         }
  76.         if ($redirect != '' && html_entity_decode($sp[1]) != $redirect && strpos($sp[1], 'https://e.mail.ru/settings/security?changepass') === FALSE)
  77.         {
  78.             error_log('unexpected redirect URL: ' . $sp[1]);
  79.             return FALSE;
  80.         }
  81.         $this->username = $username;
  82.         return TRUE;
  83.     }
  84.  
  85.     public function grab_all()
  86.     {
  87.         curl_setopt($this->curl, CURLOPT_HTTPGET, TRUE);
  88.         curl_setopt($this->curl, CURLOPT_TIMEOUT, PAGE_TIMEOUT);
  89.         curl_setopt($this->curl, CURLOPT_FILE, STDOUT);
  90.         curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
  91.         if (($response = $this->http_request(sprintf(self::BASE_URL . 'messages/inbox/?back=1'))) === NULL)
  92.             return FALSE;
  93.  
  94.         if (!preg_match('|patron\.updateToken\("(\S+?)"\);|', $response, $sp))
  95.         {
  96.             error_log('unable to get API token');
  97.             return FALSE;
  98.         }
  99.         $token = $sp[1];
  100.  
  101.         $folders = array(0 => array());
  102.         while (list($folder_id, $folder_data) = each($folders))
  103.         {
  104.             $folder_message = 0;
  105.             for ($offset = 0; ; $offset += self::API_MESSAGES_LIMIT)
  106.             {
  107.                 curl_setopt($this->curl, CURLOPT_HTTPGET, TRUE);
  108.                 curl_setopt($this->curl, CURLOPT_TIMEOUT, PAGE_TIMEOUT);
  109.                 curl_setopt($this->curl, CURLOPT_FILE, STDOUT);
  110.                 curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
  111.                 if (($response = $this->http_request(self::BASE_URL . sprintf('api/v1/messages/status?ajax_call=1&email=%s&nolog=0&cts=1&force=1&folder=%s&offset=%u&limit=%u&api=1&token=%s', urlencode($this->username), $folder_id, $offset, self::API_MESSAGES_LIMIT, urlencode($token)))) === NULL)
  112.                     return FALSE;
  113.                 if (($api_response = json_decode($response, TRUE)) === NULL)
  114.                 {
  115.                     error_log("API request - unable to decode JSON data:\n" . $response);
  116.                     return FALSE;
  117.                 }
  118.                 if (count($folders) <= 1) // if not filled yet
  119.                 {
  120.                     echo "parsing folders list\n";
  121.                     foreach ($api_response['body']['folders'] as $item)
  122.                     {
  123.                         $dir = sprintf("#%s - %s", $item['id'], self::sanitize_filename($item['name']));
  124.                         if (!is_dir($dir) && !mkdir($dir))
  125.                         {
  126.                             error_log("can't create a directory: " . $dir);
  127.                             return FALSE;
  128.                         }
  129.                         $folders[$item['id']] = array(
  130.                             'name' => $item['name'],
  131.                             'messages' => $item['messages_total'],
  132.                             'dir' => $dir
  133.                         );
  134.                     }
  135.                     print_r($folders);
  136.                 }
  137.                 if (empty($api_response['body']['messages']))
  138.                     break 1;
  139.                 foreach ($api_response['body']['messages'] as $message)
  140.                 {
  141.                     ++$folder_message;
  142.                     printf("[%u/%u] %s - %s - %s\n", $folder_message, $folders[$message['folder']]['messages'],
  143.                         $message['id'], date('Y-m-d H:i:s', $message['date']), $message['subject']);
  144.                     if (!$this->retrieve_message($message['id'], $folders[$message['folder']]['dir']))
  145.                         return FALSE;
  146.                 }
  147.             }
  148.         }
  149.     }
  150.  
  151.     public function retrieve_message($id, $dir)
  152.     {
  153.         if (!is_dir($dir) && !mkdir($dir))
  154.         {
  155.             error_log("can't create a directory");
  156.             return FALSE;
  157.         }
  158.         $filename = sprintf("%s/%s.eml", $dir, $id);
  159.         if (($fOutput = fopen($filename, 'w')) === FALSE)
  160.         {
  161.             echo "unable to create a file: $filename\n";
  162.             return FALSE;
  163.         }
  164.         curl_setopt($this->curl, CURLOPT_URL, self::BASE_URL . 'cgi-bin/getmsg?id=' . $id);
  165.         curl_setopt($this->curl, CURLOPT_TIMEOUT, DOWNLOAD_TIMEOUT);
  166.         curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, 0);
  167.         curl_setopt($this->curl, CURLOPT_FILE, $fOutput);
  168.         $result = curl_exec($this->curl);
  169.         fclose($fOutput);
  170.         $http_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
  171.         if ($result === FALSE || $http_code != 200)
  172.         {
  173.             printf("unable to fetch message #%s (HTTP status code = %u)\n", $id, $http_code);
  174.             return FALSE;
  175.         }
  176.         return TRUE;
  177.     }
  178.  
  179.     protected static function sanitize_filename($filename)
  180.     {
  181.         return preg_replace("|[/\\\?\*\|:\"<>]|", '_', $filename);
  182.     }
  183. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement