In my previous article, I described how to read the SMS, MMS, and Emails data from your Windows Mobile device. Now Iโm going to tell you how to read the attachments from the emails. Iโll also explain where you can find the attachments to MMS messages.
Contents
Description of IAttach Properties
Message attachments are one or several additional “blobs” of data, such as a picture, document or sound file attached to the email by a sender. Each individual attachment to a message is supported by the IAttach
interface.
Although the IAttach
interface has no unique methods, it is derived from the IMAPIProp
interface. Below, I describe the properties that are used to configure an attachment.
PR_ATTACH_DATA_BIN
โ itโs the IStream interface, which is used to access the attachment. Property type isPT_BINARY
.PR_ATTACH_FILENAME
โ itโs the display name for the attachment. The type for this property isPT_TSTRING
.PR_ATTACH_METHOD
โ this property must be set to PR_ATTACH_BY_VALUE, it hasPT_LONG
type.PR_ATTACH_NUM
โ Itโs the number that uniquely identifies the attachment within the message. The type for this property isPT_LONG
.PR_ATTACH_SIZE
โ itโs the size, in bytes, of the attachment and all of the attachment properties. The type for this property isPT_LONG
.PR_ENTRYID
โ itโs the object’s entry identifier. The type for property isPT_BINARY
.PR_LAST_MODIFICATION_TIME
โ itโs the last date and time when the object was modified. The type for property isPT_SYSTIME
.PR_NULL
โ itโs a NULL value. The type for property isPT_NULL
.PR_OBJECT_TYPE
โ itโs the type of object. The type for property isPT_LONG
.PR_PARENT_ENTRYID
โ itโs the parent object’s entry identifier. The type for property isPT_BINARY
.
Working with e-mail attachments
We have already discussed how to open message, so I omit this part.
We have an already opened message. So, let’s go ahead and get the attachments by first getting the attachment table for the message.
HRESULT hr = S_OK;
//check
if(pMsg == NULL)
{
return E_FAIL;
}
IMAPITable *attachmentTable = NULL;
hr = pMsg->GetAttachmentTable(0, &attachmentTable);
if(FAILED(hr))
{
return hr;
}
In this example, we query the table for the PR_ATTACH_NUM
for the attachment we are interested in.
Then we need to get the properties from the table for the Attachments. For example, weโll read just three: PR_ATTACH_NUM
, PR_ATTACH_SIZE
, PR_ATTACH_FILENAME
.
SRowSet *pAttachmentRowSet = NULL;
SizedSPropTagArray(3, tableAttachmentColumns) =
{3,{PR_ATTACH_NUM,PR_ATTACH_SIZE,PR_ATTACH_FILENAME}};
attachmentTable->SetColumns((LPSPropTagArray)&tableAttachmentColumns, 0);
Then, in the cycle, we can ask all attachments of the email.
โฆ
hr = attachmentTable->QueryRows(1, 0, &pAttachmentRowSet);
if(pAttachmentRowSet->cRows != 1)
return E_FAIL;
// Grab the properties from the table entry that you will use to open the attachment stream.
long attachmentNumber = 0;
DWORD attachmentSize = 0;
TCHAR attachmentName[MAX_PATH] = TEXT("");
attachmentNumber = pAttachmentRowSet->aRow[0].lpProps[0].Value.l;
attachmentSize = pAttachmentRowSet->aRow[0].lpProps[1].Value.ul;
_tcscpy(attachmentName, pAttachmentRowSet->aRow[0].lpProps[2].
Value.lpszW);
FreeProws(pAttachmentRowSet);
Using the IMessage::OpenAttach()
method with the attachment number, which we found in the query, we can get the IAttach
interface pointer.
IAttach *pAttach = NULL;
hr = pMsg->OpenAttach(attachmentNumber, 0, 0, &pAttach);
if(FAILED(hr))
{
return hr;
}
After getting an attach interface, we can get the IStream
pointer for the PR_ATTACH_DATA_BIN
property.
LPSTREAM AttachmentStream = NULL;
TCHAR filePath[MAX_PATH] = TEXT("");
wsprintf(filePath, TEXT("%s"), attachmentName);
hr = pAttach->OpenProperty(PR_ATTACH_DATA_BIN, NULL, 0, 0,
(IUnknown **)&AttachmentStream);
When we have the stream pointer, we can copy it to the file or vector of bytes.
STATSTG stg;
HRESULT hr = pstmBody->Stat(&stg,STATFLAG_NONAME);
if (FAILED(hr))
{
return hr;
}
unsigned int bodysize = stg.cbSize.LowPart;
if(bodysize == 0)
{
return hr;
}
unsigned char* bodybuf = new unsigned char[bodysize];
ZeroMemory(bodybuf, bodysize);
ULONG read;
hr = pstmBody->Read(bodybuf, bodysize, &read);
if (FAILED(hr) || bodysize != read)
{
delete bodybuf;
return hr;
}
outBuffer.assign(bodybuf, bodybuf + bodysize);
delete [] bodybuf;
And donโt forget to clean up all resources.
AttachmentStream->Release();
pAttach->Release();
โฆ
attachmentTable->Release()
MMS attachments โ short explanation
We cannot read mms attachments in the same way we read the email ones.
The MMS storage will send us an error when we ask for the properties from the attachment table.
IMAPITable *attachmentTable = NULL;
โฆ
hr = attachmentTable->QueryRows(1, 0, &pAttachmentRowSet);
if(FAILED(hr))
{
return hr;
}
โฆ
We can find MMS attachments in the raw body of the message. My previous article can tell you about how to read the message body.
โฆ
HRESULT hr = pMsg->OpenProperty (PR_BODY, NULL, STGM_READ, 0, (IUnknown **) &pstmBody);
โฆ
The format of MMS message is SMIL (Synchronized Multimedia Integration Language). We can find the attachments looking through the raw message body.
Parsing of the SMIL body of an MMS massage is beyond the scope of this article.
Conclusion
I hope this article helped you to get to know about:
- Work with the e-mail attachments
- The differences between Email and MMS attachments
In this article, I didnโt show how to get the MMS attachments and how to parse SMIL format.
Useful links
Download Sample Source (ZIP, 12 KB)
Read another Dev Blog article: How to USB debug Windows.