Email to RSS Feeder

Some days back my boss given me assignment to setup an system to move the noisy emails to some RSS feeder or newsgroup. I never work on RSS or any newsgroup distribution lists. But yes i know the RSS concept.

Generally people use RSS to feed the updates of there website, or one step ahead to it, integrate RSS to emails, Means if any updates came to subscribed RSS you will get the corresponding email. All these kond of requirement you can easily workout by searching on google. But my requirement is opposite to it. I want all the noisy emails like houry reports or lots of other unwanted emails some of them came on 15 mins basis also. So there are huge emails coming to everybody’s mailbox.

I searched lot on google to workout on this requirement finally found a cool solution(php script) that worked for me like a charm.

Below is the script:

<?php
// imap2rss.php .
// A simple PHP script to convert the data in an IMAP mailbox available
// over the internet to an RSS file readable by news aggregators.

// GLOBAL CONFIGURATION
// Version of imap2rss.php
$vers = "1.0beta3";
// Permalink for this feed - just points to the current page.
$feedLink = "http://".$_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
// Configuration file directory - used if you want to place your configuration file somewhere outside your web server path.  Make sure the user
// running the web server has read permission to this file
$configurationDirectory = "/etc";

// Part types taken from php.net documentation
$parttypes = array ("text", "multipart", "message", "application", "audio", "image", "video", "other");

// Check if an external configuration has been chosen and load it if possible
if(isset($_GET['conf'])) {
// First, strip out dangerous characters
$slashpos = strrpos($_GET['conf'], '/');
if($slashpos === false)
$slashpos = strrpos($_GET['conf'], '\\');
if($slashpos !== false)
$conf = substr($_GET['conf'], $slashpos+1);
else
// Open the file inside the configuration directory
$conf = $configurationDirectory."/".$_GET['conf'].".conf.php";
// If the file exists, load the parameters.
if(file_exists($conf)) {
require($conf);
$feedLink .= "?conf=".$_GET['conf'];
} else {
// Configuration file does not exist - error and exit
die("Selected configuration not available");
}
}

// Load variables only if an external configuration was not selected.
if(!isset($srvStr)) {
// Server string for IMAP connection.
// Hint: Changing "localhost" for your hostname should do it.
$srvStr = "{localhost:143/notls}INBOX";
// IMAP account username
$accountUser = "username";
// IMAP account password
$accountPass = "password";
// Maximum number of messages to include in the feed
// (from newest, 0 for no limit)
$maxMsgNum = 0;
// Title for this feed
$feedTitle = "imap2rss.php Feed";
// Feed description
$feedDesc = "Sample description";
// Feed language
$feedLang = "en-gb";
// Feed editor's name
$feedEditor = "Feed Editor";
// Feed editor's email
$feedEditorMail = "editor@example.com";
// General Options
// Munge sender emails - 1 for yes, 0 for no
$mungeSenderEmail = 0;
// Make http addresses links in plain-text emails
$makeHttpLinks = 1;
// Make email addresses mailto: links in plain-text emails
$makeMailtoLinks = 1;
}

//-------------------------------------------------------------------
// reEncodeString()
// Goes through a string an reencodes all the html entities that it
// finds into a format that won't make XML parsers choke.
function reEncodeString($string) {
$temp = $string;
$ents = get_html_translation_table(HTML_ENTITIES);
$special = get_html_translation_table();
$table = array_diff($ents, $special);
foreach($table as $item) {
$temp = str_replace($item, "&amp;".substr($item, 1), $temp);
}
return $temp;
}

//-------------------------------------------------------------------
// mungeEmailAddress()
// Munges an email address to prevent being harvested by spambots.
// This is really simple, you can replace this with whatever technique you prefer.
// Remember that for the feed to validate as RSS, this needs to be a valid address,
// @ sign and all, so the munging is limited.
function mungeEmailAddress($address) {
return str_replace("@", ".NOSP@MMER.", $address);
}

//-------------------------------------------------------------------
// renderPlainText()
// Processes plain text so that it looks decent when rendered as HTML.
// All it does is substitute newline characters for <br> tags.
// It also substitutes URLs for links and email addresses for mailto:
// links.
function renderPlainText($text) {
global $makeHttpLinks, $makeMailtoLinks;
// Throw in <br> tags
$retval = str_replace("\n", "<br/>\n", $text);
if($makeHttpLinks) {
// Replace urls with links
$retval = preg_replace('/\s(\w+:\/\/)(\S+)/',
' <a href="\\1\\2" target="_blank">\\1\\2</a>', $retval);
}
if($makeMailtoLinks) {
// Replace email addresses with mailto: links
$retval = preg_replace('/\s(\w+@)(\S+)/',
' <a href="mailto:\\1\\2">\\1\\2</a>', $retval);
}
return $retval;
}

