473,409 Members | 1,966 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,409 software developers and data experts.

Outlook Message Format Library

Hi all,

I need to be able to take messages that have been saved from Outlook
(*.msg) and read them into a C# application (think of it as workflow
management). But these msg files are pretty funky.
All my research only turned up stuff about Automating Exchange and MAPI
which I know nothing about. I would prefer in this instance to think of
it more as a "black box" scenario where I can have a nice managed
library where I can load a msg file and have nicely exposed properties
about the message. We would then save the important information
(sender, subject, body, importance) to a database table and discard the
actual message file.

I can pay for such a component if it exists, but can develop one with
the right guidance as well.

Can you please provide advice to help me solve my problem?

Many thanks,
Steven Nagy

Dec 13 '06 #1
2 5195
Hi Steven,
I had to deal with *.msg files as well a while back. Turns out they are
actually so-called compound files (a single file containing several
streams/subdirectories).
First you need the StgOpenStorage(Ex) function from the ole32.dll to
open these files, then
you can use the IStream/IStorage Interfaces to work with the contents
(IStream is already implemented in the .NET Framework, IStorage
unfortunately isn't).
I can't release the classes I created to work with these messages, but
I can provide you with my IStorage-Interface and StgOpenStorage
definitions, hopefully these will enable you to open the *.msg files
and take a look at their contents.
Its actually pretty straightforward from there, certain properties are
always stored in certain subdirectories/streams, so you need to figure
out the names of the streams you need and read their contents.
For further assistance with the IStream/IStorage interfaces you can
take a look at the msdn, they are pretty well documented.

Sincerely,
Kevin Wienhold

Definitions:

[ComImport,ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown )]
[Guid("0000000b-0000-0000-C000-000000000046")]
public interface IStorage
{
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CreateStream(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] int grfMode,
[In] int reserved1,
[In] int reserved2,
[Out] out UCOMIStream ppstm);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint OpenStream(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] IntPtr reserved1,
[In] int grfMode,
[In] int reserved2,
[Out] out UCOMIStream ppstm);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CreateStorage(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] int grfMode,
[In] int reserved1,
[In] int reserved2,
[Out] out IStorage ppstg);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint OpenStorage(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgPriority,
[In] int grfMode,
[In] string[] snbExclude,
[In] int reserved,
[Out] out IStorage ppstg);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CopyTo(
[In] int ciidExclude,
[In] Guid[] rgiidExclude,
[In] string[] snbExclude,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgDest);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint MoveElementTo(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgDest,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName,
[In] int grfFlags);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Commit(
[In] int grfCommitFlags);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Revert();
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint EnumElements(
[In] int reserved1,
[In] IntPtr reserved2,
[In] int reserved3,
[Out] out IEnumSTATSTG ppenum);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint DestroyElement(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint RenameElement(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsOldName,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetElementTimes(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] ref FILETIME pctime,
[In] ref FILETIME patime,
[In] ref FILETIME pmtime);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetClass(
[In] ref Guid clsid);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetStateBits(
[In] uint grfStateBits,
[In] uint grfMask);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Stat(
[Out] out STATSTG pstatstg,
[In] uint grfStatFlag);

}
[DllImport("Ole32.dll")]
private static extern int StgOpenStorage
(
[MarshalAs(UnmanagedType.LPWStr)] string wcsName,
IStorage pstgPriority,
int grfMode, // access method
IntPtr snbExclude, // must be NULL
int reserved, // reserved
out IStorage storage // returned storage
);

Steven Nagy schrieb:
Hi all,

I need to be able to take messages that have been saved from Outlook
(*.msg) and read them into a C# application (think of it as workflow
management). But these msg files are pretty funky.
All my research only turned up stuff about Automating Exchange and MAPI
which I know nothing about. I would prefer in this instance to think of
it more as a "black box" scenario where I can have a nice managed
library where I can load a msg file and have nicely exposed properties
about the message. We would then save the important information
(sender, subject, body, importance) to a database table and discard the
actual message file.

I can pay for such a component if it exists, but can develop one with
the right guidance as well.

Can you please provide advice to help me solve my problem?

