- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A recent thread has shown how Jugoslav Dujic's wrappers can be used to access MAPI functionality.
A typical call to the MAPIReadMail function returns a pointer to a MAPIMessage structure (code
taken from Jugoslav's MAPI module, with thanks)
type T_MapiMessage
SEQUENCE
integer ulReserved ! Reserved for future use (M.B. 0)
integer(LPSTR) lpszSubject ! Message Subject
integer(LPSTR) lpszNoteText ! Message Text
integer(LPSTR) lpszMessageType ! Message Class
integer(LPSTR) lpszDateReceived ! in YYYY/MM/DD HH:MM format
integer(LPSTR) lpszConversationID ! conversation thread ID
integer flFlags ! unread,return receipt
integer(LPVOID) lpOriginator ! Originator descriptor
integer nRecipCount ! Number of recipients
integer(LPVOID)lpRecips ! Recipient descriptors
integer nFileCount ! # of file attachments
integer(LPVOID) lpFiles ! Attachment descriptors
end type T_MapiMessage
This works fine and message structure can be populated OK.
The main problem next is to recover the list of recipients and the list of
files (which turns out to include the text of the mail message as a temporary file)
using the descriptor pointers.
What the MAPIMessage structure supplies is a pointer to a descriptor which, in the case of multiple
recipients and multiple files, is an array.
For recovering the list of recipients, what I have tried so far is the following:
type(t_MapiRecipDesc) Recipients(5)
integer lprecips
pointer(lprecips, Recipients)
...
character(100) Receiver
pointer(lpreceiver,Receiver)
!
type(t_MapiMessage) :: NewMsg
pointer(lppmessage,NewMsg)
!
character(3) chrecipcount, chfilecount, chir
...
iret = MAPIReadMail(hSession, 0, MsgID, MAPI_BODY_AS_FILE, 0,lppmessage )
...
if(newmsg%lprecips.ne.0) then
if(newmsg%nrecipcount.gt.0) then
lprecips=newmsg%lprecips
do ir=1,newmsg%nrecipcount
write(chir,'(i3)') ir
lpreceiver=Recipients(ir)%lpszname
imess=MessageBox(0,trim(Receiver)//char(0),"Message Receiver no. "//chir//char(0),mb_ok)
end do
endif
endif
Note that I have dimensioned an array Recipients(5) not knowing how many actual recipients there may be
(theoretically I could make it larger than any likely list length, but this seems inefficient storage-wise)
and I use the simplest pointer that I know how to use.
This code works and I can list the recipients (and the file list using a similar dimensioning of an array).
Given that the following is not permitted according to the compiler:
type(t_MapiRecipDesc), allocatable :: Recipients(:)
integer lprecips
pointer(lprecips, Recipients)
what I am enquiring from the forum is whether there is a way of recovering the recipient array using array
allocation, having established the number of recipients using newmsg%nrecipcount ? (the same query
applies to recovering the list of files)
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For recovering the list of recipients, what I have tried so far is the following:
type(t_MapiRecipDesc) Recipients(5)
integer lprecips
pointer(lprecips, Recipients)
When you declare a (pointer, pointee) pair as above, the pointee array does not occupy any storage, thus does not waste any memory. You may declare it with a dimension of (1000000) without any consequences (as long as you don't access any undefined members). Thus, they're similar to assumed-size arguments, and indeed, there is the alternate, cleaner, syntax:
type(t_MapiRecipDesc) Recipients(*)
pointer(lprecips, Recipients)
which has an ugly side effect of not being able to watch all of them in the debugger.
These days, I prefer using F2003 C interoperability. With it, you would use a C pointer (type(C_PTR)) and convert it to a standard Fortran pointer to an array, like this:
type(t_MapiRecipDesc), pointer:: Recipients(:)
type(C_PTR):: recips
!Get the value of recips through somehow
...
!convert recips to Fortran pointer of given shape, similar to RESHAPE:
call C_F_POINTER(recips, Recipients, (/newmsg%nrecipcount/))
Alas, C interoperability does not play nice with IFWIN interfaces (which still use -- and will continue to -- DEC$ATTRIBUTES syntax). In particular, Intel does not support STDCALL + BIND(C) combination (for functions), so your portability in this area is somewhat limited.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
type(t_MapiRecipDesc) Recipients(*)
pointer(lprecips, Recipients)
The compiler likes it!
Regarding your alternative suggestion:
type(t_MapiRecipDesc), pointer:: Recipients(:)
type(C_PTR):: recips
!Get the value of recips through somehow
Getting the value of 'recips' is indeed the crux. Are you implying here that I cannot just use
the integer pointer recovered from the T_MAPIMessage structure?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Since we (i.e. you and I) have the control over MAPI.f90, we could have used
[bash]type T_MapiMessage ... integer nRecipCount ! Number of recipients type(C_PTR) lpRecips ! Recipient descriptors [/bash]
If not, we can use the fact that type(C_PTR) contains the integer pointer, so you can "cast" one to another using TRANSFER:
[bash]type T_MapiMessageor, in one line (though it's ugly:)
...
integer nRecipCount ! Number of recipients
integer(LPVOID) lpRecips ! Recipient descriptors
type(T_MAPIRecipDesc), pointer:: Recipients(:)
type(T_MAPIMessage):: msg
type(C_PTR):: cptr
...
ptr = TRANSFER(msg%lpRecips, cptr)
call C_F_POINTER(cptr, Recipients, [msg%nRecipCount])
[/bash]
[bash]call C_F_POINTER(TRANSFER(msg%lpRecips, cptr), Recipients, [msg%nRecipCount])[/bash]It's more or less a style choice. I generally prefer standard solutions (C interoperability), but they are 1) a bit more verbose 2) not applicable all the way (because you cannot use both STDCALL and BIND(C)) and 3) Not applied by Intel in IFWIN modules, so we're forced to do mixed-style anyway.
![](/skins/images/06022F5BB6D2F28C8F102671A0F06E85/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page