mail: decode multipart attachments (text, html, images)
[minimedit.git] / mail / index.php
index d8195f689f3eaa5f9eb1fa4f628581582512e363..9f570640e8b5862ee3908bf6af6140db7d515604 100644 (file)
@@ -2,6 +2,7 @@
 $mailbox = 'mail/inbox';
 @list ($msgid) = explode('/', ltrim($Page->path, '/'));
 
+if (!function_exists('parsemailhead')) {
 function parsemailhead($headerdata)
 {
        $headlist = iconv_mime_decode_headers($headerdata, ICONV_MIME_DECODE_CONTINUE_ON_ERROR);
@@ -12,9 +13,14 @@ function parsemailhead($headerdata)
        });
        return $headlist;
 }
+}
 
 if ($msgid) {
        $filename = "$mailbox/$msgid";
+       if (!is_readable($filename)) {
+               return TRUE;
+       }
+
        list ($headerdata, $rawbody) = explode("\n\n", file_get_contents($filename), 2);
        $head = parsemailhead($headerdata);
        $head['date']->setTimezone(new DateTimeZone(date_default_timezone_get()));
@@ -30,25 +36,72 @@ if ($msgid) {
        );
        print '</dl>';
 
-       if (preg_match('{^text/plain}', $head['Content-Type'] ?? 'text/plain')) {
+       $type = preg_replace('/;.*/', '', $head['Content-Type'] ?? 'text/plain', 1);
+       switch ($type) {
+       case 'text/plain':
                $body = $rawbody;
                if (($head['Content-Transfer-Encoding'] ?? '') === 'quoted-printable') {
                        $body = quoted_printable_decode($body);
                }
-               printf('<pre>%s</pre>', htmlspecialchars($body));
-       }
-       else {
-               printf('<p>Geen ondersteuning voor <em>%s</em>.</p>', htmlspecialchars($head['Content-Type']));
-
-               /* TODO
+               $body = nl2br(htmlspecialchars($body));
+               print "<p>$body</p>\n";
+               break;
+       case 'multipart/alternative':
                $mime = mailparse_msg_parse_file($filename);
-               $part = mailparse_msg_get_part($mime, '1');
-               mailparse_msg_extract_part_file($part, $filename);
-               */
+               foreach (mailparse_msg_get_structure($mime) as $section) {
+                       print "<h3>$section</h3>\n";
+                       $part = mailparse_msg_get_part($mime, $section);
+                       if ($section === '1') {
+                               continue; // do not access container to prevent segfault
+                       }
+                       $pinfo = mailparse_msg_get_part_data($part);
+               #printf('<pre>%s</pre>', htmlspecialchars(print_r($pinfo,TRUE)));
+                       $phead = $pinfo['headers'];
+                       list ($ptype) = explode(';', strtolower($phead['content-type']));
+                       list ($pmedia) = explode('/', $ptype);
+                       switch ($pmedia) {
+                       case 'multipart':
+                               continue 2;
+                       case 'text':
+                               $body = mailparse_msg_extract_part_file($part, $filename, NULL);
+                               #iconv($pinfo['charset'], 'UTF-8', $body); #TODO test if needed
+                               switch ($ptype) {
+                               case 'text/plain':
+                                       $body = htmlspecialchars($body);
+                                       print "<pre><p>$body</p></pre>\n";
+                                       break;
+                               case 'text/html':
+                                       $body = preg_replace('{
+                                               (<br */?>) | <[^>]+> # keep line breaks, replace other elements
+                                       }x', "\\1\n", $body); # strip_tags
+                                       print "<p>$body</p>\n";
+                                       break;
+                               }
+                               break;
+                       case 'image':
+                               if (!preg_match('/^inline;/', $phead['content-disposition'])) {
+                                       continue 2;
+                               }
+                               $name = iconv_mime_decode($phead['disposition-filename']);
+                               $body = mailparse_msg_extract_part_file($part, $filename, NULL);
+                               printf('<img src="data:%s;base64,%s" alt="%s" />',
+                                       $ptype, base64_encode($body),
+                                       htmlspecialchars($phead['name'] ?? '-')
+                               );
+                               break;
+                       }
+               }
+               mailparse_msg_free($mime);
+               break;
+       default:
+               printf('<p>Geen ondersteuning voor <em>%s</em>.</p>', htmlspecialchars($type));
        }
        return;
 }
 
+if ($Page->api) {
+       return;
+}
 if (!$User->admin('user')) {
        http_response_code(403);
        $Page->place['warn'] = "Geen gebruikersrechten om e-mails in te zien.";
@@ -93,8 +146,6 @@ foreach (array_reverse($rows) as $filename) {
 }
 print "</ul>\n";
 
-print $Page->widget('nav', [
-       "start=$nav[start]", "n=$nav[n]", "total=$nav[total]",
-]);
+print $Page->widget('nav', $nav);
 
 $Page->place['maillist'] = ob_get_clean();