Accessing MsgHdr Values

Talk about add-ons and extension development.
Post Reply
dataspace
Posts: 7
Joined: June 17th, 2019, 7:14 am

Accessing MsgHdr Values

Post by dataspace »

What would the best way to read in the encoded/plaintext string of the "content-type" value in the header for a message? The nsIMsgDBHdr interface doesn't contain a specific method to retrieve this value, and using getStringProperty doesn't seem to retrieve it, as

Code: Select all

	console.log(msgHdr.getStringProperty("content-type"));
just logs an empty line, although I could definitely be using it wrong. Is there another method for this in the nsIMsgDBHdr interface, or would it be possible to read in the decoded MIME header as a stream, and then parse it line by line?

Thanks so much! Sorry for the double post so soon.
morat
Posts: 6421
Joined: February 3rd, 2009, 6:29 pm

Re: Accessing MsgHdr Values

Post by morat »

Try these:

Code: Select all

alert(currentHeaderData["content-type"].headerValue);

Code: Select all

var msgHdr = gFolderDisplay.selectedMessage;
var msgUri = msgHdr.folder.getUriForMsg(msgHdr);
var msgService = messenger.messageServiceFromURI(msgUri);
var scriptableInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].
  createInstance(Components.interfaces.nsIScriptableInputStream);
var syncStreamListener = Components.classes["@mozilla.org/network/sync-stream-listener;1"].
  createInstance(Components.interfaces.nsISyncStreamListener);
scriptableInputStream.init(syncStreamListener);
var messageUri = msgService.streamHeaders(msgUri, syncStreamListener, null /*urlListener*/);
var data = new String();
var count = scriptableInputStream.available();
while (count) {
  data = data + scriptableInputStream.read(count);
  count = scriptableInputStream.available();
}
scriptableInputStream.close();
var re = new RegExp("Content-Type: (.*)");
var m = data.match(re);
var header = m && m[1];
alert(header);
P.S.

Here is how to show the properties of the selected message.

Code: Select all

var msgHdr = gFolderDisplay.selectedMessage;
var properties = msgHdr.propertyEnumerator;
var out = new Array();
while (properties.hasMore()) {
  var property = properties.getNext();
  out.push(property);
}
alert(out.join("\n"));
dataspace
Posts: 7
Joined: June 17th, 2019, 7:14 am

Re: Accessing MsgHdr Values

Post by dataspace »

Thanks for the reply! This is exactly what I was trying to find. As a followup, how do we access the currentHeaderData var given a selected msgHdr? Additionally, the content-type doesn't show up in the printed array of properties. Is there DB query/modification possible to change that?
morat
Posts: 6421
Joined: February 3rd, 2009, 6:29 pm

Re: Accessing MsgHdr Values

Post by morat »

If you want the header from a random message, then use the stream listener.

The currentHeaderData object stores the header of the current message.
dataspace
Posts: 7
Joined: June 17th, 2019, 7:14 am

Re: Accessing MsgHdr Values

Post by dataspace »

Streaming the message successfully retrieved the content type. Thanks so much!
dataspace
Posts: 7
Joined: June 17th, 2019, 7:14 am

Re: Accessing MsgHdr Values

Post by dataspace »

A quick followup about scriptable input streams: when implemented with the selected message header (var msgHdr = gFolderDisplay.selectedMessage), the stream works without error and prints the correct values. However, when implemented with the message header for the incoming message (var newMsgHdr = item.QueryInterface(Components.interfaces.nsIMsgDBHdr)), the stream times out on the line

Code: Select all

var count = scriptableInputStream.available();
Upon logging both objects for debugging, the objects are displayed as having the same properties in the sidebar, but the raw text differs slightly:

For the selected message header:
XPCWrappedNative_NoHelper { flags: Getter, folder: Getter, recipients: Getter, ccList: Getter, messageKey: Getter, getStringProperty: getStringProperty(), label: Getter, author: Getter, isRead: Getter, messageId: Getter, 40 more… }

vs. for the incoming message header:
XPCWrappedNative_NoHelper { QueryInterface: QueryInterface(), getProperty: getProperty(), setProperty: setProperty(), setStringProperty: setStringProperty(), getStringProperty: getStringProperty(), getUint32Property: getUint32Property(), setUint32Property: setUint32Property(), isRead: Getter, isFlagged: Getter, isKilled: Getter, 40 more… }

The nsIMsgDBHdr getter methods work for both objects, so I'm not sure why the input stream available() method times out when trying to fetch the bytes of the second message. My suspicion is that the different functions that return them wrapped in slightly different ways, but beyond that, I'm stumped. Any ideas as to why this might be happening or what the fix could be?
morat
Posts: 6421
Joined: February 3rd, 2009, 6:29 pm

Re: Accessing MsgHdr Values

Post by morat »

Try this:

Code: Select all

- scriptableInputStream.init(syncStreamListener);
+ scriptableInputStream.init(syncStreamListener.inputStream);

Code: Select all

- var data = new String();
- var count = scriptableInputStream.available();
- while (count) {
-   data = data + scriptableInputStream.read(count);
-   count = scriptableInputStream.available();
- }
+ const MAX_MESSAGE_LENGTH = 65536;
+ var data = scriptableInputStream.read(MAX_MESSAGE_LENGTH);
i.e.

Code: Select all

var msgHdr = gFolderDisplay.selectedMessage;
var msgUri = msgHdr.folder.getUriForMsg(msgHdr);
var msgService = messenger.messageServiceFromURI(msgUri);
var scriptableInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].
  createInstance(Components.interfaces.nsIScriptableInputStream);
var syncStreamListener = Components.classes["@mozilla.org/network/sync-stream-listener;1"].
  createInstance(Components.interfaces.nsISyncStreamListener);
scriptableInputStream.init(syncStreamListener.inputStream);
var messageUri = msgService.streamHeaders(msgUri, syncStreamListener, null /*urlListener*/);
const MAX_MESSAGE_LENGTH = 65536;
var data = scriptableInputStream.read(MAX_MESSAGE_LENGTH);
scriptableInputStream.close();
var re = new RegExp("Content-Type: (.*)");
var m = data.match(re);
var header = m && m[1];
alert(header);
Reference
http://dxr.mozilla.org/comm-release/sou ... ervice.idl (streamMessage and streamHeaders methods)
http://dxr.mozilla.org/comm-release/sea ... r+ext%3Ajs (nsISyncStreamListener examples)
http://dxr.mozilla.org/comm-release/sou ... ersion.txt

You could try passing true for the streamHeaders method optional aLocalOnly param if the headers are in the offline store.
Post Reply