//-------------------------------------------------------------------
// returnAttachment()
// This function returns a given attachment from an item.
function returnAttachment($itemId, $attachId) {
global $vers, $parttypes, $srvStr, $accountUser, $accountPass;
$inbox = imap_open($srvStr, $accountUser, $accountPass);
$msgStructure = imap_fetchstructure($inbox, $itemId);
$part = $msgStructure->parts[$attachId-1];
$ctype = $parttypes[$part->type]."/".$part->subtype;
$filename = "filename";
foreach($part->parameters as $param) {
if($param->attribute=="NAME")
$filename = $param->value;
}
header("content-type: ".$ctype);
header("content-disposition: attachment; filename=".$filename);
// Returned data depends on whether the attachment is binary or text
if($part->type>0) {
// Binary attachment - convert from base64 to binary
echo base64_decode(imap_fetchbody($inbox, $itemId, $attachId));
} else {
// Text attachment - just display it as-is
echo imap_fetchbody($inbox, $itemId, $attachId);
}
imap_close($inbox);
return;
}

//-------------------------------------------------------------------
// showArticle()
// This function displays a post in an html page. This
// functionality exists to complement permalink/guid behaviour
// in RSS and also to enable compatibility with readers like
// Thunderbird, that always load the permalink instead of
// displaying the summary.
function showArticle($articleId) {
global $vers, $srvStr, $accountUser, $accountPass, $mungeSenderEmail;
$inbox = imap_open($srvStr, $accountUser, $accountPass);
header('Content-type: text/html');
// Retrieve post information from the message header
$headers = imap_headerinfo($inbox, $articleId);
$subject = htmlentities($headers->subject);
$author = htmlentities($headers->fromaddress);
// If author email munging is enabled...
if($mungeSenderEmail) {
$author = mungeEmailAddress($author);
}
// Format the date according to the standard
$entryDate = date("D, d M Y H:i:s O", $headers->udate);
// Get the message body.
// Negotiate the presence of attachments.
$msgStructure = imap_fetchstructure($inbox, $articleId);
if(count($msgStructure->parts)>1) {
$body = imap_fetchbody($inbox, $articleId, "1");
if($msgStructure->parts[0]->subtype=="PLAIN")
$body = renderPlainText($body);
$body .= "<h3>Attachments:</h3>\n";
$partCount = 0;
foreach($msgStructure->parts as $part) {
$partCount++;
if (isset($part->disposition)) {
foreach($part->parameters as $param) {
if($param->attribute=="NAME")
// Generate the link for retrieving attachments
$body .="<a href=\"".$feedLink;
if(isset($_GET['conf'])) {
$body .= "?conf=".$_GET['conf']."&amp;";
} else {
$body .= "?";
}
$body .="itemId=".$articleId."&attachId=".$partCount."\">";
$body .=$param->value."</a><br/>\n";
break;
}
}
}
} else {
$body = imap_body($inbox, $articleId);
}
// If the body is plain-text, run the HTML rendering function
if($msgStructure->subtype=="PLAIN")
$body = renderPlainText($body);
imap_close($inbox);
// The HTML used for displaying post content.
?>
<html>
<head>
<title><?php echo $subject;?></title>
</head>
<body>
<div style="background:#eeeeee; border:solid 1px"
<strong><?php echo $subject; ?></strong><br />
<i><?php echo "by: ".$author.", @ ".$entryDate;?></i>
</div>
<br />
<?php echo $body; ?>
</body>
</html>
<?php
}
//-------------------------------------------------------------------
// generateFeed()
// Opens an IMAP connection to the specified server and converts the
// contents of the inbox to an RSS feed.
function generateFeed() {
global     $vers, $srvStr, $accountUser, $accountPass, $feedTitle, $maxMsgNum,
$feedLink, $feedDesc, $feedLang, $feedEditor, $feedEditorMail, $mungeSenderEmail;

$inbox = imap_open($srvStr, $accountUser, $accountPass);

$pubDate = date("D, d M Y H:i:s O", time());

header('Content-type: text/xml');

// RSS header
echo "<?xml version=\"1.0\"?>\n";
echo "<rss version=\"2.0\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n";
echo "   <channel>\n";
echo "       <title>$feedTitle</title>\n";
echo "       <link>$feedLink</link>\n";
echo "       <description>$feedDesc</description>\n";
echo "       <language>$feedLang</language>\n";
echo "       <generator>IMAP2RSS v.$vers</generator>\n";
echo "       <managingEditor>$feedEditor ($feedEditorMail)</managingEditor>\n";
echo "       <webMaster>$feedEditor ($feedEditorMail)</webMaster>\n";
echo "       <pubDate>$pubDate</pubDate>\n";

// Calculate the number of items to include in the feed.
$msgCount = imap_num_msg($inbox);
if($maxMsgNum && $msgCount>$maxMsgNum)
$lowerLimit = $msgCount - $maxMsgNum;
else
$lowerLimit = 0;
// Generate item entries
for($i=$msgCount; $i>$lowerLimit; $i--) {
$headers = imap_headerinfo($inbox, $i);
$subject = reEncodeString(htmlentities($headers->subject));
// Use htmlentities() because sometimes the address appears
// inside angle brackets.
$author = reEncodeString(htmlentities($headers->fromaddress));
// If author email munging is enabled...
if($mungeSenderEmail) {
$author = mungeEmailAddress($author);
}
// Format the date according to the standard
$entryDate = date("D, d M Y H:i:s O", $headers->udate);
// Set the item link depending on whether there is a custom
// configuration in use or not.
$itemUrl = $feedLink.((isset($_GET['conf']))?"&amp;":"?")."itemId=$i";

// Negotiate the presence of attachments.
$msgStructure = imap_fetchstructure($inbox, $i);
if(count($msgStructure->parts)>1) {
$body = imap_fetchbody($inbox, $i, "1");
// If the body is plain-text, run the HTML rendering function
if($msgStructure->parts[0]->subtype=="PLAIN")
$body = renderPlainText($body);
$body .= "<h3>Attachments:</h3>\n";
$partCount = 0;
foreach($msgStructure->parts as $part) {
$partCount++;
if (isset($part->disposition)) {
foreach($part->parameters as $param) {
if($param->attribute=="NAME")
// Generate the link for retrieving attachments
$body .="<a href=\"".$feedLink;
if(isset($_GET['conf'])) {
$body .= "&amp;";
} else {
$body .= "?";
}
$body .="itemId=".$i."&attachId=".$partCount."\">";
$body .=$param->value."</a><br/>\n";
break;
}
}
}
} else {
$body = imap_body($inbox, $i);
// If the body is plain-text, run the HTML rendering function
if($msgStructure->subtype=="PLAIN")
$body = renderPlainText($body);
}
// Clean up output to avoid problems with the XML produced
$body = reEncodeString(htmlentities($body));
echo "       <item>\n";
echo "        <title>$subject</title>\n";
echo "               <link>$itemUrl</link>\n";
echo "               <pubDate>$entryDate</pubDate>\n";
echo "               <description>$body</description>\n";
echo "               <dc:creator>$author</dc:creator>\n";
echo "               <guid>$itemUrl</guid>\n";
echo "       </item>\n";
}
echo "     </channel>\n";
echo "</rss> ";

imap_close($inbox);
}

