Scenario: We have a text block (such as text/calendar data) which needs to be added as a MIME part to an email message. We then need to add a couple of additional headers to this message and finally read it back as a string.
For Message Body:
require_once 'Horde/MIME/Message.php'; $message = new MIME_Message(); $part = new MIME_Part('text/plain', $message_text); $message->addPart($part);
For text/calendar attachment:
$part = new MIME_Part('text/calendar', $text_calendar_data); $message->addPart($part);
For Headers:
require_once 'Horde/MIME/Headers.php'; $headers = new MIME_Headers(); $headers->addHeader('Header 1', $Header_1_Value); $headers->addHeader('Header 2', $Header_2_Value); $headers->addMIMEHeaders($message);
To return the message as a string:
$string = $headers->toString() . "\n\n" . $message->toString();
require_once 'Horde/MIME/Mail.php'; // New Horde MIME_Mail Object $mail = new MIME_Mail(); // Set the header date $mail->addHeader('Date', date('r')); // Set the from address $mail->addHeader('From', 'sender@example.com'); // Set the subject of the mail $mail->addHeader('Subject', 'Horde MIME_Mail example'); // Set the text message body $mail->setBody('Example MIME message with an attachment'); // Add the file as an attachment, set the file name and what kind of file it is. $mail->addAttachment('/tmp/some_file.zip', 'some_file.zip', 'application/x-zip-compressed'); // Add recipients $mail->addRecipients('recipient@example.com'); // Get the mail driver $mail_driver = $conf['mailer']['type']; $mail_params = $conf['mailer']['params']; if ($mail_driver == 'smtp' && $mail_params['auth'] && empty($mail_params['username'])) { if (Auth::getAuth()) { $mail_params['username'] = Auth::getAuth(); $mail_params['password'] = Auth::getCredential('password'); } } // Send the mail if (!is_a($sent = $mail->send($mail_driver, $mail_params), 'PEAR_Error')) { print "E-Mail sent\n"; } else { print "E-Mail not sent\n"; }
Scenario: We have an existing text string which contains a valid MIME email message. We need to parse this string in order to read back the body of a specific MIME part with a certain content type.
require_once 'Horde/MIME/Structure.php'; $message = MIME_Structure::parseTextMIMEMessage($message_text);
To determine the structure of the MIME message, e.g. to find out the MIME ID we are looking for:
$map = $message->contentTypeMap();
$map is an array with key being the MIME IDs and values being the Content Types of that IDs.
To retrieve a certain MIME part of the message:
$part = $message->getPart($mime_id);
The following code snippets require at least Horde 3.2.
To retrieve the body text:
require_once 'Horde/MIME/Contents.php'; $contents = new MIME_Contents($message); $body_id = $contents->findBody(); if ($body_id) { $part = &$contents->getMIMEPart($body_id); $body = $part->transferDecode(); } else { $body = 'Could not render body of message.'; }
To retrieve a list of all attachments:
$attachments = $contents->getAttachmentContents(); foreach ($attachments as $attachment) { echo 'Attachment ' . htmlspecialchars($attachment['name']) . ' is ' . strlen($attachment['data']) . ' bytes long.'; }
Scenario: Continuing the previous example we want to render the text/calendar part to HTML. This code currently only works inside of a Horde application because it relies on the registry and Horde's configuration files.
require HORDE_BASE . '/config/mime_drivers.php'; require_once 'Horde/MIME/Viewer.php'; $viewer = MIME_Viewer::factory($part); $html = $viewer->render();
Scenario: We want to read a certain message from a certain message on the mail server, for example to search for messages with a known header.
/* Load libraries. */ require_once 'Horde/MIME/Headers.php'; require_once 'Horde/NLS.php'; /* Custom MIME_Headers class because we need to implement _getStream(). */ class MyHeaders extends MIME_Headers { function _getStream() { return imap_open('{localhost/imap}INBOX', 'username', 'password'); } } /* Get message subject. */ $headers = new MyHeaders($message_uid); $headers->buildHeaders(); $subject = $headers->getValue('Subject');
If the headers can't be received from an IMAP server or already are available as a string, this alternative approach could be used:
$headerText = 'Return-Path: <john@example.com> Message-ID: <20080228160832.604925ntqxdo4o00@example.com> Date: Thu, 28 Feb 2008 16:08:32 +0100 From: John Doe <john@example.com> To: jane@example.com Subject: Some Subject'; /* Load libraries. */ require_once 'Horde/MIME/Structure.php'; //require_once 'Horde/NLS.php'; /* Get message subject. */ $headers = MIME_Structure::parseMIMEHeaders($headerText); $subject = $headers['Subject'];
This is a complete example script that parses all messages of an INBOX for any CSV attachments, extract these attachments from the messages, saves them in a folder, and deletes the parsed message. The script can also be downloaded from the AttachedFiles area of this page.
#!/usr/bin/php <?php /* IMAP/POP3 server settings. */ $imap_user = ''; $imap_pass = ''; $imap_host = 'localhost'; $imap_protocol = 'imap/notls'; /* Directory where the CSV attachments get stored WITH trailing slash. */ $target_dir = '/home/jan/csv/'; /* Search string for potential messages. * Might be optimized by using something like 'SUBJECT "Always the same"'. */ $imap_search = 'ALL'; /* Possible mime types of CSV attachments. */ $csv_mimetypes = array('text/plain', 'text/x-comma-separated-values', 'application/csv', 'application/vnd.ms-excel'); /* If necessary set the include path to the location where PEAR and the Horde * packages are installed. */ // ini_set('include_path', '/usr/share/php'); /****************************************************************************/ /** * Shows all IMAP errors and exits. */ function error_out() { $errors = imap_errors(); if ($errors) { foreach ($errors as $error) { echo $error . "\n"; } } exit; } /* Load libraries. */ require_once 'Horde/CLI.php'; require_once 'Horde/MIME/Structure.php'; require_once 'Horde/MIME/Headers.php'; require_once 'Horde/NLS.php'; /* Setup CLI. */ if (!Horde_CLI::runningFromCLI()) { exit("Must be run from the command line\n"); } Horde_CLI::init(); /* Custom MIME_Headers class. */ class MyHeaders extends MIME_Headers { function _getStream() { return $GLOBALS['imap']; } } /* Open IMAP connection. */ $imap = imap_open(sprintf('{%s/%s}INBOX', $imap_host, $imap_protocol), $imap_user, $imap_pass); if (!$imap) { error_out(); } /* Regexp for target filename. */ $regexp = '/_(\d+).csv$/'; /* Get all messages from the folder. */ $messages = imap_search($imap, $imap_search, FT_UID); foreach ($messages as $uid) { $struct = imap_fetchstructure($imap, $uid, FT_UID); /* Is this no multipart message? */ if ($struct->type != 1) { continue; } /* Parse message structure. */ $body = imap_fetchheader($imap, $uid, FT_UID) . imap_body($imap, $uid, FT_UID); $message = MIME_Structure::parseTextMIMEMessage($body); $map = $message->contentTypeMap(); /* Search for message with possible CSV attachment. */ foreach ($map as $mime_id => $mime_type) { if (!in_array($mime_type, $csv_mimetypes)) { continue; } $mime_part = $message->getPart($mime_id); $filename = $mime_part->getName(true); if (String::lower(substr($filename, -4)) != '.csv') { continue; } /* CSV file found. */ $content = $mime_part->transferDecode(); /* Get message subject. */ $headers = new MyHeaders($uid); $headers->buildHeaders(); $subject = $headers->getValue('Subject'); if (empty($subject)) { $subject = $filename; } else { $subject .= '.csv'; } /* Find unique file name. */ $filename = preg_replace('/[^a-z0-9_\-\.]/i', '_', $subject); while (file_exists($target_dir . $filename)) { if (preg_match($regexp, $filename, $match)) { $filename = preg_replace($regexp, '_' . ($match[1] + 1) . '.csv', $filename); } else { $filename = substr($filename, 0, -4) . '_1.csv'; } } /* Write CSV file. */ $fp = fopen($target_dir . $filename, 'w'); if (!$fp) { exit("Can't open file '" . $target_dir . $filename . "' for writing.\n"); } fwrite($fp, $content); fclose($fp); /* Delete message. */ imap_delete($imap, $uid, FT_UID); } } /* Purge and close mailbox. */ // imap_expunge($imap); imap_close($imap); error_out();