Serence Inc.
© 2004-2006 Serence Inc.
info@serence.com
http://www.serence.com
POP3 Email
EXc312AzsGWheOqjsDXFZneg78f5lMx1WxAjbsojlSzHF3NKoKnPDCEwwn1e0MtVuezJbccBDCmRvsp7Ck9vDxo35Xt9uAo3Vl77GUCr7QI+2sWcr3zuekFbOYKNsH8IcwEwDr6Wbqud+jpPw9/ORqFgEr2FHUpE2O+BR+BXUtU=
3.04
2006.08.14:1139
This Klip will notify you when new email has been delivered to your
POP3 email account.
email pop pop3 new message incoming received
http://www.serence.com/serence_klips/pics/email/email_klip_icon.png
http://www.serence.com/serence_klips/pics/email/pop_klip_banner.jpg
http://www.serence.com/serence_klips/email_pop3.klip
No new mail.
--
extended
65001
true
0)
{
result += "~|~";
}
result += prop+": "+message[prop];
}
return result;
}
function serializedHeaderValue(messageStr, key)
{
var result = "";
var key_re = new RegExp("(?:^|~\\|~)" + key + ":\\s([^]*?)(?:$|~\\|~)");
var match = messageStr.match(key_re);
if (match)
{
result = match[1];
}
return result;
}
function formatItem(item)
{
if (KlipFolio.build < 5840)
{
var messageStr = item.extra;
var text = "";
for (var j = 0; j < headerFields.length; j++)
{
if (text.length > 0)
{
text += delim;
}
text += serializedHeaderValue(messageStr, headerFields[j]);
}
item.text = text;
}
else
{
for (var j = 0; j < headerFields.length; j++)
{
item.setData("col" + (j+1), ""+item.getData(headerFields[j]));
}
for (var j = headerFields.length; j < 3; j++)
{
item.setData("col" + (j+1), "");
}
}
}
function formatChange(index)
{
Prefs.setPref ("format", "" + index);
headerFields = column_maps[index].split(',');
for (var i = 0; i < Items.length; i++)
{
formatItem(Items[i]);
}
}
function refreshRateChange (index)
{
Prefs.refreshrate = refresh_rate_array[index]-0;
Prefs.setPref("refreshrate", "" + c_refresh_rate.selected);
}
function loadPrefs ()
{
refreshRateChange(c_refresh_rate.selected);
}
function savePrefs ()
{
if (c_user.value && c_user.value.length)
{
Items.altA = Prefs.title + " (" + c_user.value + ")";
}
else
{
Items.altA = Prefs.title;
}
if (c_server.value != Prefs.getPref ("server") ||
c_user.value != Prefs.getPref ("user")
)
{
Prefs.setPref ("account_changed", "true");
}
Prefs.setPref("server", c_server.value);
Prefs.setPref("user", c_user.value);
Prefs.setPref("pass", garble(c_pass.value));
Prefs.setPref("format", "" + c_format.selected);
Prefs.setPref("refreshrate", "" + c_refresh_rate.selected);
Prefs.setPref("getbody", "" + c_get_body.checked);
Prefs.setPref("dashboard", "" + c_dashboard.checked);
}
function prefsValid()
{
return (c_server.value.length && c_user.value.length && c_pass.value.length);
}
function introMessage()
{
// create temporary items to educate the user
Items.clear (true);
var food = "";
food += newElement("title", 'To configure this email Klip, click here and sign in to the account you wish to monitor.');
food += newElement("body", 'This Klip continuously monitors your email account for new messages.');
food += newElement("uidl", 'intro');
food += "";
var saveCreate = Engines.KlipFood.onCreate;
var saveUpdate = Engines.KlipFood.onUpdate;
Engines.KlipFood.onCreate = null;
Engines.KlipFood.onUpdate = null;
try
{
Engines.KlipFood.process(food);
}
finally
{
Engines.KlipFood.onCreate = saveCreate;
Engines.KlipFood.onUpdate = saveUpdate;
}
idx = Items.length - 1;
Items[idx].canvisit = false; Items[idx].candelete = false; Items[idx].onClick = fn_configure_item_click;
Items.B = " ";
}
function fn_configure_item_click ()
{
Setup.open (0);
}
function newElement(tag, value)
{
return "<" + tag + ">" + value + "" + tag + ">";
}
function check(item)
{
formatItem(item);
item.candelete = (!c_dashboard.checked);
item.canvisit = false;
return true;
}
function createItem(newItem)
{
newItem.touched = true;
return check(newItem);
}
function updateItem(oldItem, properties)
{
oldItem.touched = true;
return check(properties);
}
function processData30(message)
{
var food = "- ";
for (prop in message)
{
if (message[prop].length)
{
food += newElement(prop, message[prop]);
}
}
food += newElement("col1", "");
food += newElement("col2", "");
food += newElement("col3", "");
if (message.content_type && (message.content_type.indexOf("multipart/mixed") >= 0))
{
food += newElement("icon", "http://www.serence.com/serence_klips/pics/email/email-unread-attach.png");
}
else
{
food += newElement("icon", "http://www.serence.com/serence_klips/pics/email/email-unread.png");
}
food += "
";
Engines.KlipFood.process(food);
}
function processData26(message)
{
var idx = Items.create (message.uidl, "", message.uidl);
if (idx >= 0)
{
var item = Items[idx];
item.pubdate = message.pubdate;
item.note =
//"Message UIDL: " + message.udil + "\r\n" +
"From: " + message.from_long + "\r\n" +
"Sent: " + message.date_long + "\r\n" +
"To: " + message.to + "\r\n" +
(message.cc != null?"CC: " + message.cc + "\r\n":"") +
(message.subject_full != null ? "Subject: " + message.subject_full + "\r\n\r\n":"") +
(message.body != null?message.body + "\r\n\r\n":"") +
"Size: " + message.size
;
item.extra = serializeHeader(message);
item.candelete = (!c_dashboard.checked);
item.canvisit = false;
formatItem(item);
Items.sort ("pubdate");
}
}
function processData(message)
{
if (KlipFolio.build < 5840)
{
processData26(message);
}
else
{
processData30(message);
}
}
/////////////////////////////////////////////////////////////////////////////
// onRefresh()
/////////////////////////////////////////////////////////////////////////////
function setStatus (status, alert)
{
Klip.progressmessage = status;
}
function onRefresh ()
{
var result = false;
var last_refresh_complete = (Prefs.getPref("lrc") == "true");
Prefs.setPref ("lrc", "false");
savePrefs ();
if (Prefs.getPref ("account_changed") == "true")
{
Prefs.setPref ("account_changed", "false");
Items.clear (true);
Items.Deleted.clear ();
}
if (!prefsValid())
{
introMessage();
return false;
}
else
{
Items.B = "";
}
Engines.KlipFood.onCreate = createItem;
Engines.KlipFood.onUpdate = updateItem;
setStatus("Connecting...");
var conn = Engines.TCP.newConnection();
conn.host = c_server.value; conn.port = 110;
if (openConnection(conn))
{
setStatus ("Authenticating...");
if (authenticateUser(conn))
{
var count = getMessageCount(conn);
if (count < 0)
{
setStatus ("Error: could not count messages");
}
else
{
// Items.purge(true);
if (Items.length && Items[0].getData ("uidl") == "intro")
{
Items.remove (0, true);
}
var i;
for (i = 0; i < Items.length; ++i)
{
Items[i].touched = false;
}
if (count == 0)
{
result = true;
}
else
{
if (c_dashboard.checked)
{
var new_messages = enumerateMessages(conn);
if (new_messages != null)
{
for (i = new_messages.length-1; i >= 0; i--)
{
setStatus ("Downloading message " + (count - i) + " of " + count);
if (downloadMessage(conn, i+1, new_messages[i]))
{
processData(new_messages[i]);
}
}
result = true;
for (i = 0; i < Items.length; ++i)
{
if (!Items[i].touched)
{
Items.remove (i);
--i;
}
}
}
}
else
{
// grab the last UIDL in the messagedrop
var last_uidl = getMessageUIDL(conn, count);
if (last_uidl != null)
{
// check to see if we've got this message already
if (last_refresh_complete && (findUIDL(last_uidl) >= 0))
{
// we must have all the messages currently in the messagedrop so abort this fetch
result = true;
}
else
{
var new_messages = enumerateMessages(conn);
if (new_messages != null)
{
for (var i = new_messages.length - 1; i >= 0; i--)
{
if (findUIDL(new_messages[i].uidl) < 0)
{
setStatus ("Downloading message " + (count - i) + " of " + count);
if (downloadMessage(conn, i+1, new_messages[i]))
{
processData(new_messages[i]);
}
}
}
result = true;
}
}
}
}
}
savePrefs ();
Prefs.setPref ("lrc", result);
}
closeConnection(conn);
}
else
{
if (c_user.value.length || c_pass.length)
{
setStatus ("Error: could not authenticate");
}
}
conn.close();
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
// POP3 protocol implementation
/////////////////////////////////////////////////////////////////////////////
var message_stat_re = new RegExp ("+OK (\\d+) (\\d+)");
var message_multi_list_re = new RegExp ("^(\\d+) (\\d+)", "gm");
var message_uidl_re = new RegExp ("+OK (\\d+) (.*)");
var message_multi_uidl_re = new RegExp ("^(\\d+) (.*?)$", "gm");
var email_address_re = new RegExp ("<(.*?)>");
var header_re_text = "^{header}:\\s*([^]*?)\\r\\n[^\\s]";
function openConnection (conn)
{
var data;
// open the TCP connection
if (conn.open())
{
// validate initial server ready response
data = fetchData(conn, false);
if (data != null && data.indexOf ("+OK") == 0)
{
// we've got a valid one-line hello
return true;
}
}
return false;
}
function authenticateUser(conn)
{
var data;
// send the username
var command = "USER " + c_user.value + "\r\n";
if (conn.send(command, command.length))
{
// validate the response
data = fetchData(conn, false);
if (data != null && data.indexOf ("+OK") == 0)
{
// send the password
command = "PASS " + c_pass.value + "\r\n";
if (conn.send(command, command.length))
{
// validate the response
data = fetchData (conn, false);
if (data != null && data.indexOf ("+OK") == 0)
{
return true;
}
}
}
}
if (data != null)
{
trace("Email authentication failed: " + data + "\r\n");
}
else
{
trace("Email authentication failed!\r\n");
}
return false;
}
function getMessageCount(conn)
{
var data;
// request the maildrop status
var command = "STAT\r\n";
if (conn.send(command, command.length))
{
// validate the response
data = fetchData (conn, false);
if (data != null && data.indexOf ("+OK") == 0)
{
// parse out the message count
var m;
if (m = message_stat_re.exec(data))
{
// return the message count as a number
return m[1] - 0;
}
}
}
return -1;
}
function getMessageUIDL(conn, message_num)
{
var data;
// request the UIDL of a given message
var command = "UIDL " + message_num + "\r\n";
if (conn.send(command, command.length))
{
// validate the response
data = fetchData(conn, false);
if (data != null && data.indexOf ("+OK") == 0)
{
// parse out the message count
var m;
if (m = message_uidl_re.exec(data))
{
// return the message uidl
return trim(m[2]);
}
}
}
return null;
}
function enumerateMessages(conn)
{
// request the list of message unique ids
var command = "UIDL\r\n";
if (conn.send(command, command.length))
{
// store the response
var uidl = fetchData(conn, true);
if (uidl != null)
{
// request the list of message sizes
command = "LIST\r\n";
if (conn.send(command, command.length))
{
// store the response
var list = fetchData(conn, true);
if (list != null)
{
var messages = new Array();
var m;
while (m = message_multi_uidl_re.exec(uidl))
{
var message = new Message(m[2]);
message.itemIdx = findUIDL(m[2]);
if ((message.itemIdx >= 0) && (message.itemIdx < Items.length))
{
if (!Items[message.itemIdx])
message.body = headerValue(Items[message.itemIdx], "body");
}
messages[messages.length] = message;
}
var i = 0;
while (m = message_multi_list_re.exec(list))
{
if (i >= messages.length)
{
break;
}
messages[i].size = translateSize(m[2]);
i++;
}
return messages;
}
}
}
}
return null;
}
function downloadMessage(conn, idx, message)
{
if (message != null)
{
var command = "TOP " + idx + " " + (c_get_body.checked?100:0) + "\r\n";
if (conn.send (command, command.length))
{
// validate the response
var data = fetchData (conn, true);
if (data != null && data.indexOf ("+OK") == 0)
{
var bodidx = data.indexOf ("\r\n\r\n");
var header = data.substring (0, bodidx) + "\r\n.";
// parse out the headers
var h_from = decodeHeader("from", header);
var h_to = decodeHeader("to", header);
var h_cc = decodeHeader("cc", header);
var h_subject = decodeHeader("subject", header);
var h_date = decodeHeader("date", header, new Date().toString());
var h_content_type = decodeHeader("content-type", header, "text/plain; charset=us-ascii");
// prepare date
var date, pubdate;
if (h_date.length > 0)
{
pubdate = Engines.MIME.decodeDate(h_date);
}
else
{
pubdate = new Date().getTime() / 1000;
pubdate = Math.round(pubdate);
}
date = new Date(pubdate * 1000);
parseFromHeader(h_from, message);
message.subject_full = h_subject;
message.subject_short = truncateString(h_subject, 60);
message.date_long = date.toString();
message.date_short = months[date.getMonth()] + " " + date.getDate();
message.to = unbracketEmail(h_to);
message.cc = unbracketEmail(h_cc);
message.pubdate = pubdate;
message.content_type = h_content_type;
if (c_get_body.checked && (message.body.length == 0))
{
body = extractBody(data);
if (body.length)
{
body = body.substring(0, 200) + (body.length > 200 ? "..." : "");
}
else
{
body = "[" + h_content_type.substring(0, h_content_type.indexOf(";")) + "]";
}
message.body = body;
}
return true;
}
}
}
return false;
}
function extractBody(data)
{
var body = "";
if (data && data.length)
{
var bodidx = data.indexOf ("\r\n\r\n");
var endidx = data.indexOf ("\r\n.");
var header = data.substring (0, bodidx) + "\r\n.";
var body = data.substring (bodidx + 4, (endidx >= 0 ? endidx : data.length));
var h_content_type = decodeHeader("content-type", header);
if (h_content_type.indexOf("text/") >= 0)
{
var h_transfer_encoding = decodeHeader("content-transfer-encoding", header);
if (h_transfer_encoding.toLowerCase().indexOf("base64") >= 0)
{
body = base64decode(body.replace (/\r\n/g, ""));
}
if (h_transfer_encoding.toLowerCase().indexOf("quoted-printable") >= 0)
{
body = Engines.MIME.unquoteText(body);
}
var h_charset = getAttribute(h_content_type, "charset");
if (h_charset.length)
{
body = Engines.MIME.convertText(body, Engines.MIME.charsetToCodepage(h_charset), 65001);
}
body = stripConsecutiveNewlines(Klip.stripTags(Klip.processEntities(body.replace(/