// display page body
// If an itemId has been set, display that item in an HTML page.
// If an itemId and an attachId have been set, return that attachment
// If not, show the entire feed.
if(isset($_GET['itemId'])) {
if(isset($_GET['attachId'])) {
returnAttachment($_GET['itemId'], $_GET['attachId']);
} else {
showArticle($_GET['itemId']);
}
} else {
generateFeed();
}
?> 

You can download the script directly from here

Just make the IMAP mail server settings thats it. Now place the script any of the webserver document root, then you can access these feeds using any of the RSS reader.
To test wheather your script is working or not, you can check that by accessing the mai2rss.php from URL. For eg.
I have placed the script on linuxtrove document root now my URL would be http://linuxtrove.com/mail2rss.php it will show the mails for the user that you have configured in your script in XML format. This script is valid only for one mailbox but you can configure it for multiple mailboxes also.

To use one installation of imap2rss.php to access several mailboxes, you need to create a file in the same directory that you installed the script in, and call it .conf.php. The file should look something like this:


Once you have configured this, you can call imap2rss.php with an additional parameter passed to the script, conf, which should be set to whatever you called the configuration. For example, if your configuration file is called mycfg.conf.php, the url would look like http://yourserver/imap2rss.php?conf=mycfg.
If you have problems hooking up to your IMAP server, read the page referred to near the beginning of the file. Correct configuration for your IMAP server can be tricky

I have tested it with thunderbird and firefox. Firefox need an add-on for this. Any RSS reader will work with it.

All credit goes to http://www.noaxs.net/imap2rss/ who resolved my problem.

  • Al

    Good Work!!! If have problem with german characters. I set lang to de-de, but there are ASCII-characters like =DF instad of ß.

I'm happy to use Increase Sociability.