Many thanks,
Steven Nagy
Dec 13 '06 #2
Thanks Kevin. This is definately a good place for me to start.
Great well rounded response!
KWienhold wrote:
Hi Steven,
I had to deal with *.msg files as well a while back. Turns out they are
actually so-called compound files (a single file containing several
streams/subdirectories).
First you need the StgOpenStorage(Ex) function from the ole32.dll to
open these files, then
you can use the IStream/IStorage Interfaces to work with the contents
(IStream is already implemented in the .NET Framework, IStorage
unfortunately isn't).
I can't release the classes I created to work with these messages, but
I can provide you with my IStorage-Interface and StgOpenStorage
definitions, hopefully these will enable you to open the *.msg files
and take a look at their contents.
Its actually pretty straightforward from there, certain properties are
always stored in certain subdirectories/streams, so you need to figure
out the names of the streams you need and read their contents.
For further assistance with the IStream/IStorage interfaces you can
take a look at the msdn, they are pretty well documented.

Sincerely,
Kevin Wienhold

Definitions:

[ComImport,ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown )]
[Guid("0000000b-0000-0000-C000-000000000046")]
public interface IStorage
{
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CreateStream(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] int grfMode,
[In] int reserved1,
[In] int reserved2,
[Out] out UCOMIStream ppstm);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint OpenStream(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] IntPtr reserved1,
[In] int grfMode,
[In] int reserved2,
[Out] out UCOMIStream ppstm);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CreateStorage(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] int grfMode,
[In] int reserved1,
[In] int reserved2,
[Out] out IStorage ppstg);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint OpenStorage(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgPriority,
[In] int grfMode,
[In] string[] snbExclude,
[In] int reserved,
[Out] out IStorage ppstg);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CopyTo(
[In] int ciidExclude,
[In] Guid[] rgiidExclude,
[In] string[] snbExclude,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgDest);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint MoveElementTo(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgDest,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName,
[In] int grfFlags);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Commit(
[In] int grfCommitFlags);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Revert();
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint EnumElements(
[In] int reserved1,
[In] IntPtr reserved2,
[In] int reserved3,
[Out] out IEnumSTATSTG ppenum);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint DestroyElement(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint RenameElement(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsOldName,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetElementTimes(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] ref FILETIME pctime,
[In] ref FILETIME patime,
[In] ref FILETIME pmtime);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetClass(
[In] ref Guid clsid);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetStateBits(
[In] uint grfStateBits,
[In] uint grfMask);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Stat(
[Out] out STATSTG pstatstg,
[In] uint grfStatFlag);

}
[DllImport("Ole32.dll")]
private static extern int StgOpenStorage
(
[MarshalAs(UnmanagedType.LPWStr)] string wcsName,
IStorage pstgPriority,
int grfMode, // access method
IntPtr snbExclude, // must be NULL
int reserved, // reserved
out IStorage storage // returned storage
);

Steven Nagy schrieb:
Hi all,

I need to be able to take messages that have been saved from Outlook
(*.msg) and read them into a C# application (think of it as workflow
management). But these msg files are pretty funky.
All my research only turned up stuff about Automating Exchange and MAPI
which I know nothing about. I would prefer in this instance to think of
it more as a "black box" scenario where I can have a nice managed
library where I can load a msg file and have nicely exposed properties
about the message. We would then save the important information
(sender, subject, body, importance) to a database table and discard the
actual message file.

I can pay for such a component if it exists, but can develop one with
the right guidance as well.

Can you please provide advice to help me solve my problem?

Many thanks,
Steven Nagy
Dec 14 '06 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Fritz Switzer | last post by:
Can anyone provide a small snippet in C# that pulls out the Contacts in Outlook XP. I've seen a couple of examples in C++ and VB in previous newsgroup posts, but either the originals didn't work...
2
by: MaxH | last post by:
I need to perform programmatically from a C# .net application the following tasks: _ open an outlook (or default e-mail client) compose message window; _ attach a document to the new message; _...
3
by: Kurt | last post by:
Hi We are developing an off-the-shelf software suite for a certain business sector. Most of the program is simply a GUI on top of some .mdb files. Its a .net application written in c# One...
1
by: Eric Nelson | last post by:
Experienced, but first time outlook programmer asks... Each day I get an e-mail containing a gzipped tar archive as an attachment. I'd like an automated way to (1) save the archive as-is in a...
5
by: Susan Bricker | last post by:
Greetings. I am trying to create an instance of Outlook.Application so that I may build an email within a routine in the VBA behind my database. I am running MS/Access 2003 (2000 format). The...
3
by: Bigfoot | last post by:
Hello, I would like to send e-mail and meetingrequests from an asp.NET webform, is this possible? In other words: can I use the Outlook objectmodel in asp.NET? Stefan
10
by: John | last post by:
Hi When I open a new outlook email from vb.net, sometimes outlook is very slow to appear or occasionally outlook freezes completely. I am targeting mixed office2000/xp environments so I am...
23
by: Graham F French | last post by:
Hello, I can read text files into my application, but I cannot read in msg files as they seem to be in a proprietry format. Is there anyway of converting it on the fly or is there an...
9
by: Srinivas | last post by:
hi all how to access the outlook user profiles through VB.net any help.... thanks in advanc Srinivas
2
by: Ori :) | last post by:
I am writing an application to retrieve appointments from Outlook, I have the appointment items sorted by "Start" field and now I want to find the first record which's "Start" value is later than...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.