RSS Feed

実験的に開発した小さなプログラムやWebサービスを公開。また、気になった最新IT技術情報をブログ形式でメモ。

簡易Webメーラー

Zend Frameworkに付属するデモ:
簡易Webメーラーのサンプル

E-Mailの送信や受信したE-Mailの閲覧が可能な簡易Webメーラーの機能を実現するサンプルです。

動作サンプル : なし

ソース: /demos/Zend/Mail/SimpleMailer.php

  1. < ?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to version 1.0 of the Zend Framework
  8. * license, that is bundled with this package in the file LICENSE, and
  9. * is available through the world-wide-web at the following URL:
  10. * http://www.zend.com/license/framework/1_0.txt. If you did not receive
  11. * a copy of the Zend Framework license and are unable to obtain it
  12. * through the world-wide-web, please send a note to license@zend.com
  13. * so we can mail you a copy immediately.
  14. *
  15. * @package    Zend_Mail
  16. * @copyright Copyright (c) 2005-2006 Zend Technologies USA Inc. (http://www.zend.com)
  17. * @license    http://www.zend.com/license/framework/1_0.txt Zend Framework License version 1.0
  18. */
  19.  
  20.  
  21. /**
  22. * Zend_Loader
  23. */
  24. require_once 'Zend/Loader.php';
  25.  
  26. /**
  27. * A simple web-mailer based on Zend_Mail_Storage classes.
  28. *
  29. * This simple mailer demonstrates the most important features of the mail reading classes. You can
  30. * use the test mbox and maildir files or a Pop3 or Imap server. It's meant to be run in a web enviroment
  31. * and CLI is not supported. Copy the files to a directory in your webroot and make sure the Zend Framework
  32. * is in your include path (including incubator!).
  33. *
  34. * SSL and TLS are supported by Zend_Mail_Storage_[Pop3|Imap], but not shown here). You'd need to add
  35. *   'ssl' => 'SSL'
  36. * or
  37. *   'ssl' => 'TLS'
  38. * if you want to use ssl support.
  39. *
  40. * Because of problems with Windows filenames (maildir needs : in filenames) the maildir folder is in a tar.
  41. * Untar maildir.tar in maildir/ to test maildir support (won't work on Windows).
  42. *
  43. * The structure of the class is very simple. Every method named show...() output HTML, run() inits mail storage
  44. * after login and calls a show method, everything else inits and checks variables and mail storage handler.
  45. *
  46. * @package    Zend_Mail
  47. * @copyright Copyright (c) 2005-2006 Zend Technologies USA Inc. (http://www.zend.com)
  48. * @license    http://www.zend.com/license/framework/1_0.txt Zend Framework License version 1.0
  49. */
  50. class Demo_Zend_Mail_SimpleMailer
  51. {
  52.     /**
  53.      * mail storage type (mbox, mbox-folder, maildir, maildir-folder, pop3, imap)
  54.      */
  55.     private $type;
  56.  
  57.     /**
  58.      * filename, dirname or hostname for current mailstorage
  59.      */
  60.     private $param;
  61.  
  62.     /**
  63.      * selected mail message or null if none
  64.      */
  65.     private $messageNum;
  66.  
  67.     /**
  68.      * mail storage handler
  69.      */
  70.     private $mail;
  71.  
  72.     /**
  73.      * query string with current selection for output
  74.      */
  75.     private $queryString;
  76.  
  77.    /**
  78.      * don't run run(), needed for auth
  79.      */
  80.     private $noRun = false;
  81.  
  82.     /**
  83.      * init class for run() and output
  84.      */
  85.     function __construct()
  86.     {
  87.         $this->initVars();
  88.         $this->loadClasses();
  89.         $this->whitelistParam();
  90.  
  91.         // we use http auth for username and password or mail storage
  92.         if (($this->type == 'pop3' || $this->type == 'imap') && !isset($_SERVER['PHP_AUTH_USER'])) {
  93.             $this->needAuth();
  94.             return;
  95.         }
  96.  
  97.         switch ($this->type) {
  98.             case 'mbox':
  99.                 $this->mail = new Zend_Mail_Storage_Mbox(array('filename' => $this->param));
  100.                 break;
  101.             case 'mbox-folder':
  102.                 $this->mail = new Zend_Mail_Storage_Folder_Mbox(array('dirname' => $this->param));
  103.                 break;
  104.             case 'maildir':
  105.                 $this->mail = new Zend_Mail_Storage_Maildir(array('dirname' => $this->param));
  106.                 break;
  107.             case 'maildir-folder':
  108.                 $this->mail = new Zend_Mail_Storage_Folder_Maildir(array('dirname' => $this->param));
  109.                 break;
  110.             case 'pop3':
  111.                 $this->mail = new Zend_Mail_Storage_Pop3(array('host'     => $this->param,
  112.                                                                'user'     => $_SERVER['PHP_AUTH_USER'],
  113.                                                                'password' => $_SERVER['PHP_AUTH_PW']));
  114.                 break;
  115.             case 'imap':
  116.                 $this->mail = new Zend_Mail_Storage_Imap(array('host'     => $this->param,
  117.                                                                'user'     => $_SERVER['PHP_AUTH_USER'],
  118.                                                                'password' => $_SERVER['PHP_AUTH_PW']));
  119.                 break;
  120.             default:
  121.                 $this->mail = null;
  122.                 break;
  123.         }
  124.     }
  125.  
  126.     /**
  127.      * check parameter and type
  128.      */
  129.     function whitelistParam()
  130.     {
  131.         $whitelist = array('mbox'           => array('mbox/INBOX', 'mbox/subfolder/test'),
  132.                            'mbox-folder'    => array('mbox'),
  133.                            'maildir'        => array('maildir', 'maildir/.subfolder', 'maildir/.subfolder.test'),
  134.                            'maildir-folder' => array('maildir', 'maildir/.subfolder', 'maildir/.subfolder.test'),
  135.                            'pop3'           => array(),
  136.                            'imap'           => array());
  137.  
  138.         if ($this->type === null || @$whitelist[$this->type] === array() || @in_array($this->param, $whitelist[$this->type])) {
  139.             return;
  140.         }
  141.  
  142.         throw new Exception('Unknown type or param not in whitelist');
  143.     }
  144.  
  145.     /**
  146.      * load needed classes
  147.      */
  148.     function loadClasses()
  149.     {
  150.         $classname = array('mbox'           => 'Zend_Mail_Storage_Mbox',
  151.                            'mbox-folder'    => 'Zend_Mail_Storage_Folder_Mbox',
  152.                            'maildir'        => 'Zend_Mail_Storage_Maildir',
  153.                            'maildir-folder' => 'Zend_Mail_Storage_Folder_Maildir',
  154.                            'pop3'           => 'Zend_Mail_Storage_Pop3',
  155.                            'imap'           => 'Zend_Mail_Storage_Imap');
  156.  
  157.         if (isset($classname[$this->type])) {
  158.             Zend_Loader::loadClass($classname[$this->type]);
  159.         }
  160.  
  161.         Zend_Loader::loadClass('Zend_Mail_Storage');
  162.     }
  163.  
  164.     /**
  165.      * init variables
  166.      */
  167.     function initVars()
  168.     {
  169.         $this->type        = isset($_GET['type'])   ? $_GET['type']   : null;
  170.         $this->param       = isset($_GET['param'])  ? $_GET['param']  : null;
  171.         $this->folder      = isset($_GET['folder']) ? $_GET['folder'] : null;
  172.         $this->messageNum  = isset($_GET['message']) && is_numeric($_GET['message']) ? $_GET['message'] : null;
  173.         $this->queryString = http_build_query(array('type'   => $this->type,
  174.                                                     'param'  => $this->param,
  175.                                                     'folder' => $this->folder));
  176.     }
  177.  
  178.     /**
  179.      * send http auth headers, for username and password in pop3 and imap
  180.      */
  181.     function needAuth()
  182.     {
  183.         header("WWW-Authenticate: Basic realm='{$this->type} credentials'");
  184.         header('HTTP/1.0 401 Please enter credentials');
  185.         $this->noRun = true;
  186.     }
  187.  
  188.     /**
  189.      * get data from mail storage and output html
  190.      */
  191.     function run()
  192.     {
  193.         if ($this->noRun) {
  194.             return;
  195.         }
  196.  
  197.         if ($this->mail instanceof Zend_Mail_Storage_Folder_Interface && $this->folder) {
  198.             // could also be done in constructor of $this->mail with parameter 'folder' => '...'
  199.             $this->mail->selectFolder($this->folder);
  200.         }
  201.  
  202.         $message = null;
  203.         try {
  204.             if ($this->messageNum) {
  205.                 $message = $this->mail->getMessage($this->messageNum);
  206.             }
  207.         } catch(Zend_Mail_Exception $e) {
  208.             // ignored, $message is still null and we display the list
  209.         }
  210.  
  211.         if (!$this->mail) {
  212.             $this->showChooseType();
  213.         } else if ($message) {
  214.             $this->showMessage($message);
  215.         } else {
  216.             $this->showList();
  217.         }
  218.     }
  219.  
  220.     /**
  221.      * output html header
  222.      *
  223.      * @param string $title page title
  224.      */
  225.     function showHeader($title)
  226.     {
  227.         echo "<html><head>
  228.               <title>{$title}</title>
  229.               <style>
  230.               table {border: 1px solid black; border-collapse: collapse}
  231.               td, th {border: 1px solid black; padding: 3px; text-align: left}
  232.               th {text-align: right; background: #eee}
  233.               tr.unread td {font-weight: bold}
  234.               tr.flagged td {font-style: italic}
  235.               tr.new td {color: #800}
  236.               .message {white-space: pre; font-family: monospace; padding: 0.5em}
  237.               dl dt {font-style: italic; padding: 1em 0; border-top: 1px #888 dashed}
  238.               dl dd {padding-bottom: 1em}
  239.               dl dt:first-child {border: none; padding-top: 0}
  240.               </style>
  241.               </head><body><h1>{$title}</h1>";
  242.     }
  243.  
  244.     /**
  245.      * output html footer
  246.      */
  247.     function showFooter()
  248.     {
  249.         echo '</body></html>';
  250.     }
  251.  
  252.     /**
  253.      * output type selection AKA "login-form"
  254.      */
  255.     function showChooseType()
  256.     {
  257.         $this->showHeader('Choose Type');
  258.  
  259.         echo '<form><label>Mbox file</label><input name="param" value="mbox/INBOX"/>
  260.               <input type="hidden" name="type" value="mbox"/><input type="submit"/></form>
  261.  
  262.               <form><label>Mbox folder</label><input name="param" value="mbox"/>
  263.               <input type="hidden" name="type" value="mbox-folder"/><input type="submit"/></form>
  264.  
  265.               <form><label>Maildir file</label><input name="param" value="maildir"/>
  266.               <input type="hidden" name="type" value="maildir"/><input type="submit"/></form>
  267.  
  268.               <form><label>Maildir folder</label><input name="param" value="maildir"/>
  269.               <input type="hidden" name="type" value="maildir-folder"/><input type="submit"/></form>
  270.  
  271.               <form><label>Pop3 Host</label><input name="param" value="localhost"/>
  272.               <input type="hidden" name="type" value="pop3"/><input type="submit"/></form>
  273.  
  274.               <form><label>IMAP Host</label><input name="param" value="localhost"/>
  275.               <input type="hidden" name="type" value="imap"/><input type="submit"/></form>';
  276.  
  277.         $this->showFooter();
  278.     }
  279.  
  280.     /**
  281.      * output mail message
  282.      */
  283.     function showMessage($message)
  284.     {
  285.         try {
  286.             $from = $message->from;
  287.         } catch(Zend_Mail_Exception $e) {
  288.             $from = '(unknown)';
  289.         }
  290.  
  291.         try {
  292.             $to = $message->to;
  293.         } catch(Zend_Mail_Exception $e) {
  294.             $to = '(unknown)';
  295.         }
  296.  
  297.         try {
  298.             $subject = $message->subject;
  299.         } catch(Zend_Mail_Exception $e) {
  300.             $subject = '(unknown)';
  301.         }
  302.  
  303.         $this->showHeader($subject);
  304.  
  305.         echo "<table>
  306.               <tr><th>From:<td>$from</td></th></tr>
  307.               <tr><th>Subject:<td>$subject</td></th></tr>
  308.               <tr><th>To:<td>$to</td></th></tr><tr><td colspan='2' class='message'>";
  309.  
  310.         if ($message->isMultipart()) {
  311.             echo '<dl>';
  312.             foreach (new RecursiveIteratorIterator($message) as $part) {
  313.                 echo "<dt>Part with type {$part->contentType}:</dt><dd>";
  314.                 echo htmlentities($part);
  315.                 echo '</dd>';
  316.             }
  317.             echo '</dl>';
  318.         } else {
  319.             echo htmlentities($message->getContent());
  320.         }
  321.  
  322.         echo "</td></tr></table><a href='?{$this->queryString}'>back to list</a>";
  323.  
  324.         if ($this->messageNum > 1) {
  325.             echo " - <a href="?{$this->queryString}&message=", $this->messageNum - 1, '">prev</a>';
  326.         }
  327.  
  328.         if ($this->messageNum < $this->mail->countMessages()) {
  329.             echo " - <a href="?{$this->queryString}&message=", $this->messageNum + 1, '">next</a>';
  330.         }
  331.  
  332.         $this->showFooter();
  333.     }
  334.  
  335.     /**
  336.      * output message list
  337.      */
  338.     function showList()
  339.     {
  340.         $this->showHeader('Overview');
  341.  
  342.         echo '<table><tr><td></td><th>From</th><th>To</th><th>Subject</th></tr>';
  343.  
  344.         foreach ($this->mail as $num => $message) {
  345.             if ($this->mail->hasFlags) {
  346.                 $class = array();
  347.  
  348.                 if ($message->hasFlag(Zend_Mail_Storage::FLAG_RECENT)) {
  349.                     $class['unread'] = 'unread';
  350.                     $class['new']    = 'new';
  351.                 }
  352.                 if (!$message->hasFlag(Zend_Mail_Storage::FLAG_SEEN)) {
  353.                     $class['unread'] = 'unread';
  354.                 }
  355.                 if ($message->hasFlag(Zend_Mail_Storage::FLAG_FLAGGED)) {
  356.                     $class['flagged'] = 'flagged';
  357.                 }
  358.  
  359.                 $class = implode(' ', $class);
  360.                 echo "<tr class='$class'>";
  361.             } else {
  362.                 echo '</tr><tr>';
  363.             }
  364.  
  365.             echo "<td><a href='?{$this->queryString}&message=$num'>read</a></td>";
  366.  
  367.             try {
  368.                 echo "<td>{$message->from}</td><td>{$message->to}</td><td>{$message->subject}</td>";
  369.             } catch(Zend_Mail_Exception $e){
  370.                 echo '<td><em>error</em></td>';
  371.             }
  372.  
  373.             echo '</tr>';
  374.         }
  375.  
  376.         echo '</table>';
  377.  
  378.         if ($this->mail instanceof Zend_Mail_Storage_Folder_Interface) {
  379.             $this->showFolders();
  380.         }
  381.  
  382.         $this->showFooter();
  383.     }
  384.  
  385.     /**
  386.      * output folder list
  387.      */
  388.     function showFolders()
  389.     {
  390.         echo "<br /><form method='get' action='?{$this->queryString}'><label>Change folder:</label>
  391.               <select name='folder'>";
  392.  
  393.         $folders = new RecursiveIteratorIterator($this->mail->getFolders(), RecursiveIteratorIterator::SELF_FIRST);
  394.  
  395.         foreach ($folders as $localName => $folder) {
  396.             echo '<option ';
  397.             if (!$folder->isSelectable()) {
  398.                 echo 'disabled="disabled" ';
  399.             }
  400.             $localName = str_pad('', $folders->getDepth() * 12, '&nbsp;', STR_PAD_LEFT) . $localName;
  401.             echo "value='$folder'>$localName</option>";
  402.         }
  403.  
  404.         echo "</select><input type='submit' value='change'/><input type='hidden' name='param' value='{$this-/>param}'>
  405.               <input type='hidden' name='type' value='{$this-/>type}'></form>";
  406.     }
  407. }
  408.  
  409. // init and run mailer
  410. $SimpleMailer = new Demo_Zend_Mail_SimpleMailer();
  411. $SimpleMailer->run();
  412. ?>
関連記事